首先,我们先来看下peripheral_main.c文件:
#if(defined(DCDC_ENABLE)) && (DCDC_ENABLE == TRUE) PWR_DCDCCfg(ENABLE); #endif
这段代码是灰色的,说明没有调用,如果想要降低功耗,可以在config.h文件将DCDC_ENABLE设置为TRUE,开启DCDC功能,可以起到降低功耗的作用。
注意点:开启DCDC,电源电路中VSW上的22uH电感必须要接,不开DCDC电感处短接即可。
22uH电感要求:直流电阻2Ω以内,额定电流大于100mA。EVT板使用电感型号:YNR2016-220M
SetSysClock(CLK_SOURCE_PLL_60MHz);
设置系统主频为60M,跑蓝牙一般建议使用例程中60M,最低不要低于48M。
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE) GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU); GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU); #endif
这段代码也是灰色的,没有调用,如果想要开启睡眠降低功耗,可以在config.h文件将HAL_SLEEP设置为TRUE,开启睡眠功能。
睡眠逻辑:睡眠时间有协议栈控制,根据tmos任务进行睡眠和跑任务交替,从而降低功耗。
#ifdef DEBUG GPIOA_SetBits(bTXD1); GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA); UART1_DefInit(); #endif
这段代码是串口打印的初始化,在预编译中定义了DEBUG为1,那就是使用串口1打印,在预编译中更改DEBUG宏和更改打印串口可参考下方链接:
1.MounRiver工程配置讲解一(添加全局宏定义) - WCH蓝牙应用分享 - 博客园 (cnblogs.com)
2.CH573 CH582 CH579外设UART例程讲解(更改打印串口) - WCH蓝牙应用分享 - 博客园 (cnblogs.com)
PRINT("%s\n", VER_LIB); CH58X_BLEInit();
这段代码是打印库的版本号和蓝牙库初始化。我们来看看库初始化哪些内容:
void CH58X_BLEInit(void) { uint8_t i; bleConfig_t cfg; if(tmos_memcmp(VER_LIB, VER_FILE, strlen(VER_FILE)) == FALSE) { PRINT("head file error...\n"); while(1); } SysTick_Config(SysTick_LOAD_RELOAD_Msk); PFIC_DisableIRQ(SysTick_IRQn); tmos_memset(&cfg, 0, sizeof(bleConfig_t)); cfg.MEMAddr = (uint32_t)MEM_BUF; cfg.MEMLen = (uint32_t)BLE_MEMHEAP_SIZE; cfg.BufMaxLen = (uint32_t)BLE_BUFF_MAX_LEN; cfg.BufNumber = (uint32_t)BLE_BUFF_NUM; cfg.TxNumEvent = (uint32_t)BLE_TX_NUM_EVENT; cfg.TxPower = (uint32_t)BLE_TX_POWER; #if(defined(BLE_SNV)) && (BLE_SNV == TRUE) cfg.SNVAddr = (uint32_t)BLE_SNV_ADDR; cfg.readFlashCB = Lib_Read_Flash; cfg.writeFlashCB = Lib_Write_Flash; #endif #if(CLK_OSC32K) cfg.SelRTCClock = (uint32_t)CLK_OSC32K; #endif cfg.ConnectNumber = (PERIPHERAL_MAX_CONNECTION & 3) | (CENTRAL_MAX_CONNECTION << 2); cfg.srandCB = SYS_GetSysTickCnt; #if(defined TEM_SAMPLE) && (TEM_SAMPLE == TRUE) cfg.tsCB = HAL_GetInterTempValue; // 根据温度变化校准RF和内部RC( 大于7摄氏度 ) #if(CLK_OSC32K) cfg.rcCB = Lib_Calibration_LSI; // 内部32K时钟校准 #endif #endif #if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE) cfg.WakeUpTime = WAKE_UP_RTC_MAX_TIME; cfg.sleepCB = CH58X_LowPower; // 启用睡眠 #endif #if(defined(BLE_MAC)) && (BLE_MAC == TRUE) for(i = 0; i < 6; i++) { cfg.MacAddr[i] = MacAddr[5 - i]; } #else { uint8_t MacAddr[6]; GetMACAddress(MacAddr); for(i = 0; i < 6; i++) { cfg.MacAddr[i] = MacAddr[i]; // 使用芯片mac地址 } } #endif if(!cfg.MEMAddr || cfg.MEMLen < 4 * 1024) { while(1); } i = BLE_LibInit(&cfg); if(i) { PRINT("LIB init error code: %x ...\n", i); while(1); } }
这里面的诸多参数都是在config.h中定义的,可在config.h中查看注释,
【MAC】 BLE_MAC - 是否自定义蓝牙Mac地址 ( 默认:FALSE - 使用芯片Mac地址 ),需要在main.c修改Mac地址定义 【DCDC】 DCDC_ENABLE - 是否使能DCDC ( 默认:FALSE ) 【SLEEP】 HAL_SLEEP - 是否开启睡眠功能 ( 默认:FALSE ) SLEEP_RTC_MIN_TIME - 非空闲模式下睡眠的最小时间(单位:625us) WAKE_UP_RTC_MAX_TIME - 等待32M晶振稳定时间(单位:625us) 根据不同睡眠类型取值可分为: 睡眠模式/下电模式 - 45(默认) 暂停模式 - 45 空闲模式 - 5 【TEMPERATION】 TEM_SAMPLE - 是否打开根据温度变化校准的功能,单次校准耗时小于10ms( 默认:TRUE ) 【CALIBRATION】 BLE_CALIBRATION_ENABLE - 是否打开定时校准的功能,单次校准耗时小于10ms( 默认:TRUE ) BLE_CALIBRATION_PERIOD - 定时校准的周期,单位ms( 默认:120000 ) 【SNV】 BLE_SNV - 是否开启SNV功能,用于储存绑定信息( 默认:TRUE ) BLE_SNV_ADDR - SNV信息保存地址,使用data flash最后( 默认:0x77E00 ) - 如果配置了SNVNum参数,则需要对应修改Lib_Write_Flash函数内擦除的flash大小,大小为SNVBlock*SNVNum 【RTC】 CLK_OSC32K - RTC时钟选择,如包含主机角色必须使用外部32K( 0 外部(32768Hz),默认:1:内部(32000Hz),2:内部(32768Hz) ) 【MEMORY】 BLE_MEMHEAP_SIZE - 蓝牙协议栈使用的RAM大小,不小于6K ( 默认:(1024*6) ) 【DATA】 BLE_BUFF_MAX_LEN - 单个连接最大包长度( 默认:27 (ATT_MTU=23),取值范围[27~516] ) BLE_BUFF_NUM - 控制器缓存的包数量( 默认:5 ) BLE_TX_NUM_EVENT - 单个连接事件最多可以发多少个数据包( 默认:1 ) BLE_TX_POWER - 发射功率( 默认:LL_TX_POWEER_0_DBM (0dBm) ) 【MULTICONN】 PERIPHERAL_MAX_CONNECTION - 最多可同时做多少从机角色( 默认:1 ) CENTRAL_MAX_CONNECTION - 最多可同时做多少主机角色( 默认:3 )
一般建议是在预编译中添加修改,防止很多工程使用一个公共文件的时候,你去修改这个宏定义,就会导致所有工程都会跟着改变,且新增文件夹时会出现头文件忘记包含.h
HAL_Init();
这段代码是硬件初始化。我们来看看初始化哪些内容:
void HAL_Init() { halTaskID = TMOS_ProcessEventRegister(HAL_ProcessEvent); HAL_TimeInit(); #if(defined HAL_SLEEP) && (HAL_SLEEP == TRUE) HAL_SleepInit(); #endif #if(defined HAL_LED) && (HAL_LED == TRUE) HAL_LedInit(); #endif #if(defined HAL_KEY) && (HAL_KEY == TRUE) HAL_KeyInit(); #endif #if(defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE) tmos_start_task(halTaskID, HAL_REG_INIT_EVENT, MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD)); // 添加校准任务,单次校准耗时小于10ms #endif // tmos_start_task( halTaskID, HAL_TEST_EVENT, 1600 ); // 添加一个测试任务 }
1.注册一个taskid,2.硬件时间初始化,3.如果使用SLEEP,LED,KEY同样也会初始化,4.开启校准任务,5.测试任务,开启后会1s打印一次 * 号。
tmos任务参考链接:
GAPRole_PeripheralInit();
这段代码是GAP初始化,按照例程调用就行了。
Peripheral_Init();
这段是外设初始化,我们来看看初始化哪些内容:
void Peripheral_Init() { Peripheral_TaskID = TMOS_ProcessEventRegister(Peripheral_ProcessEvent); // Setup the GAP Peripheral Role Profile { uint8_t initial_advertising_enable = TRUE; uint16_t desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; uint16_t desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; // Set the GAP Role Parameters GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable); GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData); GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData); GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desired_min_interval); GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desired_max_interval); } // Set the GAP Characteristics GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName); { uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL; // Set advertising interval GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt); GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt); // Enable scan req notify GAP_SetParamValue(TGAP_ADV_SCAN_REQ_NOTIFY, ENABLE); } // Setup the GAP Bond Manager { uint32_t passkey = 0; // passkey "000000" uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; uint8_t mitm = TRUE; uint8_t bonding = TRUE; uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey); GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode); GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm); GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap); GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding); } // Initialize GATT attributes GGS_AddService(GATT_ALL_SERVICES); // GAP GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes DevInfo_AddService(); // Device Information Service SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile // Setup the SimpleProfile Characteristic Values { uint8_t charValue1[SIMPLEPROFILE_CHAR1_LEN] = {1}; uint8_t charValue2[SIMPLEPROFILE_CHAR2_LEN] = {2}; uint8_t charValue3[SIMPLEPROFILE_CHAR3_LEN] = {3}; uint8_t charValue4[SIMPLEPROFILE_CHAR4_LEN] = {4}; uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = {1, 2, 3, 4, 5}; SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, charValue1); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, charValue2); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, SIMPLEPROFILE_CHAR3_LEN, charValue3); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, SIMPLEPROFILE_CHAR4_LEN, charValue4); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5); } // Init Connection Item peripheralInitConnItem(&peripheralConnList); // Register callback with SimpleGATTprofile SimpleProfile_RegisterAppCBs(&Peripheral_SimpleProfileCBs); // Register receive scan request callback GAPRole_BroadcasterSetCB(&Broadcaster_BroadcasterCBs); // Setup a delayed profile startup tmos_set_event(Peripheral_TaskID, SBP_START_DEVICE_EVT); }
1.注册一个taskid,2.开启广播,3.配置广播内容,扫描应答包内容,连接间隔,4.
Main_Circulation();
这段代码是主循环,用来查询tmos进程。
__HIGH_CODE __attribute__((noinline)) void Main_Circulation() { while(1) { TMOS_SystemProcess(); } }
此函数上的修饰是将函数放到RAM中跑,运行速度较快,能够更快的查询,主循环中不可以添加延时函数或处理代码时间过长,可添加一些轮询的代码。