STM32从零到量产开发:四路继电器工业控制模块开发-RS485 半双工通信底层驱动模块(bsp_res485)设计说明

STM32从零到量产开发:四路继电器工业控制模块开发-RS485 半双工通信底层驱动模块(bsp_res485)设计说明

1. 模块概述

本模块(bsp_rs485)是基于 STM32 HAL 库开发的 RS485 半双工通信底层驱动,主要基于 USART1 实现。模块采用“单字节接收中断 + IDLE 总线空闲中断”的机制进行 Modbus 帧的分割与接收,并使用阻塞式发送配合 DE 方向引脚自动控制完成半双工换向。支持运行时动态切换波特率,并提供配套的字符串查询接口供 Shell 调试打印。

2. 硬件接口配置

  • TX (发送引脚): PA9
  • RX (接收引脚): PA10
  • DE (发送使能引脚): PA8(高电平有效,拉高进入发送模式,拉低进入接收模式)

3. 核心数据流

3.1 接收数据流

  1. RS485 总线数据到达 USART1,触发单字节接收中断。
  2. 进入BSP_RS485_OnRxByte(),将字节线性写入s_rx_buf,并使s_rx_index递增。
  3. 总线空闲触发 IDLE 中断,进入BSP_RS485_OnIdleIRQ()
  4. 置位s_frame_ready并记录s_frame_len,标记整帧接收完成。
  5. 主循环通过BSP_RS485_IsFrameReady()查询到就绪标志后,调用BSP_RS485_GetFrame()取走完整数据。
  6. 上层协议栈(如modbus_rtu)对取出的数据进行解析。

3.2 发送数据流

  1. 上层协议栈调用BSP_RS485_Send()发起发送。
  2. 模块自动拉高 DE 引脚,切换为发送模式,并关闭接收中断(防止总线回环干扰)。
  3. 执行阻塞式发送,轮询等待 TC(发送完成)标志。
  4. 发送完成后拉低 DE 引脚,恢复接收模式。
  5. 清空接收缓存中的脏数据,重新开启单字节接收中断,恢复总线监听。

4. 关键变量与缓冲区

变量/宏名称类型/大小说明
RS485_RX_BUF_SIZE宏 (256u)RS485 接收线性缓冲区最大字节数(适配 Modbus 最大帧长)
RS485_TX_BUF_SIZE宏 (256u)RS485 发送缓冲区最大字节数
s_rx_buf静态数组线性接收缓存,存放当前正在接收的一帧原始报文
s_rx_index静态变量接收缓存写入下标
s_frame_readyvolatile 静态变量完整帧就绪标志(中断置位,主循环清零)
s_frame_lenvolatile 静态变量完整帧字节长度
s_baud_tbl静态常量数组波特率索引到硬件寄存器数值的映射表
g_baud_str静态常量数组波特率索引到打印字符串的映射表(仅本文件私有)

5. API 接口说明

5.1 初始化与配置

  • void BSP_RS485_Init(void)

    • 功能: RS485 外设初始化。
    • 说明: 初始化串口,DE 引脚默认拉低进入接收模式,开启 IDLE 空闲中断与单字节接收中断。
  • int8_t BSP_RS485_SetBaudrate(uint8_t baud_index)

    • 功能: 动态重新配置 RS485 串口波特率。
    • 参数:baud_index(波特率索引,范围BAUD_INDEX_9600~BAUD_INDEX_115200)
    • 返回值:0配置成功;-1索引参数非法或初始化失败。
    • 说明: 会重新初始化串口,清空接收缓存,重启中断接收。

5.2 数据收发

  • uint8_t BSP_RS485_Send(const uint8_t *data, uint16_t len)

    • 功能: RS485 阻塞发送一帧数据,自动控制 DE 发送引脚。
    • 参数:data(待发送二进制数据指针),len(发送字节长度)
    • 返回值:0发送成功;1空指针/长度超限/发送超时失败。
    • 注意: 阻塞式发送,禁止在中断上下文调用。
  • uint8_t BSP_RS485_IsFrameReady(void)

    • 功能: 查询是否收到完整一帧数据。
    • 返回值:1存在完整帧;0无完整接收帧。
  • void BSP_RS485_GetFrame(uint8_t *buf, uint16_t *len)

    • 功能: 读取已接收完整 Modbus 帧,读取后自动清空帧标志并重启接收。
    • 参数:buf(接收数据存储缓冲区),len(实际接收字节长度输出)

