esp32基于中断+FIFO+事件队列的uart

摘要:本文分析了基于队列的数据处理机制,适用于多任务并行、容错性要求高及协议解析场景,但不适合超低功耗或资源受限系统。通过实例解析了串口中断触发条件(包括正常接收、异常错误和特殊信号),并演示了三种数据处理情况:少量数据(触发超时中断)、大量数据(分批次处理)以及处理速度慢于接收速度时的积压处理。该机制通过环形缓冲区和队列实现稳健的数据处理,确保数据不丢失,但需注意硬件资源消耗。

目录

一、应用

(1)适用场景

1.多任务并存:

2.容错性强:

3.协议解析:

(1)这种机制不适合的场景

[1.超低功耗(Ultra-Low Power):](#1.超低功耗(Ultra-Low Power):)

[2协议极简的 51 单片机](#2协议极简的 51 单片机)

二、实例解析

(1)中断触发条件:

[1. 正常接收触发](#1. 正常接收触发)

[2. 异常错误触发(保护机制)](#2. 异常错误触发(保护机制))

[3. 特殊信号触发](#3. 特殊信号触发)

(2)三种情况

[1.当发的数据量极少(例如:每隔 1 秒发 1 个字节)](#1.当发的数据量极少(例如:每隔 1 秒发 1 个字节))

[2.发的数据又快又多(例如:一次性发 500 字节,波特率 115200)](#2.发的数据又快又多(例如:一次性发 500 字节,波特率 115200))

3.你(程序)处理得慢,对方发得快


这种基于队列的机制,是为数据量大、逻辑复杂的系统设计的

一、应用

(1)适用场景

1.多任务并存

当串口在收数据时,你的 CPU 还可以去处理 Wi-Fi、控制电机或刷新屏幕等。

2.容错性强

它能自动帮你缓存数据(RingBuffer),即便你的主任务卡住了 10ms,数据也不会丢失。

3.协议解析

非常适合处理 AT 指令、JSON 数据包或 Modbus 协议。

(1)这种机制不适合的场景

1.超低功耗(Ultra-Low Power):

事件驱动机制需要维持 FreeRTOS 的调度器运行,且串口外设必须一直通电。

2协议极简的 51 单片机

在内存只有几百字节的单片机上,开辟 1024 字节的 RingBuffer 和 FreeRTOS 队列简直是"奢侈品"。

二、实例解析

复制代码
    while(1)
    {
        if(pdTRUE == xQueueReceive(uart_queue,&uart_ev,portMAX_DELAY))
        {
            switch(uart_ev.type)
            {
                case UART_DATA:
                ESP_LOGI(TAG, "UART_DATA, size: %d", uart_ev.size);
                    uart_read_bytes(USER_UART,uart_buffer,uart_ev.size,portMAX_DELAY);
                    uart_write_bytes(USER_UART,uart_buffer,uart_ev.size);
                    break;
                default:
                    break;
            }
        }
    }

以上代码是例子,在此之前先了解一下串口中断触发的机制

(1)中断触发条件:

1. 正常接收触发

  • RX FIFO Full (满阈值中断): 硬件自带一个"小仓库"(FIFO),当硬件 FIFO 里的数据满时(比如esp32s3的 120 字节)触发。

    • 场景:对方发大段数据,效率最高,攒够一波再处理。
  • RX FIFO Timeout (接收超时中断): FIFO 里有数据,但对方停止发送的时间超过了设定的阈值(比如 10 个字符传输的时间)。

    • 场景 :对方发完了一串短指令(比如 AT+OK),虽然没填满 FIFO,但为了保证实时性,硬件会强制触发中断通知 CPU 领走。

10 个字符传输的时间具体长短取决于波特率,波特率的定义是"每秒传输的比特数。

当串口是:1 位起始位+8 位数据位+1 位停止位= 10 Bits,十个字符传输了100bits。

时间计算公式:总比特数/波特率

2. 异常错误触发(保护机制)

当通讯物理链路出现问题时,硬件会立刻报警。

  • RX FIFO Overflow (硬件溢出中断): 硬件 FIFO(128 字节)已经满了,但 CPU 还没把数据搬走,新数据又进来了,导致旧数据被覆盖。

    • 场景:波特率极高且中断处理程序被其他高优先级任务卡住了。
  • Frame Error (帧错误中断): 数据位的起始位或停止位不符合标准(波形乱了)。

    • 场景波特率设置不一致,或者线路干扰极其严重。
  • Parity Error (校验错误中断): 开启了奇偶校验,但接收到的数据校验位对不上。

3. 特殊信号触发

  • UART Break (总线中断信号): 接收线(RX)被拉低并持续超过一个完整帧的时间(通常用于复位从设备或进入某种特殊模式)。

  • Pattern Detect (模式匹配中断) :你可以设置硬件监控特定的字符(比如 + 字符)。当硬件连续看到 3 个 + 时,即使没发生超时或满溢,也会立刻触发中断。

    • 场景:用于进入无线模块的 AT 指令模式。

(2)三种情况

1.当发的数据量极少(例如:每隔 1 秒发 1 个字节)

假设你从电脑串口助手发送了一个字符 A

  • 过程

    1. A 进入硬件的 FIFO。

    2. 因为只有一个字节,没达到"满员阈值"(比如 120 字节),不触发中断

    3. 触发计时器 :硬件发现 1 个字节进来后,后面没动静了。等待一段时间后,触发 "接收超时中断"

    4. 驱动程序把 A 搬到仓库(Ring Buffer)。

    5. 驱动程序往队列里发一张通知单:UART_DATA, size: 1

  • 结果 :你的 xQueueReceive 被唤醒,if 成立,uart_ev.size1

在 ESP-IDF 框架下,当你调用 uart_driver_install 时,系统会自动在内部帮你开辟、初始化并管理这个 Ring Buffer。如果是stm32f103,需要自己写这个Ring Buffer。

2.发的数据又快又多(例如:一次性发 500 字节,波特率 115200)

假设你发送了一个很长的字符串,长度为 500 字节。

  • 过程

    1. 第一波 :前 120 字节进入 FIFO,达到阈值,触发 "FIFO 全满中断"

      • 驱动迅速把这 120 字节搬进仓库。

      • 发第一张通知单:UART_DATA, size: 120

    2. 第二波:紧接着后续数据又填满一次 FIFO。

      • 发第二张通知单:UART_DATA, size: 120
    3. 以此类推...

    4. 最后一波 :剩下的 20 字节不满 120,触发 "超时中断"

      • 发最后一张通知单:UART_DATA, size: 20
  • 结果 :你的 while(1) 循环会连续跑 5 次 if

    • 前 4 次 uart_ev.size 都是 120。

    • 最后 1 次 uart_ev.size 是 20。

  • 体验:系统处理非常稳健,不会因为数据太快而卡死,因为数据都在仓库里排队。

3.你(程序)处理得慢,对方发得快

假设对方每 10ms 发 100 字节,但你的程序在 if 里面加了一个 vTaskDelay(500)(故意偷懒)。

  • 过程

    1. 对方发了 5 次数据,产生了 5 个事件通知单都在队列里排队。

    2. 因为你没去读仓库(Ring Buffer),数据一直在仓库里堆积。

    3. 终于 ,你处理完上一个任务,回到 xQueueReceive 拿到了下一张通知单。

  • 结果 :由于驱动程序非常聪明,它给你的 size 实际上是当前仓库里积压的所有字节数

    • 你拿到的 uart_ev.size 可能会变成 500
  • 体验 :你会发现 size 变大了。这是一种自我保护机制,防止你漏掉已经存进仓库的数据。

当缓冲区读取完了,消息队列还有未处理的数据,但此时仓库已经是 的了,这个函数会返回 0 或者阻塞等待。

相关推荐
不做无法实现的梦~10 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
熊猫_豆豆15 小时前
同步整流 Buck 降压变换器
单片机·嵌入式硬件·matlab
whik119418 小时前
ESP32-C3-DevKitM-1开发板深度上手评测
wifi·嵌入式·esp32·arduino·蓝牙·开发板·乐鑫
chenchen0000000019 小时前
49元能否买到四核性能?HZ-RK3506G2_MiniEVM开发板评测:MCU+三核CPU带来的超高性价比
单片机·嵌入式硬件
孤芳剑影20 小时前
反馈环路设计总结
嵌入式硬件·学习
dump linux21 小时前
设备树子系统与驱动开发入门
linux·驱动开发·嵌入式硬件
专注VB编程开发20年21 小时前
简易虚拟 PLC 服务器-流水线自动化,上位机程序维护升级,西门子PLC仿真
服务器·单片机·自动化·上位机·plc·流水线·工控
LeoZY_21 小时前
CH347/339W开源项目:集SPI、I2C、JTAG、SWD、UART、GPIO多功能为一体(3)
stm32·单片机·嵌入式硬件·mcu·开源
chenchen0000000021 小时前
国产显示芯势力新篇章:内置DDR+四核A35!MY-SSD2351-MINI开发板深度评测
驱动开发·嵌入式硬件
BackCatK Chen21 小时前
第13篇:TMC2240 StallGuard4失速检测|寄存器配置+状态读取(保姆级)
单片机·嵌入式硬件·tmc2240·stm32实战·stallguard4·失速检测·电机故障识别