esp32s3中使用串口中断事件消息队列的方式接收数据
在esp32芯片中接收串口数据有多种方式默认采用串口轮询读取方式效率低下通常像51或stm32基于中断的方式对于esp32这种与rtos深度融合的系统来说会降低系统的实时性所以可以采用freertos的事件上报的消息队列方式会提高系统的性能。使用串口1监听数据到来事件再立即读取缓冲区。#ifndef __BOARD_UART1_H__ #define __BOARD_UART1_H__ #include freertos/FreeRTOS.h #include freertos/task.h #include esp_system.h #include esp_log.h #include driver/uart.h #include string.h #include driver/gpio.h #include freertos/queue.h static const char *UART1_TAG uart1_events; #define RX_BUF_SIZE (1024) #define UART_NUM_1 (1) #define TXD_PIN (GPIO_NUM_17) #define RXD_PIN (GPIO_NUM_18) #define EX_UART_NUM UART_NUM_1 #define PATTERN_CHR_NUM (3) #define RD_BUF_SIZE (RX_BUF_SIZE) static QueueHandle_t uart1_queue; #define UART1_QUEUE_SIZE (30) /** * 枚举uart_event_type_t 环形缓冲区中使用的UART事件类型。值 UART_DATA UART数据事件 UART_BREAK UART中断事件 UART_BUFFER_FULL UART RX缓冲区已满事件 UART_FIFO_OVF UART FIFO溢出事件 UART_FRAME_ERR UART RX帧错误事件 UART_PARITY_ERR UART RX奇偶校验事件 UART_DATA_BREAK UART TX数据和中断事件 UART_PATTERN_DET 检测到UART模式 UART_EVENT_MAX UART事件最大索引 */ static inline void uart1_init(void) { const uart_config_t uart_config { .baud_rate 115200, .data_bits UART_DATA_8_BITS, .parity UART_PARITY_DISABLE, .stop_bits UART_STOP_BITS_1, .flow_ctrl UART_HW_FLOWCTRL_DISABLE, .source_clk UART_SCLK_DEFAULT, }; uart_driver_install(EX_UART_NUM, RX_BUF_SIZE * 2, 0,UART1_QUEUE_SIZE,uart1_queue, 0); uart_param_config(EX_UART_NUM, uart_config); uart_set_pin(EX_UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); //Set uart pattern detect function. uart_enable_pattern_det_baud_intr(EX_UART_NUM, , PATTERN_CHR_NUM, 9, 0, 0); //Reset the pattern queue length to record at most 20 pattern positions. uart_pattern_queue_reset(EX_UART_NUM, UART1_QUEUE_SIZE); } static inline void uart1_send(unsigned char*data,int len) { int offset 0; int txbytes 0; while(len 0) { txbytes uart_write_bytes(EX_UART_NUM, data offset, len); offset txbytes; len - txbytes; } } #endif /////////////////////////////////////////////////////////////////事件队列任务static void uart1_event_task(void *pvParameters) { uart_event_t event; size_t buffered_size; uint8_t* dtmp (uint8_t*) malloc(RD_BUF_SIZE); for(;;) { //Waiting for UART event. if(xQueueReceive(uart1_queue, (void * )event, (TickType_t)portMAX_DELAY)) { //bzero(dtmp, RD_BUF_SIZE); //ESP_LOGI(UART1_TAG, uart[%d] event:, EX_UART_NUM); switch(event.type) { //Event of UART receving data /*Wed better handler data event fast, there would be much more data events than other types of events. If we take too much time on data event, the queue might be full.*/ case UART_DATA: //ESP_LOGI(UART1_TAG, [UART DATA]: %d, event.size); uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY); //ESP_LOGI(UART1_TAG, [DATA EVT]:); //uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size); print0x(dtmp,event.size); break; //Event of HW FIFO overflow detected case UART_FIFO_OVF: ESP_LOGI(UART1_TAG, hw fifo overflow); // If fifo overflow happened, you should consider adding flow control for your application. // The ISR has already reset the rx FIFO, // As an example, we directly flush the rx buffer here in order to read more data. uart_flush_input(EX_UART_NUM); xQueueReset(uart1_queue); break; //Event of UART ring buffer full case UART_BUFFER_FULL: ESP_LOGI(UART1_TAG, ring buffer full); // If buffer full happened, you should consider increasing your buffer size // As an example, we directly flush the rx buffer here in order to read more data. uart_flush_input(EX_UART_NUM); xQueueReset(uart1_queue); break; //Event of UART RX break detected case UART_BREAK: ESP_LOGI(UART1_TAG, uart rx break); break; //Event of UART parity check error case UART_PARITY_ERR: ESP_LOGI(UART1_TAG, uart parity error); break; //Event of UART frame error case UART_FRAME_ERR: ESP_LOGI(UART1_TAG, uart frame error); break; //UART_PATTERN_DET case UART_PATTERN_DET: uart_get_buffered_data_len(EX_UART_NUM, buffered_size); int pos uart_pattern_pop_pos(EX_UART_NUM); ESP_LOGI(UART1_TAG, [UART PATTERN DETECTED] pos: %d, buffered size: %d, pos, buffered_size); if (pos -1) { // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not // record the position. We should set a larger queue size. // As an example, we directly flush the rx buffer here. uart_flush_input(EX_UART_NUM); } else { uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS); uint8_t pat[PATTERN_CHR_NUM 1]; memset(pat, 0, sizeof(pat)); uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS); ESP_LOGI(UART1_TAG, read data: %s, dtmp); ESP_LOGI(UART1_TAG, read pat : %s, pat); } break; //Others default: ESP_LOGI(UART1_TAG, uart event type: %d, event.type); break; } } } free(dtmp); dtmp NULL; vTaskDelete(NULL); } xTaskCreate(uart1_event_task, uart1_event_task, 4096, NULL, UART1_EVENT_TASK_PRIORITY, NULL);