/** * @file app_flow.c * @author xxx * @date 2023-08-30 08:58:43 * @brief 此文件用于管理各个任务流程 * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. */ #include #include "app.h" #include "main.h" #include "flow.h" #include "tim.h" #include "filter.h" #include "lcds.h" #include "menus.h" #include "mode.h" #include "mode_diagnosis.h" #include "at_bluetooth.h" #include "bootload.h" #include "app_hart.h" // bootloader static struct flow bootload_system_fw; // BOOTLOAD系统流程 uint16_t scheduler_use_time = 0; /** * @brief 100毫秒定时中断处理函数 * * 当定时器到达100毫秒时,会触发此中断处理函数。 * 在该函数中,启动或重置定时器计数。 * @param cycle 定时器周期 毫秒 */ void scheduler_time_1s_irqhandler(uint8_t cycle) { DBG_ASSERT(cycle > 0 __DBG_LINE); static uint32_t cnt = 0; uint32_t time_ms = ++cnt * cycle; // 考虑是否要控制器工作的时候才计时 if (rt_save.dev_run_time_h < WORK_HOURS_MAX) { if (time_ms % 1000 == 0) { rt_save.dev_run_time_s++; // 工作时长 } if (rt_save.dev_run_time_s >= 3600) { rt_save.dev_run_time_h++; rt_save.dev_run_time_s = 0; } } // 控制过程中快速闪灯 if (mode_get()->interface_req.mode_control_idle() == FALSE) { if (time_ms % 200 == 0) { diagnosis_fault_indicate((diag_class_e)get_diagnosis_result()->priority); } } else { if (time_ms % 1000 == 0) { diagnosis_fault_indicate((diag_class_e)get_diagnosis_result()->priority); } } } /** * @brief bootload系统检测 * @param {struct flow *} fl * @return {*} */ static uint8_t bootload_systom_inspection(struct flow *fl) { FL_HEAD(fl); for (;;) { if (TRUE == BLE_IS_ENABLE()) { leds_off(LEDS_RED); leds_toggle(LEDS_GREEN); } else { leds_off(LEDS_GREEN); leds_toggle(LEDS_RED); } FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } #if HART_SOFTWARE_TEST_ENABLE == FALSE static struct flow sensor_fw; // 传感器检测 static struct flow business_fw; // 业务流程 static struct flow system_fw; // 系统检测 static struct flow idle_fw; // 空闲任务 // 时间戳更新 static void timestamp_update(uint8_t cycle) { BOOL ret = FALSE; rtc_date_t date; rtc_time_t time; uint32_t timestamp = 0; static uint8_t count = 0; if (count++ >= cycle) { count = 0; ret = rtc_get_datetime(&date, &time); if (ret == TRUE) { timestamp = time2stamp(&date, &time); if (timestamp > rt_data.seconds) { rt_save.real_time.date.year = date.year; rt_save.real_time.date.month = date.month; rt_save.real_time.date.day = date.day; rt_save.real_time.date.hour = time.hour; rt_save.real_time.date.minute = time.minute; rt_save.real_time.date.second = time.second; rt_data.seconds = timestamp; } // 如果rtc_get_datetime失败,则不需要额外操作,但可以在调试时记录 // else // { // // 记录错误或进行其他处理 // } } } } // 实时数据部分更新 static void rt_data_update(void) { rt_data.board_current = get_board_current(); rt_data.cpu_percent = scheduler_time_occupancy_get(1000); rt_data.cpu_temperature = get_cpu_temperature(); rt_data.cpu_volt = get_cpu_volt(); rt_data.mem_percent = my_mem_perused(SRAMIN); rt_data.dc = CPU_VREF * adc_raw[ADC_DCDC_CHANNEL] * 4 / ADC_MAX; rt_data.vdd = CPU_VREF * adc_raw[ADC_VDD_CHANNEL] * 4 / ADC_MAX; timestamp_update(3); // 这个周期数量根据外面的任务时间来定 } /** * @brief 菜单检测 * @return {*} * @note */ void menu_inspection(void) { if (lcd->info.need_build == TRUE) { lcd->info.need_build = FALSE; // need_build 在menu_build中被置位 menus_rebuild(); } menu_task(); } /** * @brief 图标检测 * @return {*} * @note */ static void icon_inspection(void) { if (FALSE == HART_IS_ENABLE()) { driver_icon_enable.bits.hart = 0; // 禁用HART } else { driver_icon_enable.bits.hart = 1; // 使能HART } if (FALSE == BLE_IS_ENABLE()) // 检查蓝牙是否已启用 { driver_icon_enable.bits.bluetooth = 0; // 禁用蓝牙 } else { driver_icon_enable.bits.bluetooth = 1; // 使能蓝牙 } driver_icon_enable.bits.work_mode = (uint8_t)udevice.control_mode; // 工作模式 // TODO 设备是否锁定检查 } static void bootload_start_inspection(void) { } // LCD 、LED检测 static void lcd_detection(float32 loop_current, float32 temperature) { BOOL lcd_close = FALSE, led_close = FALSE; // LCD扩展板必须接入 if (is_lcd_ext_board() == FALSE) { lcd_close = TRUE; rt_data.flag.bits.lcd_detect = FALSE; // GPS2000的LED在板子上,简单处理LED不要反初始化了 // led_close = TRUE; } else { rt_data.flag.bits.lcd_detect = TRUE; } if (gui_can_work() == FALSE) { lcd_close = TRUE; } if (*mode_get()->ctrl.mode == STOP_MODE) { lcd_close = TRUE; } /** * 检查温度是否在LCD的有效工作范围内。 * 如果温度低于最小值或高于最大值,则关闭LCD。 * * @param rt_data 包含温度值的实时数据结构。 */ if (temperature < temperature_c2unit(LCD_WORK_TEMP_MIN, udevice.temp_unit) || temperature > temperature_c2unit(LCD_WORK_TEMP_MAX, udevice.temp_unit)) { lcd_close = TRUE; } // 如果工作模式为停止模式,则关闭LCD if (*mode_get()->ctrl.mode == STOP_MODE) { lcd_close = TRUE; } if (lcd_close == TRUE) { gui_clr(); // 清除LCD lcd_dinit(); get_menus()->run_enable = FALSE; } else { lcd_init(); // 初始化LCD if (rt_data.flag.bits.lcd_detect == TRUE) // 检查LCD是否已关闭,如果是,则打开LCD { if (get_menus()->run_enable == FALSE) { #if LCD_DESIGN == FALSE menus_jump(MENUS_WORK, FALSE); // 跳转到工作界面 #endif } get_menus()->run_enable = TRUE; } else { get_menus()->run_enable = FALSE; } gui_set_scandir(udevice.display_direction); // 更新扫描方向 menus_set_scandir(udevice.display_direction); // 设置菜单显示方向 gui_open(); // 打开LCD } if (led_close == TRUE) { leds_dinit(); } else { leds_init(); // 初始化LED } } static void ble_detection(float32 loop_current, float32 temperature) { float32 ble_close = FALSE; // 判断当前电流是否大于等于3.8mA,如果是,则启动UART if (loop_current >= INPUT_CURRENT_MIN_UART) { driver_init(); // 初始化驱动 if (FALSE == HART_IS_ENABLE()) // 检查HART是否已启用,如果否,则初始化HART UART { hart_uart_init(); } else { // #if DEBUG_ENABLE == TRUE // static uint8_t hart_send_test_cnt = 0; // if (hart_send_test_cnt++ <= 2) // { // hart_write_test(); // } // #endif } } // 否则,关闭UART else { driver_dinit(); // 关闭驱动 hart_uart_dinit(); // 关闭HART UART } if (temperature < BLE_WORK_TEMP_MIN || temperature > BLE_WORK_TEMP_MAX) { ble_close = TRUE; } // 蓝牙 // 判断当前电流是否大于等于xx mA且工作模式在离线模式下,如果是,则启动蓝牙 if (udevice.wireless_enable == TRUE) { if ((loop_current >= BLE_CURRENT_WORK && udevice.control_mode == DIGITAL_CTRL_MODE) || (loop_current >= BLE_CURRENT_WORK && DEBUG_ENABLE == TRUE)) { if (FALSE == BLE_IS_ENABLE()) // 检查蓝牙是否已启用,如果否,则初始化蓝牙 { hart_ble_init(); delay_ms(500); } else { // 检查蓝牙是否正常工作 if (BIT_IS_CLR(bluetooth_state, BIT2)) { delay_ms(500); if (BIT_IS_CLR(bluetooth_state, BIT0)) { bluetooth_work(AT_CMD_TEST); delay_ms(500); } if (BIT_IS_SET(bluetooth_state, BIT0)) { // 检查蓝牙名称 bluetooth_work(AT_CMD_NAME_REQ); delay_ms(500); if (BIT_IS_CLR(bluetooth_state, BIT1)) { // 设置蓝牙名称 bluetooth_work(AT_CMD_NAME); } #if BLE_TYPE == BLE_TYPE_MX02 delay_ms(100); bluetooth_work(AT_CMD_TX_POWER); #endif BIT_SET(bluetooth_state, BIT2); } else { BIT_SET(bluetooth_state, BIT2); // 如果蓝牙被主动连接的话,上面的AT指令不会有响应 } } else { // bluetooth_work(100); } } } else { ble_close = TRUE; } } else { ble_close = TRUE; } if (ble_close == TRUE) { if (TRUE == BLE_IS_ENABLE()) { hart_ble_dinit(); // 关闭蓝牙 } bluetooth_state = BIT0; } } /************************************************ 以下为应用线程 ************************************************/ static uint8_t sensor_detection(struct flow *fl) { FL_HEAD(fl); static float32 current = 0.0f; static float32 temperature = 0.0f, humidity = 0.0f; for (;;) { scheduler_time_start(); // 计算当前电流,方法为读取ADC通道ADC_LOOP_CHANNEL的平均值并转换为浮点数 current = get_current_by_resistance(); // 获取当前温度 rt_data.temperature = get_temperature(); // 获取当前湿度 if (sht40_read(&temperature, &humidity) == TRUE) { rt_data.humidity = (uint16_t)humidity; } if (current < INPUT_CURRENT_RUN) // 待机状态是如果电流小于INPUT_CURRENT_MIN_MCU,则进行系统复位 { sys_soft_reset(); } else { if (current < SYSTEM_CLOCK_HIGHT_CURRENT_MIN) { rt_data.flag.bits.current_low = TRUE; } else { if (rt_data.flag.bits.current_low == TRUE) { #if LCD_DESIGN == FALSE menus_jump(MENUS_WORK, FALSE); // 跳转到工作界面 #endif } rt_data.flag.bits.current_low = FALSE; } // 蓝牙 ble_detection(current, rt_data.temperature); // LCD 、LED lcd_detection(current, rt_data.temperature); } scheduler_use_time = scheduler_time_stop(); FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } /** * @brief 系统检测 * @param {struct flow *} fl * @return {*} */ static uint8_t systom_inspection(struct flow *fl) { FL_HEAD(fl); static BOOL run_first = TRUE; for (;;) { scheduler_time_start(); // 图标检测 icon_inspection(); scheduler_use_time = scheduler_time_stop(); if (run_first == FALSE) { menus_set_language(udevice.display_language); // 参数复位检测 params_restart_inspection(); set_app_preload_language_flag(udevice.display_language); // 缓存语言实时更新,用于重启是第一时间判断语言 // 在停机模式下,不进行诊断 if (*mode_get()->ctrl.mode != STOP_MODE) { // 过程报警 1s一次(时间可以改) diagnosis_inspection(); // 第一次不做诊断,防止报错 // 故障处理 diagnosis_fault_deal(); } } else { run_first = FALSE; } scheduler_use_time = scheduler_time_stop(); bootload_start_inspection(); FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } /** * @brief 业务流程 * @param {flow} *fl * @return {*} */ static uint8_t business_inspection(struct flow *fl) { FL_HEAD(fl); for (;;) { scheduler_time_start(); // 实时数据更新 rt_data_update(); // 工作模式检测 mode_master_detection(); // 对外输出电流 mode_ctrl_output(); // HART检测 app_hart_inspection(); // KEIL窗口强制跳转到自整定流程,需要在这里做判断 if (mode_get()->interface_req.mode_is_adjusting() == TRUE && is_selftune_menu() == FALSE) { // 跳转到自动整定界面 menus_jump(MENUS_SELFTUNE, TRUE); } uart1_set_idel_handle_1_sec(); // 设置UART1空闲处理函数 noinit_data_set(); // 设置未初始化的数据 scheduler_use_time = scheduler_time_stop(); FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } /** * @brief 空闲任务用来计算CPU占用率和内存使用率 * @param {flow} *fl * @return {*} * @note */ static uint8_t idle_inspection(struct flow *fl) { FL_HEAD(fl); for (;;) { scheduler_time_start(); scheduler_use_time = scheduler_time_stop(); FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); } FL_TAIL(fl); } #endif #if HART_SOFTWARE_TEST_ENABLE == TRUE static struct flow hart_soft_test; // HART软件测试 static uint8_t hart_soft_test_inspection(struct flow *fl) { FL_HEAD(fl); for (;;) { // 模拟传感器数据 rt_data.loop_current = 5; rt_data.temperature = 20; rt_data.pressure_a = 210; rt_data.actual_travel = i2psb(rt_data.loop_current); rt_data.driver_signal = 50; rt_data.pressure_b = 210; rt_save.travel_set_pt = i2psb(rt_data.loop_current); rt_data.pressure_cross_point = 60; rt_data.pressure_s = 210; rt_data.target_travel = i2psb(rt_data.loop_current); rt_data.servo_feedback = 50; leds_toggle(LEDS_GREEN); FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); } FL_TAIL(fl); } #endif #if HART_HARDWARE_TEST_ENABLE == TRUE static struct flow hart_hardware_test; // HART硬件测试 static uint8_t hart_hardware_test_inspection(struct flow *fl) { FL_HEAD(fl); static uint8_t data[64]; for (;;) { if (rt_data.flag.bits.hart_rts_on == TRUE) { if (rt_data.flag.bits.hart_send_test != 0) { if (rt_data.flag.bits.hart_send_test == 1) { osel_memset(data, 0x00, ARRAY_LEN(data)); } else { osel_memset(data, 0xff, ARRAY_LEN(data)); } HART_RTS_OFF(); hart_get_handle()->interface.response(APP_UART_1, data, ARRAY_LEN(data)); } } FL_LOCK_DELAY(fl, FL_CLOCK_10MSEC); } FL_TAIL(fl); } #endif /** * @brief: 流程启动 * @return {*} */ void flow_start(void) { #if HART_HARDWARE_TEST_ENABLE == TRUE hart_hardware_test_inspection(&hart_hardware_test); // HART硬件测试流程 #elif HART_SOFTWARE_TEST_ENABLE == TRUE hart_soft_test_inspection(&hart_soft_test); // HART软件测试流程 // 参数复位检测 params_restart_inspection(); if (get_current_by_resistance() >= FAL_WRITE_CURRENT) { fal_execution_process(); // fal执行 } #else sensor_detection(&sensor_fw); systom_inspection(&system_fw); // 系统检测 business_inspection(&business_fw); // 业务流程检测 menus_process(); // 菜单处理 if (get_current_by_resistance() >= FAL_WRITE_CURRENT) { fal_execution_process(); // fal执行 } idle_inspection(&idle_fw); // 空闲任务用来计算CPU占用率 #endif } /** * @brief: bootload流程启动 * @return {*} */ void bootload_flow_start(void) { bootload_systom_inspection(&bootload_system_fw); // BOOTLOAD系统流程 if (BIT_IS_CLR(bluetooth_state, BIT2) == FALSE) { bootload_inspection(); // BOOTLOAD检测 if (bootload_timeout() == TRUE) { // 如果超时退出bootload模式 set_app_preload_bootload_flag(BOOTLOAD_UNSET_FLAG); leds_off_all(); } } } /** * @brief 初始化流程 * @return {*} */ void flow_init(void) { #if HART_HARDWARE_TEST_ENABLE == TRUE hart_uart_init(); FL_INIT(&hart_hardware_test); // HART硬件测试流程 #elif HART_SOFTWARE_TEST_ENABLE == TRUE hart_uart_init(); FL_INIT(&hart_soft_test); #else rt_data.flag.bits.current_low == TRUE; FL_INIT(&sensor_fw); // 电流检测 FL_INIT(&system_fw); // 系统检测 FL_INIT(&business_fw); // 业务流程 FL_INIT(&idle_fw); // 空闲任务 FL_INIT(&bootload_system_fw); // bootload系统流程 #endif }