/****************************************************************************** * @file main.c * @brief DTU 主程序 - 屏幕与按键控制 * @details 本文件实现了 DTU 设备的主程序逻辑,包括: * - 系统初始化(时钟、外设、看门狗等) * - 按键事件处理与业务逻辑 * - RS485 Modbus 通信处理 * - 定时器中断服务(5ms 周期) * - 系统运行指示灯控制 * - 看门狗喂狗与系统复位保护 * @author 阜阳师范大学物电学院 * @version V0.1 * @date 2026.1.19 * @note 定时器周期:5ms * 系统复位时间:约 5000 秒(1000000 × 5ms) * 通信协议:Modbus RTU over RS485 ******************************************************************************/ #include "main.h" /* ============================================================================ * 全局变量定义 * ============================================================================ */ volatile static uint32_t sysRunTime = 0; /**< 系统运行时间计数器(单位:5ms) */ volatile static KEY_TYPE keyStatus = KEY_NONE; /**< 按键状态指示(当前按键值) */ volatile static KEY_TYPE keyStatusBack = KEY_NONE; /**< 按键状态指示(当前按键值) */ volatile static uint8_t LED_ToggleFlag = 0; /**< LED 闪烁定时标志位(1=需要翻转) */ /* ============================================================================ * 内部函数实现 * ============================================================================ */ /** * @brief 按键业务逻辑回调函数 * @param key_type 按键类型(KEY_TYPE 枚举值) * @note 当检测到按键事件时,由按键驱动层调用此函数 * 处理流程: * 1. 打开背光(任意按键按下都打开背光) * 2. 显示按键按下指示(KeyRun_Disp) * 3. 重置按键显示计时器 * 4. 更新按键状态(供主循环使用) * @retval 无 */ static void Key_ProcessCallback(KEY_TYPE key_type) { BackLight_ON(); /**< 任意按键按下,都打开背光 */ keyStatus = key_type; /**< 更新按键状态,供主循环处理 */ } /* ============================================================================ * 主程序入口 * ============================================================================ */ /** * @brief 主函数 * @note 系统初始化流程: * 1. HAL 库初始化 * 2. 系统时钟配置(72MHz) * 3. 延时函数初始化 * 4. LED 初始化 * 5. 按键驱动初始化 * 6. 看门狗初始化 * 7. RS485 通信初始化 * 8. LCD 初始化 * 9. Modbus 通信任务初始化 * 10. 显示存储的 LOGO * 11. 定时器初始化(5ms 周期) * 12. 注册按键回调函数 * * 主循环处理: * - 连接状态下的 LED 指示灯闪烁 * - RS485 Modbus 通信处理(包含按键上报) * - 系统运行时间监控与自动复位保护 * * 定时器中断(5ms)处理: * - 系统运行时间计数 * - LED 闪烁标志更新 * - 按键检测扫描 * - 看门狗喂狗 * - 背光关闭检测 * - Modbus 轮询计数 * - 按键显示自动关闭 * @retval 无(永不返回) */ int main(void) { /* ========== 系统初始化 ========== */ HAL_Init(); /**< 初始化 HAL 库 */ sys_stm32_clock_init(RCC_PLL_MUL9); /**< 设置系统时钟,72MHz */ delay_init(72); /**< 延时函数初始化(基于 72MHz 时钟) */ /* ========== 外设初始化 ========== */ LED_Init(); /**< LED 灯初始化 */ Key_Init(); /**< 初始化按键驱动 */ WDog_Init(); /**< 看门狗初始化 */ RS485_DMA_init(); /**< RS485 初始化(DMA 方式) */ LcdInit(); /**< LCD 初始化 */ /* ========== 通信与显示初始化 ========== */ Process_Init(); /**< Modbus 通信任务初始化 */ /* ========== 定时器与回调注册 ========== */ gtim_timx_int_init(50-1, 7200-1); /**< 定时器初始化:5ms 周期(50×0.1ms,7200 分频) */ Key_RegisterCallback(Key_ProcessCallback); /**< 注册按键回调函数 */ /* ========== 主循环 ========== */ while (1) { if (LED_ToggleFlag == 1) { LED_ToggleFlag = 0; /**< 清除闪烁标志 */ // LED_Toggle(15); /**< 翻转运行指示灯 */ } /* 快速的处理 keyStatus 的状态,避免与中断处理冲突*/ if(keyStatus != KEY_NONE) { keyStatusBack = keyStatus; keyStatus = KEY_NONE; } /* RS485 Modbus 通信处理(包含按键上报) */ RS485_Process(keyStatusBack); keyStatusBack = KEY_NONE; /* 系统运行时间监控与自动复位保护 */ if (sysRunTime > 1000000) /**< 约 5000 秒(1000000 × 5ms) */ { HAL_NVIC_SystemReset(); /**< 系统立即复位(防止长时间运行异常) */ sysRunTime = 0; } } } /* ============================================================================ * 中断服务函数 * ============================================================================ */ /** * @brief 定时器中断服务函数(5ms 周期) * @note 在定时器溢出中断中执行以下任务: * 1. 系统运行时间计数(sysRunTime++) * 2. LED 闪烁标志更新(每 200 次中断,即 1 秒) * 3. 按键检测扫描(Button_Ticks) * 4. 看门狗喂狗(Clear_Watchdog) * 5. 背光关闭检测(BackLight_Close) * 6. Modbus 轮询计数(Process_Count) * 7. 按键显示自动关闭(KeyRun_Disp_Close) * * 定时器配置:5ms 周期 * 中断标志:TIM_FLAG_UPDATE(定时器溢出标志) * @retval 无 */ void GTIM_TIMX_INT_IRQHandler(void) { /* 判断定时器溢出中断标志位 */ if (__HAL_TIM_GET_FLAG(&g_timx_handle, TIM_FLAG_UPDATE) != RESET) { sysRunTime++; /**< 系统运行时间计数递增 */ /* LED 闪烁标志更新:每 200 次中断(1 秒)翻转一次 */ if (sysRunTime % 200 == 0) { LED_ToggleFlag = 1; /**< 设置 LED 闪烁标志 */ } Button_Ticks(); /**< 按键检测扫描(MultiButton 库) */ Clear_Watchdog(); /**< 看门狗喂狗 */ BackLight_Close(); /**< 背光关闭检测 */ Process_Count(); /**< Modbus 通信轮询计数 */ __HAL_TIM_CLEAR_IT(&g_timx_handle, TIM_IT_UPDATE); /**< 清除定时器溢出中断标志 */ } }