
STM32从零到量产开发四路继电器工业控制模块开发— 继电器模块bsp_led.h与 bsp_led.c文件bsp_led.h实现/** ****************************************************************************** * file bsp_led.h * brief 四路LED指示灯底层驱动对外接口 * note RUN/COMM/FAULT/RS232四路独立指示灯非阻塞毫秒时基状态机 ****************************************************************************** */#ifndef__BSP_LED_H#define__BSP_LED_H#ifdef__cplusplusexternC{#endif#includemain.h/** * brief LED模块初始化 * note 初始化全部计时静态变量上电熄灭所有LED */voidBSP_LED_Init(void);/** * brief LED状态机刷新函数主循环周期调用(5~10ms) * note 处理RUN慢闪、FAULT快闪、COMM/RS232脉冲超时熄灭、自检计时 */voidBSP_LED_Refresh(void);/** * brief Modbus RS485总线通信脉冲触发收发数据点亮50ms */voidBSP_CommPulse(void);/** * brief RS232上位机交互脉冲触发收到串口指令点亮50ms */voidBSP_RS232Pulse(void);/** * brief 设置故障告警灯开关 * param active 1开启FAULT快闪 0关闭故障灯 */voidBSP_LED_SetFault(uint8_tactive);/** * brief 四路LED整机自检全部点亮1.5s后自动恢复正常灯效 */voidBSP_LED_SelfTest(void);#ifdef__cplusplus}#endif#endifbsp_led.c实现/** ****************************************************************************** * file bsp_led.c * brief 4路独立LED指示灯驱动实现非阻塞状态机 通信瞬时脉冲(#LED redesign) * details 依托HAL_GetTick毫秒时基实现无阻塞计时区分常驻闪烁、瞬时脉冲、全局自检三类灯效逻辑 * 硬件统一低电平有效GPIO_PIN_RESET点亮GPIO_PIN_SET熄灭 ****************************************************************************** */#includebsp_led.h#includemain.h/* 1. 顶层时序配置宏统一管理灯效时长参数 *//* 闪烁周期单位ms匹配产品规格书时序要求 * RUN运行灯 1Hz 慢闪FAULT故障灯 10Hz 快闪 */#defineLED_SLOW_PERIOD1000u/* RUN完整闪烁周期 1000ms */#defineLED_SLOW_ON_TIME500u/* RUN单次点亮持续时长 */#defineLED_FAST_PERIOD100u/* FAULT完整闪烁周期 100ms */#defineLED_FAST_ON_TIME50u/* FAULT单次点亮持续时长 */#defineLED_PULSE_MS50u/* RS485/RS232通信脉冲点亮宽度 */#defineLED_TEST_MS1500u/* 四路LED硬件自检总持续时长 *//* 2. 模块静态私有状态变量仅本文件内部读写 */staticuint32_ts_run_last0u;/* RUN运行灯慢闪计时基准时间戳 * 读写位置仅BSP_LED_Refresh内部读写 */staticuint8_ts_fault_active0u;/* 故障告警总开关 1开启FAULT快闪0关闭告警 * 赋值入口BSP_LED_SetFault()读取判断BSP_LED_Refresh故障分支 */staticuint32_ts_fault_last0u;/* FAULT故障灯快闪计时基准时间戳 * 赋值入口BSP_LED_SetFault()读取判断BSP_LED_Refresh故障分支 */staticuint32_ts_comm_off_at0u;/* RS485通信脉冲熄灭截止时间戳0代表无有效脉冲 * 赋值入口BSP_LED_CommPulse()赋值为当前滴答LED_PULSE_MS读取清零BSP_LED_Refresh脉冲分支 */staticuint32_ts_rs232_off_at0u;/* RS232串口脉冲熄灭截止时间戳0代表无有效脉冲 * 赋值入口BSP_RS232Pulse()赋值为当前滴答LED_PULSE_MS读取清零BSP_LED_Refresh脉冲分支 */staticuint32_ts_test_off_at0u;/* LED全局自检模式截止时间戳0代表无自检任务 * 赋值入口BSP_LED_SelfTest()赋值为当前滴答LED_TEST_MS读取清零BSP_LED_Refresh自检分支 *//* 3. 底层私有硬件IO适配函数全文件统一调用硬件逻辑单点维护 *//** * brief LED底层引脚输出统一适配接口 * param port: LED对应GPIO端口 * param pin: LED对应引脚编号 * param on: 逻辑状态 1点亮0熄灭 * note 硬件低电平有效on1输出GPIO_PIN_RESETon0输出GPIO_PIN_SET */staticvoidLED_Write(GPIO_TypeDef*port,uint16_tpin,uint8_ton){HAL_GPIO_WritePin(port,pin,on?GPIO_PIN_RESET:GPIO_PIN_SET);}/* 4. 对外公共业务接口按程序运行时序初始化→核心刷新→状态控制→自检 *//** * brief LED模块初始化复位全部计时、状态缓存四路LED上电统一熄灭 */voidBSP_LED_Init(void){s_run_lastHAL_GetTick();s_fault_lastHAL_GetTick();s_fault_active0u;s_comm_off_at0u;s_rs232_off_at0u;s_test_off_at0u;/* 四路LED初始全部熄灭 */LED_Write(STATUS_LED_GPIO_Port,STATUS_LED_Pin,0u);LED_Write(COMM_LED_GPIO_Port,COMM_LED_Pin,0u);LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,0u);LED_Write(RS232_LED_GPIO_Port,RS232_LED_Pin,0u);}/** * brief LED全局状态机定时刷新主函数主循环轮询调用 * note 推荐调用周期 5~10ms依赖HAL_GetTick()系统毫秒时基 * 执行优先级自检逻辑 RUN常驻闪烁 FAULT故障闪烁 通信脉冲超时熄灭 */voidBSP_LED_Refresh(void){uint32_tnowHAL_GetTick();uint32_telapsed;/* 【双向关联指引】 * 变量 s_test_off_at定义在文件顶部【模块静态私有状态变量】区块 * 变量赋值位置文件末尾函数 BSP_LED_SelfTest()调用时赋值为 HAL_GetTick() LED_TEST_MS(1500ms) * 变量非0代表自检任务正在执行自检优先级最高直接跳过所有常规灯效逻辑 */if(s_test_off_at!0u){/* 有符号差值判断兼容uwTick 49.7天溢出归零场景 */if(((int32_t)(now-s_test_off_at))0){s_test_off_at0u;s_run_lastnow;/* 复位RUN计时基准避免自检结束闪烁相位偏移 *//* 自检到期熄灭全部通信、故障灯 */LED_Write(COMM_LED_GPIO_Port,COMM_LED_Pin,0u);LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,0u);LED_Write(RS232_LED_GPIO_Port,RS232_LED_Pin,0u);}else{return;}}/* RUN运行灯1Hz常驻慢闪逻辑不受故障、通信状态干扰 * 计时变量 s_run_last定义在顶部静态变量区仅本分支读写 */elapsednow-s_run_last;if(elapsedLED_SLOW_ON_TIMEelapsedLED_SLOW_PERIOD){LED_Write(STATUS_LED_GPIO_Port,STATUS_LED_Pin,0u);}elseif(elapsedLED_SLOW_PERIOD){LED_Write(STATUS_LED_GPIO_Port,STATUS_LED_Pin,1u);s_run_lastnow;}else{LED_Write(STATUS_LED_GPIO_Port,STATUS_LED_Pin,1u);}/* FAULT故障灯10Hz快闪逻辑仅故障激活时执行 * 关联变量s_fault_active(总开关)、s_fault_last(计时戳) * 变量定义文件顶部静态变量赋值入口BSP_LED_SetFault() */if(s_fault_active){elapsednow-s_fault_last;if(elapsedLED_FAST_ON_TIMEelapsedLED_FAST_PERIOD){LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,0u);}elseif(elapsedLED_FAST_PERIOD){LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,1u);s_fault_lastnow;}else{LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,1u);}}/* RS485通信脉冲计时标志 s_comm_off_at定义在文件顶部【模块静态私有状态变量】区块 * 赋值入口BSP_LED_CommPulse()赋值为 HAL_GetTick() LED_PULSE_MS(50ms) * 变量非0代表存在未结束通信脉冲时间戳超时后熄灭LED并清零标记 */if(s_comm_off_at!0u((int32_t)(now-s_comm_off_at))0){LED_Write(COMM_LED_GPIO_Port,COMM_LED_Pin,0u);s_comm_off_at0u;}/* RS232串口通信脉冲计时标志 s_rs232_off_at定义在文件顶部【模块静态私有状态变量】区块 * 赋值入口BSP_RS232Pulse()赋值为 HAL_GetTick() LED_PULSE_MS(50ms) * 变量非0代表存在未结束串口脉冲时间戳超时后熄灭LED并清零标记 */if(s_rs232_off_at!0u((int32_t)(now-s_rs232_off_at))0){LED_Write(RS232_LED_GPIO_Port,RS232_LED_Pin,0u);s_rs232_off_at0u;}}/** * brief 故障告警状态开关控制 * param active: 1触发故障FAULT灯10Hz快闪0清除故障FAULT灯直接熄灭 * note 【关联指引】本函数为 s_fault_active / s_fault_last 唯一赋值入口 * 两个变量在BSP_LED_Refresh()故障闪烁分支做读取判断控制FAULT灯周期翻转 */voidBSP_LED_SetFault(uint8_tactive){//上层要开启故障且当前原本无故障if(active!s_fault_active){s_fault_active1u;// 打开故障总开关s_fault_lastHAL_GetTick();// 记录故障触发时刻作为闪烁计时起点LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,1u);}//上层要清除故障且当前正处于故障状态elseif(!actives_fault_active){s_fault_active0u;// 关闭故障总开关LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,0u);}}/** * brief Modbus RS485总线通信脉冲触发 * note 【关联指引】本函数为 s_comm_off_at 唯一赋值入口 * s_comm_off_at HAL_GetTick() LED_PULSE_MS赋值后在BSP_LED_Refresh()脉冲分支做超时判断熄灭 * 在Modbus有效帧收发位置调用单次触发50ms点亮脉冲频繁收发会持续刷新超时保持常亮 */voidBSP_CommPulse(void){s_comm_off_atHAL_GetTick()LED_PULSE_MS;//记录LED_PULSE_MS后要熄灭的截止时间戳LED_Write(COMM_LED_GPIO_Port,COMM_LED_Pin,1u);//立刻点亮通信指示灯BSP_LED_Refresh()没有亮灯的动作要在这里亮灯}/** * brief RS232串口通信活动脉冲触发 * note 【关联指引】本函数为 s_rs232_off_at 唯一赋值入口 * s_rs232_off_at HAL_GetTick() LED_PULSE_MS赋值后在BSP_LED_Refresh()脉冲分支做超时判断熄灭 * 在RS232命令解析、数据收发位置调用单次触发50ms点亮脉冲 */voidBSP_RS232Pulse(void){s_rs232_off_atHAL_GetTick()LED_PULSE_MS;LED_Write(RS232_LED_GPIO_Port,RS232_LED_Pin,1u);}/** * brief 启动四路LED硬件自检全部同步点亮1.5s * note 【关联指引】本函数为 s_test_off_at 唯一赋值入口 * s_test_off_at HAL_GetTick() LED_TEST_MS赋值后在BSP_LED_Refresh()头部做自检优先级判断 * 自检优先级最高运行期间屏蔽所有闪烁、脉冲逻辑非阻塞1.5s后自动恢复常规灯效用于产线硬件接线校验 */voidBSP_LED_SelfTest(void){s_test_off_atHAL_GetTick()LED_TEST_MS;LED_Write(STATUS_LED_GPIO_Port,STATUS_LED_Pin,1u);LED_Write(COMM_LED_GPIO_Port,COMM_LED_Pin,1u);LED_Write(FAULT_LED_GPIO_Port,FAULT_LED_Pin,1u);LED_Write(RS232_LED_GPIO_Port,RS232_LED_Pin,1u);}