【WCH蓝牙系列芯片】-基于CH592开发板—BLE_UART程序中,不连接状态下串口数据接收
------------------------------------------------------------------------------------------------------------------------------------


但是,有的时候,想要在蓝牙还没有连接之前,就想要通过串口发送自己的数据,等数据接收后,进行一系列处理数据之后,再开启蓝牙连接的操作。在这样的情况下,就是需要区分当前状态是否在蓝牙建立连接的状态。
如果是已经在蓝牙建立连接的状态,就走原来的BLE_UART的tmos_set_event(Peripheral_TaskID, UART_TO_BLE_SEND_EVT)事件任务。
如果当前状态是处于蓝牙断开连接的状态,就得需要通过超时判断机制识别一整包数据的结束,再一次性读取并打印。
在串口中断 UART3_IRQHandler 中,每次收到数据后重置超时TMOS任务事件,确保只有在指定时间内无新数据时,才认为一包数据结束:

在app_uart_process()函数中,通过if(peripheralConnList.connHandle != GAP_CONNHANDLE_INIT) 检查当前是否已经存在连接,建立连接之后,在执行UART_TO_BLE_SEND_EVT事件任务,进行蓝牙接收数据。

在添加void print_received_data(void)程序,读取接收串口中的数据长度,将数据从FIFO中读取出来。并且打印接收的每一个串口数据。
// 打印 接收到的数据 void print_received_data(void){ data_length = app_drv_fifo_length(&app_uart_rx_fifo); // 获取 FIFO 中的数据长度 PRINT("FIFO_LEN:%d\r\n", data_length); if (data_length > 0) // 如果接收到的数据长度大于0字节 { read_data_length = data_length; // 从 FIFO 中读取数据 app_drv_fifo_read(&app_uart_rx_fifo, buffer, &read_data_length); // 打印接收到的数据长度 PRINT("-------Received %u bytes: ", read_data_length); // 打印接收到的每个字节的数据 for (uint16_t i = 0; i < read_data_length; i++) { PRINT("%02X ", buffer[i]); // 将接收到的数据添加到环形缓冲区 enqueue(&uart_queue, buffer[i]); } PRINT("\r\n"); } }
然后处理串口数据包超时事件的任务接收。将接收串口数据打印的函数,放在UART_PACKET_TIMEOUT_EVT事件中。

通过串口来观察整个现象,在蓝牙无连接的情况下,除了打印串口数据,也会通过接收串口之后,发送到串口端,其中还利用环形缓冲区操作,每次从环形缓冲区读取并发送串口数据

在蓝牙连接的情况下的打印

在这部分程序中,讲解其中应用到环形缓冲区的方法:
// 定义一个环形队列结构体 typedef struct { uint8_t *buffer; // 环形缓冲区 uint16_t head; // 队列头指针 uint16_t tail; // 队列尾指针 uint16_t size; // 队列大小 } CircularQueue; // 初始化环形队列函数 void init_circular_queue(CircularQueue *queue, uint8_t *buffer, uint16_t size) { queue->buffer = buffer; // 将传入的缓冲区地址赋值给队列的 buffer 成员 queue->head = 0; // 初始化头指针为 0 queue->tail = 0; // 初始化尾指针为 0 queue->size = size; // 将传入的缓冲区大小赋值给队列的 size 成员 } // 入队操作函数 void enqueue(CircularQueue *queue, uint8_t data) { // 检查队列是否已满 // 当尾指针加 1 后等于头指针时,队列满 if ((queue->tail + 1) % queue->size != queue->head) { queue->buffer[queue->tail] = data; // 将数据存入尾指针指向的位置 queue->tail = (queue->tail + 1) % queue->size; // 尾指针后移一位 } else { PRINT("Queue is full!\n"); // 队列满,打印提示信息 } } // 出队操作函数 uint8_t dequeue(CircularQueue *queue) { // 检查队列是否为空 // 当头指针等于尾指针时,队列空 if (queue->head != queue->tail) { uint8_t data = queue->buffer[queue->head]; // 获取头指针指向的数据 queue->head = (queue->head + 1) % queue->size; // 头指针后移一位 return data; // 返回读取到的数据 } else { PRINT("Queue is empty!\n"); // 队列空,打印提示信息 return 0; // 返回 0(这里的 0 可能需要根据实际情况调整,作为错误值) } } // 定义缓冲区大小 #define BUFFER_SIZE BLE_BUFF_MAX_LEN - 4 - 3 // 定义缓冲区 uint8_t uart_buffer[BUFFER_SIZE]; // 定义环形队列 CircularQueue uart_queue;
在初始化中,添加初始化环形队列

在接收读取串口数据的时候,将数据进行入队列的操作,将数据添加到环形缓冲区中,

// 定时器中断或主循环中调用此函数 void send_data_via_uart() { // 检查环形缓冲区是否为空 if (uart_queue.head != uart_queue.tail) { // 计算当前缓冲区中的数据量 uint16_t data_count = (uart_queue.tail - uart_queue.head + uart_queue.size) % uart_queue.size; // 打印环形缓冲区中的数据长度 PRINT("--------Circular Queue Data Length---------: %d\r\n", data_count); // 定义一个临时缓冲区用于存储要发送的数据 uint8_t temp_buffer[data_count]; uint16_t bytes_to_send = data_count; // 从环形缓冲区读取数据到临时缓冲区 for (uint16_t i = 0; i < bytes_to_send; i++) { temp_buffer[i] = dequeue(&uart_queue); } // 打印从环形缓冲区读取的数据 PRINT("Data from Circular Queue: "); for (uint16_t i = 0; i < bytes_to_send; i++) { PRINT("%02X ", temp_buffer[i]); } PRINT("\r\n"); // 通过串口发送数据 UART3_SendString(temp_buffer, bytes_to_send); } }
然后写一个send_data_via_uart()函数,在发送数据的任务事件中,调用这个函数。

通过网盘分享的文件:5-基于CH592开发板—BLE_UART程序中,不连接状态下串口数据接收
链接: https://pan.baidu.com/s/1TVF4x75LHlxSVesiQwmcjQ 提取码: 6agf
--来自百度网盘超级会员v5的分享
浙公网安备 33010602011771号