This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/app_flow.c

679 lines
18 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file app_flow.c
* @author xxx
* @date 2023-08-30 08:58:43
* @brief 此文件用于管理各个任务流程
* @copyright Copyright (c) 2023 by xxx, All Rights Reserved.
*/
#include <math.h>
#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
}