CH32V208 BLE Peripheral例程详解
Peripheral
附件工程中有详细注释,建议搭配食用
基础知识
工程概述
该例程ble作为从机接受or发送数据
文件可分为以下几类:
- APP –有关应用的源文件和头文件均可放置于此,例程的 main 函数也在这里。
- HAL – 此文件夹中为 HAL 层的源代码与头文件,HAL 层即蓝牙协议栈与芯片硬件驱动交互层。
- LIB – 为低功耗蓝牙的协议栈库文件。
- obj — 编译器生成的文件,包括 map 文件与 hex 文件等。
- Profile – 该文件从包含 GAP 角色配置文件,GAP 安全配置文件和 GATT 配置文件的源代码与头文件,同时也包含 GATT 服务所需的头文件。详情请参考第 5 节。
- SRC — ch32库文件,debug,startup
LIB提供蓝牙的协议栈库文件
其中没有.c文件,沁恒在例程中将.hex烧录在指定的flash空间,对启动文件,链接文件进行了配置
wchble_rom.h,wchble.h存放了BLE库函数 声明 和 指针
函数解析
最好先读完 基础知识 ,了解必要的蓝牙协议栈知识
main
WCHBLE_Init(); //BLE 库初始化
HAL_Init(); //硬件初始化
GAPRole_PeripheralInit(); //Initialization function for the GAP Role Task.
Peripheral_Init(); //Initialization function for the Peripheral App Task.
Main_Circulation(); //主循环,运行TMOS系统任务处理函数
下面将对以上函数一一剖析
WCHBLE_Init
功能:
- 设置ble库版本
- 32M晶振匹配电容和电流
- BLE_LibInit
前面两个只需简单的函数即可完成,我们重点看 BLE_LibInit
bleConfig_t cfg;
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; //ble射频功率
#if(defined(BLE_SNV)) && (BLE_SNV == TRUE)
cfg.SNVAddr = (uint32_t)BLE_SNV_ADDR;
cfg.SNVNum = (uint32_t)BLE_SNV_NUM; //ble储存绑定信息flash地址
cfg.readFlashCB = Lib_Read_Flash; //读flash函数
cfg.writeFlashCB = Lib_Write_Flash; //写flash函数
#endif
cfg.ClockFrequency = CAB_LSIFQ/2; //时钟频率
#if(CLK_OSC32K==0)
cfg.ClockAccuracy = 50;
#else
cfg.ClockAccuracy = 1000;
#endif
cfg.ConnectNumber = (PERIPHERAL_MAX_CONNECTION & 3) | (CENTRAL_MAX_CONNECTION << 2); //可同时连接的从机,主机数量
cfg.BufMaxLen = BLE_BUFF_MAX_LEN;
#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.idleCB = BLE_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];
FLASH_GetMACAddress(MacAddr);
for(i = 0; i < 6; i++)
{
cfg.MacAddr[i] = MacAddr[i]; // 使用芯片mac地址,也可使用自定义的mac地址
}
}
#endif
if(!cfg.MEMAddr || cfg.MEMLen < 4 * 1024)
{
while(1);
}
i = BLE_LibInit(&cfg); //ble库初始化
if(i)
{
PRINT("LIB init error code: %x ...\n", i);
while(1);
}
从上面可以看出,BLE_LibInit主要初始化了BLE库的缓冲区,通信包,储存绑定信息,时钟频率和校准,以及用宏定义控制睡眠模式和mac地址
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, MS1_TO_SYSTEM_TIME(1000)); // 添加一个测试任务
}
首先,注册了回调是 HAL_ProcessEvent 的TMOS任务,条件编译控制睡眠,状态灯,按键,RTC校准的初始化
- 睡眠,外部中断 or RTC唤醒
- 状态灯,初始化开启定时任务,自定义闪烁
- 按键,初始化开启定时任务,在任务中读取键值
- RTC校准
tmosEvents HAL_ProcessEvent(tmosTaskID task_id, tmosEvents events)
{
uint8_t *msgPtr;
if(events & SYS_EVENT_MSG)
{ // 处理HAL层消息,调用tmos_msg_receive读取消息,处理完成后删除消息。
msgPtr = tmos_msg_receive(task_id);
if(msgPtr)
{
/* De-allocate */
tmos_msg_deallocate(msgPtr);
}
return events ^ SYS_EVENT_MSG;
}
if(events & LED_BLINK_EVENT)
{
#if(defined HAL_LED) && (HAL_LED == TRUE)
HalLedUpdate();
#endif // HAL_LED
return events ^ LED_BLINK_EVENT;
}
if(events & HAL_KEY_EVENT)
{
#if(defined HAL_KEY) && (HAL_KEY == TRUE)
HAL_KeyPoll(); /* Check for keys */
tmos_start_task(halTaskID, HAL_KEY_EVENT, MS1_TO_SYSTEM_TIME(100));
return events ^ HAL_KEY_EVENT;
#endif
}
if(events & HAL_REG_INIT_EVENT)
{
#if(defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE) // 校准任务,单次校准耗时小于10ms
BLE_RegInit(); // 校准RF
#if(CLK_OSC32K)
Lib_Calibration_LSI(); // 校准内部RC
#endif
tmos_start_task(halTaskID, HAL_REG_INIT_EVENT, MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD));
return events ^ HAL_REG_INIT_EVENT;
#endif
}
if(events & HAL_TEST_EVENT)
{
PRINT("* \n");
tmos_start_task(halTaskID, HAL_TEST_EVENT, MS1_TO_SYSTEM_TIME(1000));
return events ^ HAL_TEST_EVENT;
}
return 0;
}
GAPRole_PeripheralInit
#define BLE_LIB_JT(n) (*(uint32_t*)( FUNCITON_BASE_ADDRESSS+n*4 ))
ble库函数,沁恒在例程将 wchble_rom.hex 和 我们的应用程序的.hex分别烧录在flash里
wchble_rom.hex的flash起始地址是256KB
最大占用16K ram,实际在 WCHBLE_Init 仅分配了7K
Peripheral_Init
此为重中之重,三言两语难以在文中解释清楚,请下载附件自行了解,以在其中详细注释。
附件
本文来自博客园,作者:卫龙的技术,转载请注明原文链接:https://www.cnblogs.com/bky-Li/articles/18219022。
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
本博客之内容来源于网上收集以及相关技术人员提供,如有侵犯到您的权益,请与我联系。
本博客之内容乃分享,交流,学习,研究之目的,作者不对内容的真实性,有效性,及时性负责,也不对因本博客的任何内容导致的任何后果负责。
博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!