/** * @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 "flow.h" #include "app.h" #include "main.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" #include "file_storage.h" uint16_t scheduler_use_time = 0; /** * @brief 100毫秒定时中断处理函数 * * 当定时器到达100毫秒时,会触发此中断处理函数。 * 在该函数中,启动或重置定时器计数。 * @param cycle 定时器周期 毫秒 */ void scheduler_time_irqhandler(uint8_t cycle) { DBG_ASSERT(cycle > 0 __DBG_LINE); static uint32_t cnt = 0; uint32_t time_ms = ++cnt * cycle; BOOL flag_1s = (time_ms % 1000 == 0) ? TRUE : FALSE; BOOL flag_200ms = (time_ms % 200 == 0) ? TRUE : FALSE; // 考虑是否要控制器工作的时候才计时 if (rt_save.dev_run_time_h < WORK_HOURS_MAX) { if (flag_1s) { 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; } } else { rt_save.dev_run_time_h = WORK_HOURS_MAX; rt_save.dev_run_time_s = 0; } // 控制过程中快速闪灯 if (mode_get()->interface_req.mode_control_idle() == FALSE) { if (flag_200ms) { diagnosis_fault_indicate((diag_class_e)get_diagnosis_result()->priority); } } else { if (flag_1s) { diagnosis_fault_indicate((diag_class_e)get_diagnosis_result()->priority); } } if (flag_1s) { hart_timer_1s(); } if (cnt >= 10000) { cnt -= 10000; } } #if HART_HARDWARE_TEST_ENABLE == TRUE static struct flow hart_hardware_test_handle; // HART硬件测试任务句柄 static uint8_t hart_hardware_test_task(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_TAIL(fl); } #elif HART_SOFTWARE_TEST_ENABLE == TRUE static struct flow hart_soft_test_handle; // HART软件测试任务句柄 static uint8_t hart_soft_test_task(struct flow *fl) { float32 limit = 0.0f; float32 coefficient = 0.0f; hart_device_variable_t* pv = NULL; FL_HEAD(fl); for (;;) { if (hart_device_attribute.simulation_command52 == COMMAND_187_SET_VARIABLE_CLOSE_TO_LOWER_RANGE_VALUE) { coefficient = 0.02f; // 设置传感器输入接近零测量值。该值必须足够接近零测量值,以便设备能够重新归零其校准,但必须大于其当前校准的正常测量范围1% pv = get_device_variable(DIN_ANALOG_INPUT); // 输入电流 limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.loop_current = pv->attribute.lower_range_value + limit; pv = get_device_variable(DIN_INTERNAL_TEMPERATURE); // 温度 limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.temperature = pv->attribute.lower_range_value + limit; rt_data.actual_travel = i2psb(rt_data.loop_current); rt_save.travel_set_pt = i2psb(rt_data.loop_current); rt_data.target_travel = i2psb(rt_data.loop_current); pv = get_device_variable(DIN_SUPPLY_PRESSURE); // 供气压力 limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.pressure_s = pv->attribute.lower_range_value + limit; pv = get_device_variable(DIN_PRESSURE_PORT_A); // A路压力 limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.pressure_a = pv->attribute.lower_range_value + limit; pv = get_device_variable(DIN_PRESSURE_PORT_B); // B路压力 limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.pressure_b = pv->attribute.lower_range_value + limit; pv = get_device_variable(DIN_DRIVE_SIGNAL); // 驱动信号(百分比) limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.driver_signal = pv->attribute.lower_range_value + limit; pv = get_device_variable(DIN_DIFFERENTIAL_PRESSURE); // 压力A减压力B limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.pressure_cross_point = pv->attribute.lower_range_value + limit; pv = get_device_variable(DIN_PRIMARY_FEEDBACK); // 伺服反馈(和实际行程的值一样) limit = (pv->attribute.upper_range_value - pv->attribute.lower_range_value) * coefficient; rt_data.servo_feedback = pv->attribute.lower_range_value + limit; } else if (hart_device_attribute.simulation_command52 == COMMAND_187_SET_VARIABLE_BELOW_LOWER_TRANSDUCER_LIMIT) { coefficient = 0.1f; // 设置传感器输入值远低于下限,设备无法将其校准重新定为零 pv = get_device_variable(DIN_ANALOG_INPUT); // 输入电流 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.loop_current = pv->transducer.lower_limit.f - limit; pv = get_device_variable(DIN_INTERNAL_TEMPERATURE); // 温度 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.temperature = pv->transducer.lower_limit.f - limit; rt_data.actual_travel = i2psb(rt_data.loop_current); rt_save.travel_set_pt = i2psb(rt_data.loop_current); rt_data.target_travel = i2psb(rt_data.loop_current); pv = get_device_variable(DIN_SUPPLY_PRESSURE); // 供气压力 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_s = pv->transducer.lower_limit.f - limit; pv = get_device_variable(DIN_PRESSURE_PORT_A); // A路压力 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_a = pv->transducer.lower_limit.f - limit; pv = get_device_variable(DIN_PRESSURE_PORT_B); // B路压力 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_b = pv->transducer.lower_limit.f - limit; pv = get_device_variable(DIN_DRIVE_SIGNAL); // 驱动信号(百分比) limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.driver_signal = pv->transducer.lower_limit.f - limit; pv = get_device_variable(DIN_DIFFERENTIAL_PRESSURE); // 压力A减压力B limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_cross_point = pv->transducer.lower_limit.f - limit; pv = get_device_variable(DIN_PRIMARY_FEEDBACK); // 伺服反馈(和实际行程的值一样) limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.servo_feedback = pv->transducer.lower_limit.f - limit; } else if (hart_device_attribute.simulation_command52 == COMMAND_187_SET_VARIABLE_ABOVE_UPPER_TRANSDUCER_LIMIT) { coefficient = 0.1f; // 设置传感器输入值远高于下限,设备无法将其校准重新定为零 pv = get_device_variable(DIN_ANALOG_INPUT); // 输入电流 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.loop_current = pv->transducer.upper_limit.f + limit; pv = get_device_variable(DIN_INTERNAL_TEMPERATURE); // 温度 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.temperature = pv->transducer.upper_limit.f + limit; rt_data.actual_travel = i2psb(rt_data.loop_current); rt_save.travel_set_pt = i2psb(rt_data.loop_current); rt_data.target_travel = i2psb(rt_data.loop_current); pv = get_device_variable(DIN_SUPPLY_PRESSURE); // 供气压力 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_s = pv->transducer.upper_limit.f + limit; pv = get_device_variable(DIN_PRESSURE_PORT_A); // A路压力 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_a = pv->transducer.upper_limit.f + limit; pv = get_device_variable(DIN_PRESSURE_PORT_B); // B路压力 limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_b = pv->transducer.upper_limit.f + limit; pv = get_device_variable(DIN_DRIVE_SIGNAL); // 驱动信号(百分比) limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.driver_signal = pv->transducer.upper_limit.f + limit; pv = get_device_variable(DIN_DIFFERENTIAL_PRESSURE); // 压力A减压力B limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.pressure_cross_point = pv->transducer.upper_limit.f + limit; pv = get_device_variable(DIN_PRIMARY_FEEDBACK); // 伺服反馈(和实际行程的值一样) limit = (pv->transducer.upper_limit.f - pv->transducer.lower_limit.f) * coefficient; rt_data.servo_feedback = pv->transducer.upper_limit.f + limit; } else { // 真实的值 rt_data.loop_current = get_current(FILTER_AVERAGE); rt_data.temperature = get_temperature(); rt_data.actual_travel = i2psb(rt_data.loop_current); rt_save.travel_set_pt = i2psb(rt_data.loop_current); rt_data.target_travel = i2psb(rt_data.loop_current); rt_data.pressure_s = trim_pressure_point(DIN_SUPPLY_PRESSURE, pressure_kpa2unit(get_pressure(PRESSURE_PARAM_S), udevice.press_unit), udevice.press_unit); rt_data.pressure_a = trim_pressure_point(DIN_PRESSURE_PORT_A, pressure_kpa2unit(get_pressure(PRESSURE_PARAM_A), udevice.press_unit), udevice.press_unit); rt_data.pressure_b = trim_pressure_point(DIN_PRESSURE_PORT_B, pressure_kpa2unit(get_pressure(PRESSURE_PARAM_B), udevice.press_unit), udevice.press_unit); rt_data.driver_signal = 0; rt_data.pressure_cross_point = 0; rt_data.servo_feedback = 0; } leds_toggle(LEDS_GREEN); FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } #else static struct flow sensor_task_handle; // 传感器任务句柄 static struct flow business_task_handle; // 业务任务句柄 static struct flow system_task_handle; // 系统任务句柄 static struct flow menu_task_handle; // 菜单任务句柄 // 时间戳更新 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 = 0x64; if (count++ >= cycle) { count = 0; ret = rtc_get_datetime(&date, &time); if (ret == TRUE) { timestamp = time2stamp(&date, &time); if (timestamp > rt_data.timestamp) { 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.timestamp = timestamp; } // 如果rtc_get_datetime失败,则不需要额外操作,但可以在调试时记录 // else // { // // 记录错误或进行其他处理 // } rt_data.flag.bits.real_time_idel = TRUE; } } } // 实时数据部分更新 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); // 这个周期数量根据外面的任务时间来定 } static void rt_save_update(void) { if (is_run_max_time() == TRUE) { udevice.control_mode = WAIT_MODE; // 设备已经达到通电时间的上限,自动切换到待机模式 } rt_save.diagnosis_log_node_write_count = file_storage_block_get(&nvm1_file_storage, FILE_BLOCK_DIAGNOSIS_LOG)->params.used_node; rt_save.diagnosis_log_node_start_offset_index = file_storage_block_get(&nvm1_file_storage, FILE_BLOCK_DIAGNOSIS_LOG)->params.start_node; } static void ble_detection(float32 loop_current, float32 temperature) { float32 ble_close = FALSE; uint8_t wireless_id[WIRELESS_ID_LEN]; // 判断当前电流是否大于等于3.8mA,如果是,则启动UART if (loop_current >= INPUT_CURRENT_MIN_UART) { driver_init(); // 初始化驱动 if (FALSE == HART_IS_ENABLE()) // 检查HART是否已启用,如果否,则初始化HART UART { hart_uart_init(); } } // 否则,关闭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 (wireless_can_work(loop_current) == TRUE) { if (FALSE == BLE_IS_ENABLE()) // 检查蓝牙是否已启用,如果否,则初始化蓝牙 { hart_ble_init(); } else { // 检查蓝牙是否正常工作 if (BIT_IS_CLR(bluetooth_state, BIT7)) { delay_ms(500); if (BIT_IS_CLR(bluetooth_state, BIT0)) { // 读取蓝牙MAC地址 bluetooth_work(AT_GET_MAC); delay_ms(500); } if (BIT_IS_SET(bluetooth_state, BIT0)) { osel_memset(wireless_id, 0, WIRELESS_ID_LEN); // 设置MAC地址 at_get_memcmp_cache(wireless_id, WIRELESS_ID_LEN); if (wireless_id[0] != 0 && wireless_id[1] != 0) { if (osel_memcmp(wireless_id, (uint8_t*)&udevice.wireless_id, WIRELESS_ID_LEN) != 0) { osel_memcpy((uint8_t*)&udevice.wireless_id, wireless_id, WIRELESS_ID_LEN); } } // 检查蓝牙名称 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(500); bluetooth_work(AT_CMD_TX_POWER); #endif BIT_SET(bluetooth_state, BIT7); } else { BIT_SET(bluetooth_state, BIT7); // 如果蓝牙被主动连接的话,上面的AT指令不会有响应 } } else { // bluetooth_work(100); } } } else { ble_close = TRUE; } if (ble_close == TRUE) { if (TRUE == BLE_IS_ENABLE()) { hart_ble_dinit(); // 关闭蓝牙 } bluetooth_state = 0; rt_data.flag.bits.ble_on = FALSE; } else { rt_data.flag.bits.ble_on = TRUE; } } // 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; } 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 } } /** * @brief 图标检测 * @return {*} * @note */ static void icon_inspection(void) { if (rt_data.flag.bits.hart_on == FALSE) { driver_icon_enable.bits.hart = 0; // 禁用HART } else { driver_icon_enable.bits.hart = 1; // 使能HART } if (rt_data.flag.bits.ble_on == FALSE) // 检查蓝牙是否已启用 { driver_icon_enable.bits.bluetooth = 0; // 禁用蓝牙 } else { driver_icon_enable.bits.bluetooth = 1; // 使能蓝牙 } driver_icon_enable.bits.work_mode = (uint8_t)udevice.control_mode; // 工作模式 driver_icon_enable.bits.write_protect = get_device_write_protect(); // 是否写保护 driver_icon_enable.bits.lock = get_device_lock(); // 是否锁定 } /*********************************************************************************************** */ static uint8_t sensor_task(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.loop_current = current; rt_data.show_loop = current; // 获取当前温度 rt_data.temperature = get_temperature(); // 更新设备最小、最大温度 update_device_temp_min_max(rt_data.temperature); // 获取当前湿度 if (sht40_read(&temperature, &humidity) == TRUE) { rt_data.humidity = (uint16_t)humidity; rt_data.temperature2 = temperature; } 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); } static uint8_t business_task(struct flow *fl) { FL_HEAD(fl); for (;;) { scheduler_time_start(); if (in_correct_model()) { rt_data_update(); // 实时数据更新 rt_save_update(); // 实时数据存储更新 mode_master_detection(); // 工作模式检测 app_hart_inspection(); // HART检测 uart1_set_idel_handle_1_sec(); // 设置UART1空闲处理函数 params_storage_update(); // 存储数据更新 if (mode_get()->interface_req.mode_is_adjusting() == TRUE && is_selftune_menu() == FALSE) // KEIL窗口强制跳转到自整定流程,需要在这里做判断 { menus_jump(MENUS_SELFTUNE, TRUE); // 跳转到自动整定界面 } } scheduler_use_time = scheduler_time_stop(); FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } static uint8_t system_task(struct flow *fl) { FL_HEAD(fl); static BOOL run_first = TRUE; for (;;) { scheduler_time_start(); if (rt_data.flag.bits.dbg_assert_reset == TRUE) { DBG_ASSERT(FALSE __DBG_LINE); } // 图标检测 icon_inspection(); if (run_first == FALSE) { menus_set_language(udevice.display_language); // 参数复位检测 params_restart_inspection(); set_app_preload_language_flag(udevice.display_language); // 缓存语言实时更新,用于重启是第一时间判断语言 // 诊断同步 diagnosis_synchronous(); // 在停机模式下,不进行诊断 if (*mode_get()->ctrl.mode != STOP_MODE) { // 过程报警 1s一次(时间可以改) diagnosis_inspection(); // 第一次不做诊断,防止报错 // 故障处理 diagnosis_fault_deal(); } } else { run_first = FALSE; } current_limit_to_travel(); // 电流限制到行程 scheduler_use_time = scheduler_time_stop(); FL_LOCK_DELAY(fl, FL_CLOCK_SEC); } FL_TAIL(fl); } static uint8_t menu_process_task(struct flow *fl) { FL_HEAD(fl); for (;;) { scheduler_time_start(); // 菜单处理 menus_process(); scheduler_use_time = scheduler_time_stop(); FL_LOCK_DELAY(fl, MENU_TICKS / FL_HARD_TICK); } FL_TAIL(fl); } #endif /** * @brief 初始化流程 * @return {*} */ void flow_init(void) { #if HART_HARDWARE_TEST_ENABLE == TRUE hart_uart_init(); udevice.wireless_enable = TRUE; FL_INIT(&hart_hardware_test_handle); #elif HART_SOFTWARE_TEST_ENABLE == TRUE hart_uart_init(); FL_INIT(&hart_soft_test_handle); #else rt_data.flag.bits.current_low = TRUE; FL_INIT(&system_task_handle); FL_INIT(&business_task_handle); FL_INIT(&business_task_handle); FL_INIT(&menu_task_handle); #endif } void flow_start(void) { #if HART_HARDWARE_TEST_ENABLE == TRUE hart_hardware_test_task(&hart_hardware_test_handle); #elif HART_SOFTWARE_TEST_ENABLE == TRUE hart_soft_test_task(&hart_soft_test_handle); #else sensor_task(&sensor_task_handle); business_task(&business_task_handle); system_task(&system_task_handle); menu_process_task(&menu_task_handle); #endif }