STM32单线串口通讯实战(四):裸机架构 —— 事件驱动与状态机设计

搞定了底层的“收发”和协议层的“规则”,现在我们要把它们组装成一个能实际跑起来的系统。

在没有 RTOS(实时操作系统)的 裸机(Bare Metal) 环境下,最大的挑战是:如何在等待从机回复(通常需要几十毫秒)的同时,不阻塞主程序的其他业务(如扫描按键、刷新屏幕)?

绝对不能用 HAL_Delay()!本章将带你构建一个基于 有限状态机(FSM)非阻塞定时器 的高效处理框架。

1. 告别 HAL_Delay:前后台系统设计

初学者写单线通讯经常这样写:

// 错误示范:阻塞式代码
HAL_UART_Transmit(&huart1, tx_data, len, 100); // 1. 阻塞发送
HAL_GPIO_WritePin(DIR_Port, DIR_Pin, RX_MODE); // 2. 切方向
HAL_Delay(50); // 3. 死等从机回复 <--- 致命代码!在这里 CPU 啥也干不了
if(HAL_UART_Receive(&huart1, rx_data, len, 100) == HAL_OK) { ... }

这种写法会导致整个系统卡顿。高效的裸机架构应分为两层:

  • 前台(中断层):负责“快进快出”的工作。如 DMA 搬运完成、IDLE 中断置位。它只负责置标志位

  • 后台(主循环):负责复杂的协议解析和业务逻辑。它通过轮询标志位检查时间戳来推动状态机流转。


2. 核心设计:有限状态机 (FSM)

我们将整个通讯过程抽象为几个状态。主循环每次运行到串口任务时,根据当前状态决定做什么。

状态定义

  1. IDLE (空闲):总线无事,等待上层应用发起请求。

  2. TX_BUSY (发送中):DMA 正在干活,等待发送完成(TC)。

  3. RX_WAIT (等待回复):请求已发出,正在计时等待从机应答。这是最关键的“非阻塞”阶段。

  4. PROCESSING (处理中):收到了完整数据,正在校验和解析(耗时操作)。


3. 代码实战:非阻塞驱动框架

3.1 定义状态结构体

为了代码整洁,把所有相关的变量打包。

typedef enum {
    STATE_IDLE,
    STATE_TX_BUSY,
    STATE_RX_WAIT,
    STATE_PROCESSING
} UART_State_t;

typedef struct {
    UART_State_t State;
    uint32_t     TxStartTime;     // 发送开始时间戳
    uint32_t     RxStartTime;     // 等待接收开始时间戳
    uint32_t     TimeoutLimit;    // 超时阈值
    uint8_t      RetryCount;      // 重发计数
    uint8_t      TxBuffer[64];
    uint8_t      RxBuffer[64];    // 这

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一路往蓝-Anbo

与其打赏不如转发

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值