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
                /*We'd 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);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值