当前位置 博文首页 > freemote的博客:【玩转esp32】12、esp32串口使用

    freemote的博客:【玩转esp32】12、esp32串口使用

    作者:[db:作者] 时间:2021-07-05 09:53

    系列文章:

    【玩转ESP32】1、开发环境搭建
    【玩转ESP32】2、开发参考资料
    【玩转ESP32】3、点亮LED,Blink,blink,blink
    【玩转ESP32】4、ESP32驱动DHT11
    【玩转ESP32】5、i2c-tools访问i2c设备
    【玩转ESP32】6、驱动i2c设备—0.96 OLED
    【玩转ESP32】7、ESP32连接wifi
    【玩转ESP32】8、ESP32 Guru MeditationError报错分析
    【玩转ESP32】9、ESP32 作为TCP客户端连接服务器(非阻塞接收)
    【玩转ESP32】10、创建用户分区表,数据读写存储
    【玩转ESP32】11、编译报错:esp_bt.h:No such file or directory

    1、esp32串口

    ESP32芯片有三个UART控制器(UART0, UART1UART2),其中UART0GPIO3用于U0RXDGPIO1用于U0TXD)用作下载、调试串口,引脚不可改变;
    在这里插入图片描述
    UART1UART2的引脚是可以设置的。
    UART1默认引脚是GPIO9用作U1RXDGPIO10用作U1TXD,但是这两个引脚也是用于外接flash的,因此在使用UART1的时候需要设置其他引脚;
    在这里插入图片描述
    UART2默认引脚是GPIO16用作U2RXDGPIO17用作U2TXD
    在这里插入图片描述

    2、API

    components/driver/include/driver/uart.h中可以查看api;
    在examples/peripherals/uart中也可以参考官方的各种串口例程。

    2.1、安装uart驱动

    esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t* uart_queue, int intr_alloc_flags);
    

    这里要注意参数:uart_queue属于freertos里面的队列句柄,在这里表示用于指示来自串口底层中断的队列消息。

    2.2、uart参数配置

    esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config);
    

    2.3、接收阈值设置

    esp_err_t uart_set_rx_full_threshold(uart_port_t uart_num, int threshold);
    

    2.4、串口引脚设置

    esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num);
    

    2.5、从接收缓冲区读取数据

    int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait);
    

    2.6、数据写入发送缓冲区

    int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size);
    

    3、代码实现

    3.1、参数定义

    #define EX_UART_NUM UART_NUM_1  //串口1
    
    #define TXD_PIN    (GPIO_NUM_17) //txd使用gpio17
    #define RXD_PIN    (GPIO_NUM_16) //rxd使用gpio16
    
    #define BUF_SIZE (128)   //缓冲区定义
    static QueueHandle_t uart_queue; //队列句柄
    static uint8_t  uartbuf[BUF_SIZE];
    

    3.2、串口初始化

    void uart_comm_init(void)
    {
        /* Configure parameters of an UART driver,
         * communication pins and install the driver */
        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_APB,
        };
        //Install UART driver, and get the queue.
        uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart_queue, 0);
        uart_param_config(EX_UART_NUM, &uart_config);
        uart_set_rx_full_threshold(EX_UART_NUM,126);
    
        //Set UART pins (using UART0 default pins ie no changes.)
        uart_set_pin(EX_UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    
        //Create a task to handler UART event from ISR
        xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL); //创建串口任务
    }
    

    3.3、串口任务函数

    static void uart_event_task(void *pvParameters)
    {
        uart_event_t event;
        for(;;) {
            //阻塞接收串口队列,
            //这个队列在底层发送,用户只需在应用层接收即可
            if(xQueueReceive(uart_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
                switch(event.type) {//各种串口事件
                    case UART_DATA:
                        ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                        uart_read_bytes(EX_UART_NUM, uartbuf, event.size, portMAX_DELAY); //阻塞接收
                        ESP_LOGI(TAG, "[DATA EVT]:");
                        uart_write_bytes(EX_UART_NUM, uartbuf, event.size);//原样发送
                        break;
                    //Event of HW FIFO overflow detected
                    case UART_FIFO_OVF: //硬件fifo溢出
                        ESP_LOGI(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(uart_queue);
                        break;
                    //Event of UART ring buffer full
                    case UART_BUFFER_FULL: //环形缓冲区满
                        ESP_LOGI(TAG, "ring buffer full");
                        // If buffer full happened, you should consider encreasing 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(uart_queue);
                        break;
                    //Event of UART RX break detected
                    case UART_BREAK:
                        ESP_LOGI(TAG, "uart rx break");
                        break;
                    //Event of UART parity check error
                    case UART_PARITY_ERR:
                        ESP_LOGI(TAG, "uart parity error");
                        break;
                    //Event of UART frame error
                    case UART_FRAME_ERR:
                        ESP_LOGI(TAG, "uart frame error");
                        break;
                    //UART_PATTERN_DET
                    case UART_PATTERN_DET:
                        break;
                    //Others
                    default:
                        ESP_LOGI(TAG, "uart event type: %d", event.type);
                        break;
                }
            }
        }
        vTaskDelete(NULL);
    }
    

    4、使用总结

    1. 初始化串口参数,(队列指针、缓冲区、引脚等);
    2. 任务中阻塞等待串口队里 。
    cs