5.3 状态查询与辅助

  • uint8_t BSP_RS485_GetBaudIndex(void)

    • 功能: 获取当前生效的波特率索引。
  • const char* RS485_GetBaudStr(uint8_t index)

    • 功能: 根据波特率索引获取对应打印字符串(供 RS232 shell 调试输出)。
    • 参数:index(波特率索引 0~4)
    • 返回值: 波特率文本,索引越界返回"?"

5.4 底层中断回调(内部使用)

  • void BSP_RS485_OnIdleIRQ(void): USART IDLE 空闲中断回调,标记一帧接收完成。仅由stm32f1xx_it.c内部调用。
  • void BSP_RS485_OnRxByte(void): 单字节接收完成 HAL 回调分发函数。由HAL_UART_RxCpltCallback统一入口调用。

6. 架构设计与解耦说明

  1. HAL 回调统一分发: 本文件承载了 HAL 串口回调的总分发入口(RxCplt/Error),通过判断Instance区分 USART1(RS485) 与 UART4(RS232),分别转交各自模块处理,避免回调冲突。
  2. DE 换向时序封装: DE 方向引脚的换向时序完全封装在BSP_RS485_Send内部,上层业务只管发数据,无需关心底层硬件时序。
  3. 中断与主循环解耦: 中断上下文仅做“存字节”与“打帧标记”等极简操作,所有复杂的帧解析与业务处理全部放在主循环执行。
  4. 字符串映射解耦: 波特名字符串映射统一存放在本模块内部,对外仅提供RS485_GetBaudStr只读接口供 Shell 调用,消除了rs232_shell内部重复定义波特表的耦合问题。
  5. 线性缓冲设计: 针对 Modbus RS485 通信特性,未采用标准环形 FIFO,而是采用线性缓冲 +s_rx_index设计,配合 IDLE 中断实现精准的帧分割。
