ESP32串口的正确打开方式-esp文件
之前写过一篇关于esp32串口的文章:ESP32中断方式操作串口,但是不够详细,这篇进行更加细节的描述。
因为我这个代码是基于micropython esp32进行二次开发的,需要改造原有micropython对串口的配置。当然这些代码直接用ESP32-IDF开发也没问题。
先看下Micropython对ESP32uart0的串口配置:
对应文件为:/micropython/ports/esp32/uart.c
该文件初始化打开了串口接收中断,但是没有安装串口驱动,所以不能在中断服务函数中调用uart_write_bytes()。如果要要调用该发送函数,必须在串口初始化的时候,执行如下两步:
uart_driver_install(UART_NUM_0, 256,0, 0, NULL, 0);
uart_isr_free(UART_NUM_0);
//micropython对串口的初始化代码如下
void uart_init(void) {
uart_isr_handle_t handle;
uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle);
uart_enable_rx_intr(UART_NUM_0);
}
该函数主要执行两个步骤:
- 串口中断服务函数的注册
- 串口接收中断的使能,接收中断使能函数里面打开了两个中断FIFO 接收满和接收超时中断
如上是我们解释一下micropython对串口的配置,但不是重点,重点还在于我们自己的初始化和中断服务函数代码:
完整的串口初始化配置
void uart_init(void) {
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
};
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0,UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_isr_handle_t handle;
uart_driver_install(UART_NUM_0, 256,0, 0, NULL, 0); //安装驱动程序,使用idf自带中断服务函数
uart_isr_free(UART_NUM_0); //释放不使用idf自带中断服务函数
uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle); //重新注册中断服务函数
uart_enable_rx_intr(UART_NUM_0); //使能中断接收
uart_set_rx_timeout(UART_NUM_0,10); //配置接收超时中断时间,单位为按照当前波特率传输1个bytes的时间
}
该初始化主要执行以下几个步骤:
- 串口参数的初始化配置
- 串口引脚配置
- 串口驱动安装,这个地方需要注意,执行完uart_driver_install以后,默认会使用ESP32-IDF自带的串口中断服务函数,而这里我们不是用就需要下一步操作
- 释放idf自带串口中断服务函数
- 重新注册自定义串口中断服务函数
- 使能串口接收中断uart_enable_rx_intr,该函数会打开两个中断源:rxfifo接收满中断,rxfifo超时中断(默认超时时间为10个byte)
- 最后一步设置接收超时中断时间可以省略,因为在上一步已经默认打开,并且idf默认值为10个bytes时间。如果想修改超时中断时间的话就调用该函数
完整的串口中断服务函数
STATIC void IRAM_ATTR uart_irq_handler(void *arg) {
volatile uart_dev_t *uart = &UART0;
uint8_t recSize=0;
uart->int_clr.rxfifo_full = 1;
uart->int_clr.frm_err = 1;
if(uart->int_st.rxfifo_tout) //检查是否产生超时中断
{
uart->int_clr.rxfifo_tout = 1;
recSize=uart->status.rxfifo_cnt;
if(recSize!=0)
{
while(uart->status.rxfifo_cnt)
{
uart0RxBuf[uart0RxCount++]=uart->fifo.rw_byte;
}
if(uart0RxCount==uart0RxBuf[0]) //接收一帧数据长度等于第一个byte指示的长度,接收正确
{
port_infoToRecQueue(PORT_UART,uart0RxCount,uart0RxBuf);
uart0RxCount=0;
}
else if(uart0RxCount>uart0RxBuf[0]) //接收数据长度大于第一个byte指示的长度,接收出错
{
uart0RxCount=0;
}
}
}
}
初始化已经打开了串口中断,针对接收有两个中断源:rxfifo满中断 rx接收超时中断。默认rxfifo的深度为128byte,所以只要不连续发超过128个byte都不会触发fifo满中断。当发送完一帧数据,只要后面空闲的时间超过设定的超时时间就会产生超时中断。所以这里要弄清楚并不是每接收到一个byte就会产生一次串口中断。
在实际测试中,给ESP32发送一帧数据会让他触发两次rx超时中断,详述如下
关于esp32 串口接收超时中断
IDF中设置默认超时时间为,10代表以当前波特率传输10bytes的时间
UART_TOUT_THRESH_DEFAULT (10)
每接收一帧连续的数据包,会触发两次超时中断。
- 第一次触发超时中断,读取rxfifo中已接收字节数和这一帧数据长度相等。
- 第二次触发超时中断,读取rxfilo已接收字节数为0
所以只要每一帧数据之间都有时间空隙,并且空隙时间长于设定值,那么第一次触发超时中断时rxfifo中的数据就是一帧的数据。读取UART0.status.rxfifo_cnt该寄存器里面的值就是这一帧的数据包长度值
相关内容
-
excel怎么用乘法函数
excel怎么用乘法函数,乘法,函数,哪个,excel乘法函数怎么用?1、...
-
在wps中粘贴保留原格式化|wps中复制文件保留原
在wps中粘贴保留原格式化|wps中复制文件保留原有格式,格式化,...
-
什么是boot.ini文件错误ini的非法解决方案
什么是boot.ini文件错误ini的非法解决方案,,千奇百怪的电脑问...
-
鼠标不能拖动文件了
鼠标不能拖动文件了,鼠标,拖动,本文目录鼠标不能拖动文件了电...
-
电脑服务全部禁用了怎么恢复|电脑服务全部被禁
电脑服务全部禁用了怎么恢复|电脑服务全部被禁用怎么办,,电脑...
-
Outlook的PST文件损坏的修复方法
Outlook的PST文件损坏的修复方法,文件, ...
-
三星空调服务电话24小时|三星空调服务电话24小
三星空调服务电话24小时|三星空调服务电话24小时昆山,,三星空...
-
excel中乘法函数是什么?
excel中乘法函数是什么?,乘法,函数,什么,打开表格,在C1单元格中...
-
标准差excel用什么函数?
标准差excel用什么函数?,函数,标准,什么,在数据单元格的下方输...
-
金蝶易记账售后服务电话
金蝶易记账售后服务电话,,1.人工客服电话是多少075客服专线075...
-
电脑什么文件不能删除文件|电脑中哪些文件不能
电脑什么文件不能删除文件|电脑中哪些文件不能删除,,电脑中哪...
-
电脑上怎样打文件|电脑上怎样打文件符号
电脑上怎样打文件|电脑上怎样打文件符号,,电脑上怎样打文件符...
-
将wps转为EX|把WPS文件转为excel表格
将wps转为EX|把WPS文件转为excel表格,转为,如何将,wps,1.怎么...
-
电脑字幕手机怎么载入|电脑字幕手机怎么载入文
电脑字幕手机怎么载入|电脑字幕手机怎么载入文件,,电脑字幕手...
-
GitLab预告DevOps平台第15版服务更新 拓展可观
GitLab预告DevOps平台第15版服务更新 拓展可观察性与安全工...