【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任务事件中,将串口发送的数据,在这个任务中打印出出来,做验证,

 

 

 

 

 

 

 

posted on 2025-05-30 17:28  凡仕  阅读(399)  评论(0)    收藏  举报