/** ****************************************************************************** * @file bsp_rs485.h * @brief RS485 半双工通信底层驱动 - USART1 * @details 硬件:PA9(TX) PA10(RX) PA8(DE发送使能高有效) * 接收:单字节中断 + IDLE帧空闲中断检测一帧结束 * 发送:阻塞发送,自动拉高/拉低DE方向引脚 * 波特率配置可运行时动态切换,配套字符串查询接口供shell打印 ****************************************************************************** */#ifndef__BSP_RS485_H#define__BSP_RS485_H#ifdef__cplusplusextern"C"{#endif#include"main.h"#include"usart.h"/* RS485接收环形缓冲区最大字节数 Modbus最大帧256 */#defineRS485_RX_BUF_SIZE256u/* RS485发送缓冲区最大字节数 */#defineRS485_TX_BUF_SIZE256u/* 波特率索引枚举宏,与Flash参数保持寄存器一一对应 */#defineBAUD_INDEX_96000u#defineBAUD_INDEX_192001u#defineBAUD_INDEX_384002u#defineBAUD_INDEX_576003u#defineBAUD_INDEX_1152004u#defineBAUD_INDEX_NUM5u/** 波特率索引最大值 */#defineBAUD_INDEX_MAX(BAUD_INDEX_NUM-1u)/** * @brief RS485外设初始化 * @note 初始化串口、DE引脚默认接收模式,开启IDLE空闲中断与单字节接收中断 */voidBSP_RS485_Init(void);/** * @brief 动态重新配置RS485串口波特率 * @param[in] baud_index 波特率索引 BAUD_INDEX_9600~BAUD_INDEX_115200 * @retval int8_t 0:配置成功;-1:索引参数非法 * @note 会重新初始化串口,清空接收缓存,重启中断接收 */int8_tBSP_RS485_SetBaudrate(uint8_tbaud_index);/** * @brief 获取当前生效波特率索引 * @retval uint8_t 当前baud_index */uint8_tBSP_RS485_GetBaudIndex(void);/** * @brief 根据波特率索引获取对应打印字符串(供RS232 shell调试输出) * @param[in] index 波特率索引0~4 * @retval const char* 波特率文本,索引越界返回"?" * @note 字符串映射表仅存在bsp_rs485.c内部,上层仅通过本接口读取,消除跨文件耦合 */constchar*RS485_GetBaudStr(uint8_tindex);/** * @brief RS485阻塞发送一帧数据,自动控制DE发送引脚 * @param[in] data 待发送二进制数据指针 * @param[in] len 发送字节长度 * @retval uint8_t 0:发送成功;1:空指针/长度超限/发送超时失败 */uint8_tBSP_RS485_Send(constuint8_t*data,uint16_tlen);/** * @brief 查询是否收到完整一帧数据 * @retval uint8_t 1:存在完整帧;0:无完整接收帧 */uint8_tBSP_RS485_IsFrameReady(void);/** * @brief 读取已接收完整Modbus帧,读取后自动清空帧标志重启接收 * @param[out] buf 接收数据存储缓冲区,长度≥RS485_RX_BUF_SIZE * @param[out] len 实际接收字节长度输出 */voidBSP_RS485_GetFrame(uint8_t*buf,uint16_t*len);/** * @brief USART IDLE空闲中断回调函数 * @note 仅stm32f1xx_it.c中断服务函数内部调用,业务层禁止直接调用 * 总线空闲时标记一帧接收完成,置帧就绪标志 */voidBSP_RS485_OnIdleIRQ(void);/** * @brief 单字节接收完成HAL回调分发函数 * @note 由HAL_UART_RxCpltCallback统一入口调用,仅底层中断文件使用 */voidBSP_RS485_OnRxByte(void);#ifdef__cplusplus}#endif#endif/* __BSP_RS485_H */
/** ****************************************************************************** * @file bsp_rs485.c * @brief RS485 半双工通信底层驱动实现 (基于 USART1) * * 模块功能: * 1. 接收: 单字节接收中断 + IDLE 总线空闲中断做 Modbus 帧分割。 * 2. 发送: 阻塞式发送, 自动拉高 / 拉低 DE 方向引脚完成半双工换向。 * 3. 波特率运行时动态切换, 并提供波特字符串只读查询接口。 * * 数据流: * 接收: RS485 总线 -> USART1 接收中断 -> BSP_RS485_OnRxByte() * -> 线性写入 s_rx_buf (s_rx_index 递增) * -> 总线空闲触发 IDLE 中断 -> BSP_RS485_OnIdleIRQ() * -> 置 s_frame_ready / s_frame_len 标记整帧完成 * -> 主循环 BSP_RS485_IsFrameReady() 查询, BSP_RS485_GetFrame() 取走 * -> 上层 modbus_rtu 解析 * 发送: modbus_rtu -> BSP_RS485_Send() -> 拉高 DE -> 阻塞发送 * -> 轮询等待 TC 发送完成 -> 拉低 DE -> 清脏缓存 -> 恢复接收中断 * * 解耦优化: * 波特名字符串映射统一存放本文件, 提供 RS485_GetBaudStr 只读接口供 shell 调用, * 消除 rs232_shell 内部重复定义波特表的耦合问题。 * Modbus 485 不适用环形 FIFO, 采用线性缓冲 + s_rx_index 设计。 * * 解耦说明: * 1. 本文件同时承载 HAL 串口回调的总分发入口 (RxCplt / Error), 按 Instance * 区分 USART1(RS485) 与 UART4(RS232), 分别转交各自模块处理。 * 2. DE 方向引脚的换向时序完全封装在 BSP_RS485_Send 内部, 上层只管发数据。 * 3. 中断上下文只做 "存字节" 与 "打帧标记", 帧解析全部放主循环。 ****************************************************************************** */#include"bsp_rs485.h"#include"bsp_rs232.h"#include"main.h"#include<string.h>/* -------------------------- API 快速导航 -------------------------- * void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); HAL 接收完成总回调 (中断上下文) * void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); HAL 串口错误总回调 (中断上下文) * void BSP_RS485_Init(void); 初始化, 开 IDLE + 单字节接收中断 * int8_t BSP_RS485_SetBaudrate(uint8_t baud_index); 动态切换波特率 (0 成功 / -1 非法) * uint8_t BSP_RS485_Send(const uint8_t *data, uint16_t len); 阻塞发送一帧, 自动控制 DE * uint8_t BSP_RS485_IsFrameReady(void); 查询是否有完整帧就绪 * void BSP_RS485_GetFrame(uint8_t *buf, uint16_t *len); 读取完整帧并清标志 * uint8_t BSP_RS485_GetBaudIndex(void); 读取当前波特率索引 * const char *RS485_GetBaudStr(uint8_t index); 索引转波特字符串 (越界返回 "?") * void BSP_RS485_OnIdleIRQ(void); IDLE 空闲中断处理 (中断上下文) * void BSP_RS485_OnRxByte(void); 单字节接收中断处理 (中断上下文) * ------------------------------------------------------------------ *//* -------------------------- 区块 1:static const 只读常量 / 映射查表 -------------------------- *//** * @brief 波特率索引→硬件寄存器数值映射表,底层串口初始化使用 */staticconstuint32_ts_baud_tbl[BAUD_INDEX_NUM]={9600u,19200u,38400u,57600u,115200u};/** * @brief 波特率索引→打印字符串映射表,仅本文件static私有 * @note 上层rs232_shell通过RS485_GetBaudStr接口读取,不直接访问此数组 */staticconstchar*constg_baud_str[BAUD_INDEX_NUM]={"9600","19200","38400","57600","115200"};/* -------------------------- 区块 2:模块内部静态全局变量 -------------------------- *//* 接收环形缓存 */staticuint8_ts_rx_buf[RS485_RX_BUF_SIZE];/* 线性接收缓存,存放当前正在接收的一帧原始报文 */staticuint16_ts_rx_index=0u;/* 接收写入下标 */staticuint8_ts_rx_byte=0u;/* 中断单字节临时缓存 */staticvolatileuint8_ts_frame_ready=0u;/* 完整帧就绪标志 * volatile:由 IDLE 中断置位、主循环查询清零, * 禁止编译器把轮询判断优化为寄存器缓存 */staticvolatileuint16_ts_frame_len=0u;/* 完整帧字节长度 * volatile:与 s_frame_ready 同在中断中写入, * 主循环取帧时必须读到最新值 *//* 当前生效波特率索引 */staticuint8_ts_baud_index=BAUD_INDEX_9600;/* 发送临时缓存 */staticuint8_ts_tx_buf[RS485_TX_BUF_SIZE];/* -------------------------- 区块 3:HAL 库系统全局回调钩子(统一分发入口) -------------------------- *//** * @brief HAL库串口接收完成统一回调入口 * @param[in] huart 串口句柄指针 * @retval 无 * @note 区分USART1(RS485) / UART4(RS232)分发到各自接收处理函数 * @note 运行在中断上下文,禁止耗时操作 * 【关联指引】本钩子覆盖 HAL 弱定义,是全工程串口收字节的唯一入口, * 分别转交 BSP_RS485_OnRxByte() 与 BSP_RS232_OnRxByte()。 */voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){if(huart->Instance==USART1){BSP_RS485_OnRxByte();}elseif(huart->Instance==UART4){BSP_RS232_OnRxByte();}}/** * @brief HAL库串口错误中断统一回调入口 * @param[in] huart 串口句柄指针 * @retval 无 * @note RS485发生帧错误/溢出时清空缓存重启接收 * @note 运行在中断上下文,禁止耗时操作 */voidHAL_UART_ErrorCallback(UART_HandleTypeDef*huart){if(huart->Instance==USART1){/* 出错帧内容已不可信:直接丢弃半帧数据并重启接收 */s_rx_index=0u;s_frame_ready=0u;HAL_UART_Receive_IT(&huart1,&s_rx_byte,1u);}elseif(huart->Instance==UART4){BSP_RS232_OnError(huart);}}/* -------------------------- 区块 4:对外公共业务 API -------------------------- *//** * @brief RS485模块初始化 * @retval 无 * @note 需在 MX_USART1_UART_Init 之后调用;DE 默认拉低进入接收模式 */voidBSP_RS485_Init(void){s_rx_index=0u;s_frame_ready=0u;s_frame_len=0u;s_baud_index=BAUD_INDEX_9600;/* DE引脚默认低电平,接收模式 */HAL_GPIO_WritePin(RS485_DE_GPIO_Port,RS485_DE_Pin,GPIO_PIN_RESET);/* 使能总线空闲IDLE中断 */__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);/* 启动单字节中断接收 */HAL_UART_Receive_IT(&huart1,&s_rx_byte,1u);}/** * @brief 动态重新配置RS485串口波特率 * @param[in] baud_index 波特率索引 BAUD_INDEX_9600~BAUD_INDEX_115200 * @retval int8_t 0:配置成功;-1:索引参数非法 * @note 会重新初始化串口,清空接收缓存,重启中断接收 * 【关联指引】索引经 s_baud_tbl 查表转换为真实波特率数值; * 调用方通常是 flash_param 恢复配置或 rs232_shell 手动设置。 */int8_tBSP_RS485_SetBaudrate(uint8_tbaud_index){/* 入参校验:索引越界直接拒绝,避免查表越界 */if(baud_index>=BAUD_INDEX_NUM){return-1;}/* 注销串口重新配置波特率 */HAL_UART_DeInit(&huart1);/* 注销当前串口外设,关闭时钟、清除寄存器状态; */huart1.Init.BaudRate=s_baud_tbl[baud_index];if(HAL_UART_Init(&huart1)!=HAL_OK){return-1;}s_baud_index=baud_index;/* 重新开启IDLE总线空闲中断(Modbus帧分割依赖) */__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);HAL_GPIO_WritePin(RS485_DE_GPIO_Port,RS485_DE_Pin,GPIO_PIN_RESET);s_rx_index=0u;s_frame_ready=0u;HAL_UART_Receive_IT(&huart1,&s_rx_byte,1u);/* 重启单字节接收中断,恢复数据接收 */return0;}/** * @brief RS485阻塞发送一帧数据,自动控制DE发送引脚 * @param[in] data 待发送二进制数据指针 * @param[in] len 发送字节长度 * @retval uint8_t 0:发送成功;1:空指针/长度超限/发送超时失败 * @note 阻塞式发送,禁止在中断上下文调用 * 【关联指引】发送期间会关闭接收中断并在结束后清空 s_rx_buf 脏数据, * 避免半双工总线回环把自身报文当成接收帧。 */uint8_tBSP_RS485_Send(constuint8_t*data,uint16_tlen){/* 入参兜底:零长度、超过发送缓存容量、空指针一律判失败 */if(len==0u||len>RS485_TX_BUF_SIZE||data==NULL){return1u;}memcpy(s_tx_buf,data,len);/*手动DE硬件专属:关闭接收中断,防止发送回环干扰接收*/HAL_UART_AbortReceive_IT(&huart1);/* 拉高DE引脚,485芯片切换为发送模式 */HAL_GPIO_WritePin(RS485_DE_GPIO_Port,RS485_DE_Pin,GPIO_PIN_SET);uint32_ttimeout=(uint32_t)len*20u+50u;/* 计算发送超时时间:每字节20ms基础耗时 + 50ms保底超时 */HAL_StatusTypeDef st=HAL_UART_Transmit(&huart1,s_tx_buf,len,timeout);/* 阻塞式同步发送,CPU等待硬件发送完成或超时 *//* 轮询等待串口TC传输完成标志,确保最后一字节全部推送到总线 */uint32_ttickstart=HAL_GetTick();while(!__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)){/* 等待10ms仍无TC标志则跳出,避免死循环 */if((HAL_GetTick()-tickstart)>10u){break;}}/* 恢复接收模式,拉低DE,重启接收中断 */HAL_GPIO_WritePin(RS485_DE_GPIO_Port,RS485_DE_Pin,GPIO_PIN_RESET);/* 清空接收缓存脏数据(发送时总线回扰产生无效字节) */s_rx_index=0u;s_frame_ready=0u;/* 重新开启单字节接收中断,恢复总线监听 */HAL_UART_Receive_IT(&huart1,&s_rx_byte,1u);return(st==HAL_OK)?0u:1u;}/** * @brief 查询是否存在完整接收帧 * @retval uint8_t 1:存在完整帧;0:无完整接收帧 * 【关联指引】标志由 BSP_RS485_OnIdleIRQ 在 IDLE 中断中置位, * 主循环查询到 1 后应调用 BSP_RS485_GetFrame 取走整帧。 */uint8_tBSP_RS485_IsFrameReady(void){returns_frame_ready;}/** * @brief 读取完整Modbus接收帧,读取后清空帧标志 * @param[out] buf 输出缓存,存放读取到的整帧报文 * @param[out] len 输出帧长度,记录本帧有效字节数 * @retval 无 * @note 拷贝期间关中断,避免与接收中断竞争 s_rx_buf / s_rx_index * 【关联指引】数据由 BSP_RS485_OnRxByte 在中断中写入 s_rx_buf, * 本函数在主循环中取走并交给 modbus_rtu 解析。 */voidBSP_RS485_GetFrame(uint8_t*buf,uint16_t*len){__disable_irq();*len=s_frame_len;/* 长度合法性双重校验:防止异常长度导致 memcpy 越界 */if(s_frame_len>0u&&s_frame_len<=RS485_RX_BUF_SIZE){/* 将模块私有接收缓存内完整报文拷贝到上层提供的buf */memcpy(buf,s_rx_buf,s_frame_len);}/* 清除帧就绪标志、重置接收写入下标,释放缓存用于下一帧接收 */s_frame_ready=0u;s_rx_index=0u;__enable_irq();/* 重新开启单字节接收中断,持续监听485总线数据 */HAL_UART_Receive_IT(&huart1,&s_rx_byte,1u);}/** * @brief 获取当前波特率索引 * @retval uint8_t 当前生效的 baud_index */uint8_tBSP_RS485_GetBaudIndex(void){returns_baud_index;}/** * @brief 根据索引获取波特打印字符串,对外只读接口 * @param[in] index 波特率索引 0~4 * @retval const char* 波特率文本,索引越界返回 "?" * @note 字符串表为本文件私有,上层通过本接口读取,消除跨文件重复定义 */constchar*RS485_GetBaudStr(uint8_tindex){/* 越界返回哨兵字符串 "?",保证上层打印不会拿到野指针 */if(index>=BAUD_INDEX_NUM){return"?";}returng_baud_str[index];}/* -------------------------- 区块 5:内部私有底层处理函数(中断处理,放文件末尾) -------------------------- *//** * @brief IDLE总线空闲中断处理,标记一帧接收完成 * @retval 无 * @note 运行在中断上下文,禁止耗时操作 * @note 仅 stm32f1xx_it.c 中断服务函数内部调用,业务层禁止直接调用 * 【关联指引】置位的 s_frame_ready / s_frame_len 由主循环 * BSP_RS485_IsFrameReady / BSP_RS485_GetFrame 消费。 */voidBSP_RS485_OnIdleIRQ(void){/* 判断串口IDLE空闲标志是否置1 */if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)){/* 清除IDLE中断标志 */__HAL_UART_CLEAR_IDLEFLAG(&huart1);/* 至少收到1字节才算有效帧,过滤总线毛刺误触发IDLE */if(s_rx_index>0u){s_frame_len=s_rx_index;/* 记录这一帧总长度 */s_frame_ready=1u;/* 标记:完整帧就绪 */s_rx_index=0u;/* 下标重置,准备接收下一帧 */}}}/** * @brief 单字节接收中断处理,存入线性接收缓存(本工程未使用标准环形FIFO) * @retval 无 * @note 运行在串口接收完成中断上下文,执行必须极简;仅存储字节、重启接收 * @note 运行在中断上下文,禁止耗时操作 * @note 跨文件被 HAL_UART_RxCpltCallback 调用,故不加 static,不对外暴露头文件声明 */voidBSP_RS485_OnRxByte(void){/* 判断当前写入下标未达到缓存最大长度,缓存未满 */if(s_rx_index<RS485_RX_BUF_SIZE){/* 将本次中断收到的字节存入缓存,下标自增指向下一空位置 */s_rx_buf[s_rx_index++]=s_rx_byte;}else{/* 缓存溢出:新数据持续涌入,旧数据全部丢弃,从头覆盖存储 */s_rx_index=0u;s_rx_buf[s_rx_index++]=s_rx_byte;}/* 持续开启单字节中断接收,等待下一个总线字节到来 */HAL_UART_Receive_IT(&huart1,&s_rx_byte,1u);}