STM32从零到量产开发:四路继电器工业控制模块开发— 继电器模块bsp_led.h与 bsp_led.c文件
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);}

相关新闻

物联网安全连接:A5000加密模块与PIC18F26K42的实战应用

物联网安全连接:A5000加密模块与PIC18F26K42的实战应用

1. 硬件选型与安全连接基础在物联网设备开发中,选择A5000加密模块与PIC18F26K42微控制器的组合并非偶然。这个搭配就像给数据传输装上了防弹装甲车——A5000提供军用级加密保护,而PIC18F26K42则确保整个系统稳定可靠地运行。1.1 A5000加密模块的核心优势…

2026/10/28 0:57:09 阅读更多 →
淘天二面追问:Agentic RAG和普通RAG差在哪?不是加个智能体那么简单

淘天二面追问:Agentic RAG和普通RAG差在哪?不是加个智能体那么简单

前言 淘天二面这道题最近在 AI 求职圈反复出现。表面问"Agentic RAG 和普通 RAG 的区别",但只要答出"加个智能体让它自己决定检索几次",面试官就会端起水杯沉默——那种沉默比骂你一顿还难受。 Agentic RAG 不是在普通 RAG 上面&q…

2026/10/28 17:20:10 阅读更多 →
Send.wang 使用教程:免安装跨平台文件互传神器

Send.wang 使用教程:免安装跨平台文件互传神器

Send.wang 使用教程:免安装跨平台文件互传神器手机电脑之间传文件,还在用微信「文件传输助手」?还在插数据线?还在登录云盘上传再下载? Send.wang 让你打开网页、扫码即传——免安装、免注册、不限大小、点对点直连&am…

2026/10/28 12:32:13 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/28 7:28:00 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/28 9:02:11 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/28 9:00:54 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/28 7:29:02 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 16:58:40 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 9:01:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 19:19:37 阅读更多 →