105-ESP32_SDK开发-串口,485通信
<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnESP32" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
说明
模块有3个串口,每个串口管脚可以设置到任意的gpio上
模组出厂默认使用GPIO1,GPIO3作为串口0引脚(日志打印); GPIO17,GPIO16作为串口1引脚(AT指令)
开发板上也把串口1连接了485上.
说明2
每个串口都有一个128字节的FIFO缓存区,知道这个就可以.
设置串口1,带接收缓存,不带发送缓存区的方式(最简洁的方式)
设置GPIO17,GPIO16作为串口1引脚.
没有设置发送缓存,调用 uart_write_bytes 发送数据的时候是阻塞的.
#include <stdio.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gpio.h" #include "driver/timer.h" #include "esp_timer.h" #include "driver/uart.h" #define TXD1_PIN (GPIO_NUM_17) //串口1的发送数据引脚 #define RXD1_PIN (GPIO_NUM_16) //串口1的接收数据引脚 #define BUF_SIZE (1024) //接收数据缓存大小,该大小需要大于内部FIFO大小:UART_FIFO_LEN(128) /*串口任务*/ static void uart_task(void *arg) { /*配置串口参数*/ uart_config_t uart_config = { .baud_rate = 115200,//波特率 .data_bits = UART_DATA_8_BITS,//数据位8位 .parity = UART_PARITY_DISABLE,//无奇偶校验 .stop_bits = UART_STOP_BITS_1,//停止位1位 .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,//不使用硬件流控 .source_clk = UART_SCLK_APB,//串口使用的时钟 }; /*初始化串口1*/ uart_driver_install(UART_NUM_1, BUF_SIZE, //串口1接收缓存大小 0, //不使用发送缓存(发送数据的时候便会阻塞发送) 0, //队列大小为0;没有使用freertos内部缓存管理 NULL, //不使用QueueHandle_t 内部缓存管理,设置为空 0 //设置串口中断优先级,设置为0意味着让系统从1-3级中自动选择一个 ); /*设置串口参数*/ uart_param_config(UART_NUM_1, &uart_config); /*设置串口的TX,RX,RTS,DTR引脚*/ //不使用RTS,DTR uart_set_pin(UART_NUM_1, TXD1_PIN, RXD1_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); /*申请一块内存,用于临时存储接收的数据*/ uint8_t *data = (uint8_t *) malloc(BUF_SIZE); while (1) { //接收串口数据 //每隔10ms判断一次,可以写成portMAX_DELAY(一直判断) int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 10 / portTICK_RATE_MS); //把接收的数据发送出去 uart_write_bytes(UART_NUM_1, (const char *) data, len); } } void app_main(void) { xTaskCreate(uart_task, "uart_task", 2048, NULL, 10, NULL); }
下载程序到开发板以后可以通过串口测试
485接口默认连接串口1,也可以使用485进行通讯
发送什么数据将会返回什么数据
设置串口1,带接收缓存,带发送缓存区的方式
设置上发送缓存区以后,调用 uart_write_bytes 发送数据的时候,将不会阻塞在那里.
设置串口1,带接收缓存,带发送缓存区,并使用上freertos内部的缓存管理的方式
加上缓存管理
从缓存管理中获取数据
#include <stdio.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gpio.h" #include "driver/timer.h" #include "esp_timer.h" #include "driver/uart.h" #define TXD1_PIN (GPIO_NUM_17) //串口1的发送数据引脚 #define RXD1_PIN (GPIO_NUM_16) //串口1的接收数据引脚 #define BUF_SIZE (1024) //接收数据缓存大小,该大小需要大于内部FIFO大小:UART_FIFO_LEN(128) #define BUF_SEND_SIZE (1024) //发送数据缓存大小,该大小需要大于内部FIFO大小:UART_FIFO_LEN(128) static QueueHandle_t QueueHandle_t_uart1; /*串口任务*/ static void uart_task(void *arg) { /*配置串口参数*/ uart_config_t uart_config = { .baud_rate = 115200,//波特率 .data_bits = UART_DATA_8_BITS,//数据位8位 .parity = UART_PARITY_DISABLE,//无奇偶校验 .stop_bits = UART_STOP_BITS_1,//停止位1位 .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,//不使用硬件流控 .source_clk = UART_SCLK_APB,//串口使用的时钟 }; /*初始化串口1*/ uart_driver_install(UART_NUM_1, BUF_SIZE, //串口1接收缓存大小 BUF_SEND_SIZE, //串口1发送缓存大小 10, //队列大小为10 &QueueHandle_t_uart1, //缓存管理 0 //设置串口中断优先级,设置为0意味着让系统从1-3级中自动选择一个 ); /*设置串口参数*/ uart_param_config(UART_NUM_1, &uart_config); /*设置串口的TX,RX,RTS,DTR引脚*/ //不使用RTS,DTR uart_set_pin(UART_NUM_1, TXD1_PIN, RXD1_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); /*申请一块内存,用于临时存储接收的数据*/ uint8_t *data = (uint8_t *) malloc(BUF_SIZE); uart_event_t event; while (1) { if(xQueueReceive(QueueHandle_t_uart1, (void * )&event, portMAX_DELAY)) { switch(event.type) { case UART_DATA://接收到数据 //读取接收的数据 uart_read_bytes(UART_NUM_1, data, event.size, portMAX_DELAY); //返回接收的数据 uart_write_bytes(UART_NUM_1, (const char*) data, event.size); break; case UART_FIFO_OVF://FIFO溢出(建议加上数据流控制) uart_flush_input(UART_NUM_1); xQueueReset(QueueHandle_t_uart1); break; case UART_BUFFER_FULL://接收缓存满(建议加大缓存 BUF_SIZE) uart_flush_input(UART_NUM_1); xQueueReset(QueueHandle_t_uart1); break; case UART_BREAK://检测到接收数据中断 break; case UART_PARITY_ERR://数据校验错误 break; case UART_FRAME_ERR://数据帧错误 break; case UART_PATTERN_DET://接收到相匹配的字符(没用到) break; default: break; } } } free(data); data = NULL; vTaskDelete(NULL); } void app_main(void) { xTaskCreate(uart_task, "uart_task", 2048, NULL, 10, NULL); }
如果想配置串口0或者串口2
把以下变量的最后一个数字改为0或者2即可
关于模式匹配和485方向控制,参考
https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/uart.html?highlight=uart_pattern_det#
官方文档