蓝牙4.0BLE协议栈中串口应用详解

发布于:2025-03-10 ⋅ 阅读:(18) ⋅ 点赞:(0)

蓝牙4.0 BLE协议栈中的串口应用,就像是开发板和电脑之间的一座桥梁,承载着数据交互的重要任务。下面我们将通过生动的比喻,结合代码解读、原理说明以及时序图和流程图,深入理解这部分内容。

串口:数据交互的信使

串口作为开发板和电脑交互的工具,就如同古代传递书信的信使。初始化串口的过程,就像是为信使规划好传递信件的路线和方式,设置波特率如同确定信使的行进速度,中断设置则像是为信使安排的紧急联络机制。而向发送缓冲区发送数据或从接收缓冲区读取数据,就好比将信件放入邮筒或者从邮筒中取出信件。

蓝牙4.0 BLE协议栈:信使的调度中心

在蓝牙4.0 BLE协议栈中,串口的使用有了独特的方式,就如同信使加入了一个专业的调度中心。协议栈提供的三个关键函数HalUARTOpen()、HalUARTRead()、HalUARTWrite(),分别承担着打开通道、读取信件内容、发送信件的职责。

串口收发实验:信使的工作演练

以SimpleBLEPeripheral示例工程为基础的串口收发实验,就像是信使的一场工作演练。

  • 代码解读
    • 在“SimpleBLEPeripheral.c”文件中添加的代码,首先定义了一个数组uartbuf用于存储接收到的数据,就像准备了一个专门的信件收纳袋。rxCb函数作为回调函数,当有数据接收事件发生时,就会被调用,类似于信使收到新信件时的响应机制。
    #include "hal_uart.h"
    unsigned char uartbuf[152] ;
    static void rxCb(uint8 port,uint8 event)
    {
    HalUARTRead(0, uartbuf,19) ;//从串口读取19个数据存到uartbuf数组,如同从邮筒取出信件放入收纳袋
    if(osal_memcmp(uartbuf,"BLE_stack_uart_test",19))//判断接收的数据是否是指定字符串
      {
      HalUARTWrite(0, uartbuf,19) ;//将接收到的数据再发送出去,如同将信件原封不动地转发
      osal_memset( uartbuf,0,19);//清空数组,为下一次接收做准备,如同清空收纳袋
      }
    }
    
    • SimpleBLEPeripheral_Init()函数中添加的代码,用于配置串口参数并打开串口。halUARTCfg_t结构体就像是调度中心的任务配置表,包含了串口初始化所需的各种参数,如是否已配置、波特率、流控等。
    halUARTCfg_t uartConfig;
    uartConfig.configured    = TRUE;
    uartConfig.baudRate     = HAL_UART_BR_115200;
    uartConfig.flowControl = FALSE;
    uartConfig.callBackFunc = rxCb ;
    HalUARTOpen (0, &uartConfig);//根据配置表打开串口通道,如同为信使开启工作路径
    
  • 回调函数揭秘:回调函数rxCb就像是信使的一个特殊任务指令。当特定的事件(如数据接收)发生时,系统会通过函数指针调用这个回调函数,就好比调度中心在特定情况下向信使下达特殊任务。定义和使用回调函数的过程如下:
    • 定义回调函数rxCb,编写数据接收和处理的逻辑。
    • 在初始化时,将rxCb函数的指针传递给uartConfigcallBackFunc成员,完成回调函数的注册,就像将任务指令交给调度中心备案。
    • 当数据接收事件发生,系统通过callBackFunc调用rxCb函数,执行相应操作。

实例测试:信使工作的检验

将程序编译下载到CC2540开发板并进行实例测试,就像是对信使工作的一次实际检验。当发现接收栏没有显示数据时,就如同信使在传递信件过程中出现了问题。经过排查发现,是因为蓝牙4.0 BLE协议栈的条件编译,没有正确开启UART功能,就好比没有为信使打开正确的工作通道。通过在IAR开发环境中定义HAL_UART=TRUE宏,就像是为信使打通了道路,从而使数据能够正常收发。

串口工作原理剖析:信使的工作机制

  • 串口初始化HalUARTOpen()函数就像是调度中心的总开关,根据不同的条件(如是否使用DMA、ISR等)调用不同的初始化函数,如HalUARTOpenDMA()。在HalUARTOpenDMA()函数中,对串口波特率的初始化就像是为信使设定行进速度,根据halUARTCfg_t结构体中baudRate的值,参考CC2540数据手册中的对应值,使用switch-case语句进行设置。同时,对DMA接收缓冲区的初始化,就像是为接收信件准备好仓库。
    static void HalUARTOpenDMA(halUARTCfg_t *config)
    {
    dmaCfg.uartCB = config->callBackFunc;
    if (config->baudRate == HAL_UART_BR_57600 ||
        config->baudRate == HAL_UART_BR_115200)
    {
        UxBAUD = 216;
    }
    else
    {
        UxBAUD = 59;
    }
    switch (config->baudRate)
    {
        case HAL_UART_BR_9600:
            UxGCR = 8;
            dmaCfg.txTick = 35;
            break;
        //其他波特率设置情况类似
    }
    dmaCfg.rxBuf[0] = *(volatile uint8 *)DMA_UDBUF;
    HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX);
    HAL_DMA_ARM_IRQ(HAL_DMA_CH_RX);
    HAL_DMA_ARM_CH(HAL_DMA_CH_RX);
    osal_memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF),HAL_UART_DMA_RX_MAX*2);
    }
    
  • 数据接收与发送:在数据接收时,数据首先存放在DMA接收缓冲区,HalUARTRead()函数实际上调用HalUARTReadDMA()函数从DMA缓冲区读取数据,就像是从仓库中取出信件进行处理。发送数据时,HalUARTWrite()函数调用HalUARTWriteDMA()函数将数据写入DMA发送缓冲区,然后DMA自动将数据通过串口发送给PC机,就像是将信件放入邮车进行发送。

时序图和流程图展示

  • 串口收发时序图
串口调试助手 开发板 DMA接收缓冲区 DMA发送缓冲区 发送数据 存储数据 调用HalUARTRead()读取数据 调用HalUARTWrite()写入数据 发送数据 串口调试助手 开发板 DMA接收缓冲区 DMA发送缓冲区

网站公告

今日签到

点亮在社区的每一天
去签到