【WCH蓝牙系列芯片】-基于CH592发板—蓝牙主机移植的BLE_UART的串口收发程序
------------------------------------------------------------------------------------------------------------------------------------
参考BLE_UART蓝牙串口透传例程中的串口收发功能,将串口收发功能移植到蓝牙主机上。
第一、先将BLE_UART中的环形FIFO(先进先出)缓冲区的程序复制移植到主机中,app_drv_fifo是用于管理串口数据的临时存储和读取,并且相对应的路径。

第二、建立app_uart.c和app_uart.h文件

在app_uart.c中移植BLE_UART中的串口初始化,和串口中断处理的部分已经串口发送和串口接收处理函数
//串口发送和接收处理函数 void app_uart_process(void) { UINT32 irq_status; // 定义变量用于保存中断状态 SYS_DisableAllIrq(&irq_status); // 禁用所有中断,并保存当前中断状态 if(uart_rx_flag) // 检查是否有串口接收数据 { PRINT("UART_GET\n"); // 打印提示信息 tmos_start_task(centralTaskId, UART_TO_BLE_SEND_EVT, 2); // 启动任务,将串口接收的数据发送到蓝牙 uart_rx_flag = false; // 清除接收标志位 } SYS_RecoverIrq(irq_status); // 恢复之前保存的中断状态 //tx process 发送处理 if(R8_UART3_TFC < UART_FIFO_SIZE) // 检查串口发送FIFO是否未满 { app_drv_fifo_read_to_same_addr(&app_uart_tx_fifo, (uint8_t *)&R8_UART3_THR, UART_FIFO_SIZE - R8_UART3_TFC); // 从发送FIFO中读取数据到串口发送寄存器 } } //串口初始化 void app_uart_init() { // 初始化发送FIFO和接收FIFO // FIFO的缓冲区长度必须是2的幂 app_drv_fifo_init(&app_uart_tx_fifo, app_uart_tx_buffer, APP_UART_TX_BUFFER_LENGTH); // 初始化发送FIFO app_drv_fifo_init(&app_uart_rx_fifo, app_uart_rx_buffer, APP_UART_RX_BUFFER_LENGTH); // 初始化接收FIFO // 配置UART发送引脚(TXD3) GPIOA_SetBits(bTXD3); // 设置GPIOA的TXD3引脚为高电平 GPIOA_ModeCfg(bTXD3, GPIO_ModeOut_PP_5mA); // 配置TXD3引脚为推挽输出模式,电流为5mA // 配置UART接收引脚(RXD3) GPIOA_SetBits(bRXD3); // 设置GPIOA的RXD3引脚为高电平 GPIOA_ModeCfg(bRXD3, GPIO_ModeIN_PU); // 配置RXD3引脚为输入模式,带上拉电阻 // 初始化UART3 UART3_DefInit(); // 调用默认的UART3初始化函数,设置波特率、数据位、停止位等参数 // 使能中断 UART3_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT); // 使能接收准备中断和线路状态中断 PFIC_EnableIRQ(UART3_IRQn); // 使能UART3中断 } void app_uart_tx_data(uint8_t *data, uint16_t length) { uint16_t write_length = length; // 用于记录实际写入FIFO的数据长度 app_drv_fifo_write(&app_uart_tx_fifo, data, &write_length); // 将数据写入发送FIFO } //Not every uart reception will end with a UART_II_RECV_TOUT //UART_II_RECV_TOUT can only be triggered when R8_UARTx_RFC is not 0 //Here we cannot rely UART_II_RECV_TOUT as the end of a uart reception // UART3中断处理函数 __attribute__((interrupt("WCH-Interrupt-fast"))) __attribute__((section(".highcode"))) void UART3_IRQHandler(void) { uint16_t error; // 用于存储错误信息 // 根据UART3的中断标志判断中断类型 switch(UART3_GetITFlag()) { case UART_II_LINE_STAT: // 线路状态中断 UART3_GetLinSTA(); // 获取线路状态信息 break; case UART_II_RECV_RDY: // 接收到数据中断 case UART_II_RECV_TOUT: // 接收超时中断 // 将接收到的数据写入接收FIFO error = app_drv_fifo_write_from_same_addr(&app_uart_rx_fifo, (uint8_t *)&R8_UART3_RBR, R8_UART3_RFC); if(error != APP_DRV_FIFO_RESULT_SUCCESS) // 如果写入失败 { // FIFO已满,将数据写入FIFO黑洞 for(uint8_t i = 0; i < R8_UART3_RFC; i++) { for_uart_rx_black_hole = R8_UART3_RBR; } } uart_rx_flag = true; // 设置接收标志位 break; case UART_II_THR_EMPTY: // 发送缓冲区为空中断 break; case UART_II_MODEM_CHG: // 调制解调器状态变化中断 break; default: // 其他中断类型 break; } }
第三、在主机程序中, 添加UART_TO_BLE_SEND_EVT的事件任务,这个也可以按照BLE_BLE中进行复制。

并定义一个枚举类型,用于表示发送到蓝牙(BLE)的不同状态

在central.h中,进行UART_TO_BLE_SEND_EVT的任务注册定

第四、将主机程序中,将static uint8_t centralTaskId改为uint8_t centralTaskId; 初始化定义任务ID
static 关键字表示该变量的作用域仅限于当前文件,不会被其他文件直接访问, 但是在app.uart程序中有使用任务ID,所以需要将centralTaskId在central.h声明一下。


第五, 到这个一步,基本上移植串口都已经完成,现在就是要处理串口接收和串口发送数据的处理
得在主机程序中的,接收notify数据的地方,将接收发数据,通过调用 on_bleuartServiceEvt 函数,传入BLE连接句柄 centralConnHandle 和指向 evt 的指针。将数据发送到UART

在TMOS任务中,UART_TO_BLE_SEND_EVT任务中进行蓝牙发送数据,先回判断是否notify通知是否准备好。,如果没有连接到对应的notify的handle值,就会清空接收的FIFO

然后会判断FIFO长度,调用 app_drv_fifo_read 函数从FIFO中读取数据。读取的数据将被存储在 to_test_buffer 指向的缓冲区中

在FIFo读取到数据之后, 会先读取到FIFO的数据长度,分配一个内存,内存分配成功之后。
将从FIFO中读取的to_test_buffer数据复制到分配的内存noti.pValue。
调用 ble_uart_notify 函数发送BLE通知
如果BLE通知发送失败,会释放之前申请的内存,重新启动任务,但是如果发送成功,会重置读取到长度。
内存分配失败之后,重新重启任务。

如果是发送失败的情况下,会进入到case SEND_TO_BLE_SEND_FAILED中,重新分配内存,重新从FIFO中读取的to_test_buffer数据复制到分配的内存noti.pValue。然后再进行发送蓝牙BLE通知。

将串口TX发送来的数据,先中断接收后,uart_rx_flag串口接收标志位为1后,启动UART_TO_BLE_SEND_EVT任务,在TMOS任务中,将存放串口数据的数组to_test_buffer,通过tmos_memcpy(req.pValue, to_test_buffer, req.len); 将串口数据复制到req.pValue之后,蓝牙发送这个req.pValue数组值。

UART_TO_BLE_SEND_EVT任务事件中,将串口发送的数据,在这个任务中打印出出来,做验证,

浙公网安备 33010602011771号