CH32V208 BLE Peripheral例程详解

Peripheral

附件工程中有详细注释,建议搭配食用

基础知识

蓝牙【GATT】协议介绍

BLE技术知识点大全

低功耗蓝牙(BLE)你入门了吗

工程概述

该例程ble作为从机接受or发送数据

alt text
文件可分为以下几类:

  1. APP –有关应用的源文件和头文件均可放置于此,例程的 main 函数也在这里。
  2. HAL – 此文件夹中为 HAL 层的源代码与头文件,HAL 层即蓝牙协议栈与芯片硬件驱动交互层。
  3. LIB – 为低功耗蓝牙的协议栈库文件。
  4. obj — 编译器生成的文件,包括 map 文件与 hex 文件等。
  5. Profile – 该文件从包含 GAP 角色配置文件,GAP 安全配置文件和 GATT 配置文件的源代码与头文件,同时也包含 GATT 服务所需的头文件。详情请参考第 5 节。
  6. SRC — ch32库文件,debug,startup

LIB提供蓝牙的协议栈库文件
alt text
其中没有.c文件,沁恒在例程中将.hex烧录在指定的flash空间,对启动文件,链接文件进行了配置
wchble_rom.h,wchble.h存放了BLE库函数 声明 和 指针

函数解析

最好先读完 基础知识 ,了解必要的蓝牙协议栈知识

main

alt text

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

alt text

#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

此为重中之重,三言两语难以在文中解释清楚,请下载附件自行了解,以在其中详细注释。

附件

工程文件

posted @ 2024-05-28 21:56  卫龙的技术  阅读(750)  评论(0)    收藏  举报