ESP32 串口使用笔记

仅记录一下对ESP32函数库里

uart_enable_pattern_det_intr  和 uart_enable_pattern_det_baud_intr的理解。

因为网上很多学习资料要么过时要么互相抄不深究,导致错了也不知道而误导人。

首先,按照官方的说法 uart_enable_pattern_det_intr  已经不推荐使用了。

应该使用 uart_enable_pattern_det_baud_intr。

二者的区别是在超时设定上的时间单位不一样。

uart_enable_pattern_det_intr 的时间单位为硬件的APB时钟,ESP32是 (80Mhz)。

uart_enable_pattern_det_baud_intr的时间单位为用户配置的波特率周期。后面理解参数后会知道这样其实更好用。

esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle)

uart_num  串口号

pattern_chr  关键字符,可以是单个字符也可以是字符串比如 “+++”,下面也以它为例

chr_num  关键字的重复次数

chr_tout 

关键字间隔时间,如果小于则不被认为是关键字。如果时间设置较大,比如大于一个字节时间则串口数据"+2+3+"也会被认为是关键字。这个时间设置成单字节周期就行,串口的话一个8位字节时间最少是8+2个周期,取10即可。有个别平台的是11个周期,停止位后多一个空闲周期。所以涉及到ESP32和单片机通讯的情况,一定要检查单片机的串口特性。

post_idle 

关键字触发后的有效时间,如果小于则不认为是最后一个关键字。如果有++++,则认为有4个+,不是关键字,如果时间设置较大,那+++后设置时间内务必不能再出现+,否则会认为是4个++++导致不触发中断,即该时间也等效于+++出现后中断触发延时的时间,因为它要等超时后才能确认关键字是否满足要求。防止乱码干扰,这个可以取稍微大一点,,n*10,n取决你打算留多少字节时间的量。

pre_idle

关键字触发前的间隔时间,如果小于则不认为是第一个关键字。这可以保证消息里如果出现了关键字符不会错误的触发中断。因为消息里的字节都是紧挨着发送的。这个时间也要设置的大一点。也是n*10个周期,n取决于 。如果是简单系统,串口数据都是一口气完整发送完的。但像ESP32或者更复杂的安卓系统,不排除串口发送被打断一下的情况。

老函数的时间参数取值范围是24位,新的是16位。

老的函数是用硬件时间计时,需要你自己计算。新的函数用串口周期计时,方便用户。从函数原型看,新函数和老的基本一样,函数内部取了波特率和周期帮你算了而已。

关键字这个功能,其实更稳妥的做法应该是用头字+尾字+转移符这样的方式。但这个功能软件实现要比单片机寄存器配置实现容易些。寄存器配置就只能是简单对比,然后在时间上想办法以实现判断和排它。

所以这里关于超时的设置逻辑都是按照如何实现同样功能的角度去思考来的。毕竟我英语太烂,看了英文的注释也不确定是不是100%理解对了。

具体理解的对不对,还需要测试过才能最终确定。不过我大概率是没这个精力去做的,先把工作上的目的达到,之后看心情了。

### ESP32 使用 IDF 进行 UART (RS232) 通信 #### 配置 UART 参数 为了实现 ESP32 和 RS232 设备之间的串口通信,需要配置 UART 接口参数。通常情况下,默认的 UART0 已经被用于试日志输出到控制台[^2]。 对于其他用途,建议使用 UART1 或者 UART2 来连接外部设备。下面是一个简单的例子来展示如何初始化并设置 UART: ```c #include "driver/uart.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" void uart_init(void) { const int RX_BUF_SIZE = 1024; // Configure parameters of UART driver, // install UART driver using queue. uart_config_t uart_config = { .baud_rate = 9600, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE }; // Install UART driver for interrupt-driven reads/writes uart_driver_install(UART_NUM_2, RX_BUF_SIZE * 2, 0, 0, NULL, 0); uart_param_config(UART_NUM_2, &uart_config); // Set UART pins (using UART0 default TX/RX pins here) uart_set_pin(UART_NUM_2, GPIO_NUM_17, GPIO_NUM_16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); } ``` 这段代码展示了如何通过 `uart_config_t` 结构体指定波特率、数据位数、奇偶校验以及停止位等基本属性,并用相应的 API 函数完成硬件引脚分配和驱动安装工作。 #### 发送与接收数据 一旦完成了上述配置过程之后就可以开始发送或读取来自另一个设备的数据流了: ```c // Send string over UART void send_string(const char* str){ size_t length = strlen(str); uart_write_bytes(UART_NUM_2, (const char*)str, length); } // Read data from UART buffer into a character array int read_data(char* buf, int max_len){ return uart_read_bytes(UART_NUM_2, (uint8_t *)buf, max_len, portMAX_DELAY); } ``` 这里定义了一个函数用来向远端写入字符串消息;而第二个则是阻塞式的等待直到有新的输入到达为止再返回实际接收到的内容长度给用方处理。 #### 完整示例程序结构 最后给出一个完整的最小化应用程序框架作为参考,在此之上可以根据具体需求进一步扩展功能特性: ```c #define MAX_LINE_LENGTH 256 char line[MAX_LINE_LENGTH]; size_t pos = 0; bool newline_flag = false; static void IRAM_ATTR uart_intr_handler(void *arg) { uint8_t byte; while(uart_get_ring_buffer_data_length(UART_NUM_2)){ if(esp_rom_uart_rx_one_char(&byte)==ESP_OK){ if(byte=='\n'){ newline_flag=true; }else{ line[pos++]=byte; } } } } extern "C" void app_main() { uart_init(); uart_enable_pattern_det_baud_intr(UART_NUM_2,UART_PATTERN_CH,RX_BUF_SIZE-1,10,10,portMAX_DELAY); uart_isr_register(UART_NUM_2,uart_intr_handler,(void*)&pos,intr_alloc_flags,&handle); while(true){ if(newline_flag){ printf("Received:%s\n",line); memset(line,'\0',sizeof(line)); pos=0; newline_flag=false; } vTaskDelay(pdMS_TO_TICKS(10)); } } ``` 这个主循环会持续监听是否有新行符传进来触发中断服务例程(ISR),当检测到了换行时就会打印出来自于远程终端的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值