/** * @file app_hart.c * @author xxx * @date 2023-07-06 13:08:52 * @brief 此文件主要实现板卡的HART功能 * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. */ #include "app.h" #include "hart.h" #include "hart_frame.h" #include "uarts.h" #include "test_bsp.h" #include "at_bluetooth.h" #include "menus.h" #include "bootload.h" #include "ymodem.h" #include "flow.h" #include "app_hart.h" #include #include "app_hart_user.h" #define HART_UART_RXSIZE (240u) #define BLE_UART_RXSIZE (1100u) // 接收1100个字节,考虑到BOOTLOAD需要接收大量数据,在RAM允许的情况下,可以适当增大 #define HART_UART_TXSIZE (240u) // 发送240个字节 uart_t *uarts[APP_UART_MAX]; static void _get_real_time_clock(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec); static void update_device_status(void); // 更新其他设备状态 /** * @brief 处理用户自定义事件 * * @param event 用户自定义事件类型 * @param data 用户自定义事件数据 * * @return 返回处理结果 */ static BOOL _user_common_event(hart_interface_user_event_e event, const void *const data) { return hart_user_handle(event, data); } /** * @brief 发送数据(hart协议数据帧) * @param {uint8_t} *txBuf * @param {uint16_t} len * @return {*} */ static void _response(uint8_t uart_index, uint8_t *data, uint16_t len) { #ifdef STM32 rt_data.flag.bits.hart_rts_on = FALSE; uart_send_data(uarts[uart_index], data, len); uart_data_storage_reset(uarts[uart_index]); #else LOG_HEX(data, len); #endif } /** * @brief 获取指定UART的错误计数 * * 根据UART索引获取指定UART的错误计数。 * * @param uart_index UART索引 * * @return 如果定义了STM32宏,则返回指定UART的错误计数;否则返回0 */ static uint16_t _uart_error_count(uint8_t uart_index) { #ifdef STM32 return uart_get_error_count(uarts[uart_index]); #else return 0; #endif } static void _uart_errors(uint8_t uart_index, hart_uart_error_t *errors) { uint16_t count = uart_get_error_count(uarts[uart_index]); if (count > 0) { uarts_interupt_error_t *uart_errors = uart_get_error(uarts[uart_index]); if (uart_errors != NULL) { for (uint16_t i = 0; i < count; i++) { errors[i].uart_error = (hart_uarts_interupt_error_e)uart_errors[i].err; errors[i].rx_index = uart_errors[i].index; } } } } static void _frame_data_parse_time_start(uint16_t timer_period) { ENABLE_TIM(HART_TIM); hart_timer_start(timer_period); } /** * @brief 获取时间戳 * @return {*} */ static uint32_t _get_timestamp(void) { uint8_t year, month, day, hour, min, sec; uint32_t stamp; rtc_date_t date; rtc_time_t time; _get_real_time_clock(&year, &month, &day, &hour, &min, &sec); date.year = year; date.month = month; date.day = day; time.hour = hour; time.minute = min; time.second = sec; stamp = time2stamp(&date, &time); return stamp; } /** * @brief flash读取接口 * @param {uint32_t} addr * @param {uint8_t} *data * @param {uint16_t} len * @return {*} */ static BOOL _flash_read(hart_storage_e index, uint8_t *data) { BOOL res = FALSE; switch (index) { case HART_STORAGE_PARAMS: res = storage_read_all(hart_attribute_storage, data); break; case HART_STORAGE_VARIABLE: res = storage_read_all(hart_variable_storage, data); break; case HART_STORAGE_CONSTANT: res = storage_read_all(hart_constant_storage, data); break; case HART_STORAGE_STANDARD_VARIABLE: res = storage_read_all(hart_standard_variable_storage, data); break; default: break; } return res; } /** * @brief flash写入接口 * @param {uint32_t} addr * @param {uint8_t} *data * @param {uint16_t} len * @return {*} */ static BOOL _flash_write(hart_storage_e index, uint8_t *data) { BOOL res = FALSE; switch (index) { case HART_STORAGE_PARAMS: res = storage_write_all(hart_attribute_storage, data); if (storage_check_all(hart_attribute_storage, data) == FALSE) { rt_data.flag.bits.hart_attribute_storage = FALSE; } break; case HART_STORAGE_VARIABLE: res = storage_write_all(hart_variable_storage, data); if (storage_check_all(hart_variable_storage, data) == FALSE) { rt_data.flag.bits.hart_variable_storage = FALSE; } break; case HART_STORAGE_CONSTANT: res = storage_write_all(hart_constant_storage, data); if (storage_check_all(hart_constant_storage, data) == FALSE) { rt_data.flag.bits.hart_constant_storage = FALSE; } break; case HART_STORAGE_STANDARD_VARIABLE: res = storage_write_all(hart_standard_variable_storage, data); if (storage_check_all(hart_standard_variable_storage, data) == FALSE) { rt_data.flag.bits.hart_standard_variable_storage = FALSE; } break; default: break; } return res; } static BOOL _flash_read_item(hart_storage_e index, uint8_t item, uint8_t *data) { BOOL res = FALSE; switch (index) { case HART_STORAGE_PARAMS: res = storage_read(hart_attribute_storage, item, data); break; case HART_STORAGE_VARIABLE: res = storage_read(hart_variable_storage, item, data); break; case HART_STORAGE_CONSTANT: res = storage_read(hart_constant_storage, item, data); break; case HART_STORAGE_STANDARD_VARIABLE: res = storage_read(hart_standard_variable_storage, item, data); break; default: break; } return res; } static BOOL _flash_write_item(hart_storage_e index, uint8_t item, uint8_t *data) { BOOL res = FALSE; switch (index) { case HART_STORAGE_PARAMS: res = storage_write(hart_attribute_storage, item, data); if (storage_check(hart_attribute_storage, item, data) == FALSE) { rt_data.flag.bits.hart_attribute_storage = FALSE; } break; case HART_STORAGE_VARIABLE: res = storage_write(hart_variable_storage, item, data); if (storage_check(hart_variable_storage, item, data) == FALSE) { rt_data.flag.bits.hart_variable_storage = FALSE; } break; case HART_STORAGE_CONSTANT: res = storage_write(hart_constant_storage, item, data); if (storage_check(hart_constant_storage, item, data) == FALSE) { rt_data.flag.bits.hart_constant_storage = FALSE; } break; case HART_STORAGE_STANDARD_VARIABLE: res = storage_write(hart_standard_variable_storage, item, data); if (storage_check(hart_standard_variable_storage, item, data) == FALSE) { rt_data.flag.bits.hart_standard_variable_storage = FALSE; } break; default: break; } return res; } /** * @brief 执行自检 * @param {*} * @return {*} */ static void _perform_self_test(void) { // power_on_diagnosis(); // 是否需要延时回复 menus_show_custom_window(SET_CUSTOM_SELF_TEST); } /** * @brief 设备复位 * @param {*} * @return {*} */ static void _device_reset(void) { get_menus()->accelerate = TRUE; menus_show_custom_window(SET_CUSTOM_RESET); } /** * @brief 设备呼叫,0一直呼叫,1-255秒 * @param {*} * @return {*} */ static void _squawk_control(BOOL open, uint8_t second) { } /** * @brief 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应command74 * @param {*} * @return {*} */ static BOOL _armed(void) { return TRUE; } static void _set_real_time_clock(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) { set_real_time(year, month, day, hour, min, sec); } static void _get_real_time_clock(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec) { get_real_time(year, month, day, hour, min, sec); } /** * @brief 设置动态变量 * @return {*} */ static BOOL _set_dynamics(device_variable_dynamics_t *const dynamics) { // HART自带部分 // 下面是用户自定义部分 return TRUE; } /** * @brief 蓝牙输出 * @param {uint8_t} *data * @param {uint16_t} len * @return {*} * @note */ void bluetooth_output(uint8_t *data, uint16_t len) { DBG_ASSERT(data != NULL __DBG_LINE); if (len == 0) { return; } else { if (SystemCoreClock == SYSTEM_CLOCK_HIGHT) { return; } if (uarts[APP_UART_2] != NULL && BLE_IS_ENABLE() == TRUE) { uart_send_data(uarts[APP_UART_2], data, len); } } } void h24_bluetooth_output_dbg(uint8_t *data, uint16_t len) { DBG_ASSERT(data != NULL __DBG_LINE); if (len == 0) { return; } else { #if DEBUG_ENABLE == TRUE if (BIT_IS_SET(bluetooth_state, BIT2)) { bluetooth_output(data, len); } #endif } } void hart_write_test(void) { #define TEST_LEN 10 uint8_t buf[TEST_LEN]; osel_memset(buf, 0, ARRAY_LEN(buf)); buf[0] = 0xFF; buf[1] = 0xFF; buf[2] = 0xFF; buf[3] = 0xFF; buf[4] = 0xFF; buf[5] = 0xaa; buf[6] = 0xbb; buf[7] = 0xD5; buf[8] = 0xC8; buf[TEST_LEN - 1] = 0xce; _response(APP_UART_1, buf, TEST_LEN); } /** * @brief 蓝牙H24模块配置工作 * @return {*} * @note */ void bluetooth_work(uint8_t index) { uint8_t len = 0; char data[128]; osel_memset((uint8_t *)data, 0, 128); // HC42蓝牙模块设置名称总长度不超过 12 字节 MX02蓝牙模块设置名称总长度不超过 20 字节 #if BOOTLOAD char device_id[] = "BOOTLOAD"; #else char device_id[HART_PACKED12_LEN + 1]; osel_memset((uint8_t *)device_id, 0, HART_PACKED12_LEN); sprintf(device_id, "%s", DESCRIPTOR); uint8_t use_offset = osel_mstrlen(DESCRIPTOR); assic_to_str((uint8_t *)&udevice.dev_serial_num[INST_SERIAL_NUM_LEN - (HART_PACKED12_LEN - use_offset)], HART_PACKED12_LEN - use_offset, (uint8_t *)&device_id[use_offset]); device_id[HART_PACKED12_LEN] = 0; #endif #if BLE_TYPE == BLE_TYPE_HC42 char *test_cmd[AT_END] = { "AT", "AT+NAME", "AT+NAME=%s", "AT+RESET", }; #elif BLE_TYPE == BLE_TYPE_MX02 char *test_cmd[AT_END] = { "AT+VER?\r\n", "AT+NAME?\r\n", "AT+NAME=%s\r\n", "AT+TXPOWER=0\r\n", }; #else // 编译时输出错误提示 #error "BLE_TYPE 类型错误" #endif switch (index) { case AT_CMD_TEST: // 测试指令 { bluetooth_state = 0; sprintf(data, test_cmd[AT_CMD_TEST]); len = osel_mstrlen((unsigned char *)data); bluetooth_output((uint8_t *)data, len); break; } case AT_CMD_NAME_REQ: // 获取设备名称 { sprintf(data, "%s", device_id); at_set_memcmp_cache((unsigned char *)data, osel_mstrlen((unsigned char *)data)); osel_memset((uint8_t *)data, 0, 128); sprintf(data, test_cmd[AT_CMD_NAME_REQ]); len = osel_mstrlen((unsigned char *)data); bluetooth_output((uint8_t *)data, len); break; } case AT_CMD_NAME: // 设置设备名称 { sprintf(data, "%s", device_id); at_set_memcmp_cache((unsigned char *)data, osel_mstrlen((unsigned char *)data)); osel_memset((uint8_t *)data, 0, 128); sprintf(data, test_cmd[AT_CMD_NAME], device_id); len = osel_mstrlen((unsigned char *)data); bluetooth_output((uint8_t *)data, len); break; } case AT_CMD_TX_POWER: // 设置发射功率 { bluetooth_state = 0; sprintf(data, test_cmd[AT_CMD_TX_POWER]); len = osel_mstrlen((unsigned char *)data); bluetooth_output((uint8_t *)data, len); break; } case 100: { sprintf(data, "%f,%f,%f\r\n", 1.1, 2.2, 3.3); len = osel_mstrlen((unsigned char *)data); bluetooth_output((uint8_t *)data, len); break; } default: break; } } // 串口1、5接收中断回调函数 static void hart_rx1_cb(uint8_t uart_index, uint8_t *data, uint16_t len) { DBG_ASSERT(uart_index < APP_UART_MAX __DBG_LINE); #ifndef BOOTLOAD HART_RTS_OFF(); // RTS需要提前 uart1_set_idel_status(FALSE); if (hart_handle(uart_index, data, len) == FALSE) { HART_RTS_ON(); } #else rym_receive(uart_index, data, len); #endif } static void hart_rx5_cb(uint8_t uart_index, uint8_t *data, uint16_t len) { DBG_ASSERT(uart_index < APP_UART_MAX __DBG_LINE); if (data[0] == 'O' && data[1] == 'K') // HC42蓝牙协议 { data[0] = 'A'; data[1] = 'T'; at_cmd_parse(data, len); } else if (data[0] == '+' && data[len - 1] == '\n' && data[len - 2] == '\r') // MX02蓝牙协议 { uint8_t mx02_data[32]; mx02_data[0] = 'A'; mx02_data[1] = 'T'; osel_memcpy(&mx02_data[2], data, len); at_cmd_parse((unsigned char *)mx02_data, len + 2); } else if (data[0] == 'B' && data[1] == 'T') // 收到BOOTLOAD启动命令 { if (osel_memcmp(data, "BT RUN", 6) == 0) { if (get_app_preload_bootload_flag() == BOOTLOAD_UNSET_FLAG) // 如果已经在BOOTLOAD模式下,不再重复启动 { set_app_preload_bootload_flag(BOOTLOAD_SET_FLAG); // 设置BOOTLOAD标志 bootload_transmit_from(uart_index); // 从指定位置开始发送数据 } } else if (osel_memcmp(data, "BT STOP", 7) == 0) { set_app_preload_bootload_flag(BOOTLOAD_UNSET_FLAG); // 设置BOOTLOAD标志 } } else { // 注:在BOOTLOAD模式下,不接收HART数据 #ifndef BOOTLOAD uart1_set_idel_status(FALSE); if (hart_handle(uart_index, data, len) == FALSE) { __NOP(); } #else rym_receive(uart_index, data, len); #endif } } static void hart_tx_complete_cb(void) { // 串口1发送完成回调函数 HART_RTS_ON(); rt_data.flag.bits.hart_rts_on = TRUE; } // HART协议的使用的串口 --- 串口1 void hart_uart_init(void) { LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); GPIO_SET_OUTPUT(HART_PWR_GPIO_Port, HART_PWR_Pin); GPIO_SET_OUTPUT(HART_RST_GPIO_Port, HART_RST_Pin); GPIO_SET_OUTPUT(HART_RTS_GPIO_Port, HART_RTS_Pin); GPIO_SET_ALTERNATE(HART_TX_GPIO_Port, HART_TX_Pin); GPIO_SET_ALTERNATE(HART_RX_GPIO_Port, HART_RX_Pin); LL_mDelay(10); // 串口1初始化开始 HART_RTS_ON(); HART_RST_OFF(); LL_mDelay(20); HART_RST_ON(); HART_EN_DISABLE(); HART_EN_ENABLE(); HART_RTS_ON(); if (uarts[APP_UART_1] == NULL) { LL_mDelay(100); uarts[APP_UART_1] = uart_create(HART_UART1, FALSE, HART_UART_RXSIZE, hart_rx1_cb, FALSE, HART_UART_TXSIZE, hart_tx_complete_cb); uarts[APP_UART_1]->rx_cd_en = TRUE; uarts[APP_UART_1]->uart_index = APP_UART_1; uarts[APP_UART_1]->dma = DMA2; uarts[APP_UART_1]->dma_rx_channel = LL_DMA_CHANNEL_7; uarts[APP_UART_1]->dma_tx_channel = LL_DMA_CHANNEL_6; uart_recv_en(uarts[APP_UART_1], TRUE); rt_data.flag.bits.hart_rts_on = TRUE; } // 串口1初始化结束 uart1_set_idel_status(TRUE); uart_data_storage_reset(uarts[APP_UART_1]); } // HART协议使用的串口,为模拟IO口 void hart_uart_dinit(void) { HART_EN_DISABLE(); LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_USART1); LL_USART_Disable(USART1); GPIO_SET_ANALOG(HART_PWR_GPIO_Port, HART_PWR_Pin); GPIO_SET_ANALOG(HART_RST_GPIO_Port, HART_RST_Pin); // GPIO_SET_ANALOG(HART_CD_GPIO_Port, HART_CD_Pin); // CD作为外部输入中断,不需要设置为模拟IO口 GPIO_SET_ANALOG(HART_TX_GPIO_Port, HART_TX_Pin); GPIO_SET_ANALOG(HART_RX_GPIO_Port, HART_RX_Pin); } // 蓝牙模块串口初始化 void hart_ble_init(void) { LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5); GPIO_SET_OUTPUT(BLE_PWR_GPIO_Port, BLE_PWR_Pin); GPIO_SET_INPUT(BLE_RST_GPIO_Port, BLE_RST_Pin); GPIO_SET_ALTERNATE(BLE_TX_GPIO_Port, BLE_TX_Pin); GPIO_SET_ALTERNATE(BLE_RX_GPIO_Port, BLE_RX_Pin); if (uarts[APP_UART_2] == NULL) { uarts[APP_UART_2] = uart_create(HART_UART2, TRUE, BLE_UART_RXSIZE, hart_rx5_cb, TRUE, HART_UART_TXSIZE, NULL); uarts[APP_UART_2]->uart_index = APP_UART_2; uarts[APP_UART_2]->dma = DMA2; uarts[APP_UART_2]->dma_rx_channel = LL_DMA_CHANNEL_2; uarts[APP_UART_2]->dma_tx_channel = LL_DMA_CHANNEL_1; uart_recv_en(uarts[APP_UART_2], FALSE); } BLE_EN_ENABLE(); } // 蓝牙模块端口IO口反初始化 void hart_ble_dinit(void) { // 关闭蓝牙串口 BLE_EN_DISABLE(); LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_UART5); LL_USART_Disable(UART5); // 端口转成模拟IO口 GPIO_SET_ANALOG(BLE_PWR_GPIO_Port, BLE_PWR_Pin); GPIO_SET_ANALOG(BLE_RST_GPIO_Port, BLE_RST_Pin); GPIO_SET_ANALOG(BLE_TX_GPIO_Port, BLE_TX_Pin); GPIO_SET_ANALOG(BLE_RX_GPIO_Port, BLE_RX_Pin); } static void hart_params_init(void) { uint32_t stmp = _get_timestamp(); uint8_t message[HART_PACKED32_LEN]; osel_memset(message, 0, HART_PACKED32_LEN); // hart_storage_variable_t *p = &hart_device_attribute.flash_variable; app_hart_update_time(); // 更新时间 // 记录消息 if (dbg_assert_line != 0) { uint16_t line = dbg_assert_line; sprintf((char *)message, "GSDT RESET[%d]:%d", line, stmp); // osel_memcpy(p->message, message, sizeof(message)); // 消息 dbg_assert_line = 0; } hart_attribute_params_map_address_update(); // 参数变量地址映射 } // HART初始化 BOOL app_hart_init(void) { hart_init_t init; init.hart_protocol_version = HART_VERSION; // 协议版本 init.dir = MODULE_SLAVE; // 协议模式--从 init.interface.response = _response; init.interface.uart_error_count = _uart_error_count; init.interface.uart_errors = _uart_errors; init.interface.frame_data_parse_time_start = _frame_data_parse_time_start; init.interface.get_timestamp = _get_timestamp; init.interface.flash_read = _flash_read; init.interface.flash_write = _flash_write; init.interface.flash_read_item = _flash_read_item; init.interface.flash_write_item = _flash_write_item; init.interface.perform_self_test = _perform_self_test; init.interface.device_reset = _device_reset; init.interface.squawk_control = _squawk_control; init.interface.armed = _armed; init.interface.set_dynamics = _set_dynamics; init.interface.set_real_time_clock = _set_real_time_clock; init.interface.get_real_time_clock = _get_real_time_clock; init.interface.user_common_event = _user_common_event; init.interface.attribute_init = hart_attribute_params_restart; init.interface.variable_init = hart_attribute_params_map_restart; init.hart_timer.timer_cycle = (LL_TIM_GetAutoReload(HART_TIM) + 1) * 0.1; // 定时器周期 hart_device_attribute.last_device_variable = (uint8_t *)&rt_save.last_dev_variable; uarts[APP_UART_1] = NULL; uarts[APP_UART_2] = NULL; hart_init(&init); hart_params_init(); ENABLE_TIM(HART_OUT_TIM); PWM_START(HART_OUT_TIM, LL_TIM_CHANNEL_CH2); return TRUE; } /** * @brief HART检测任务 * @return {*} * @note 对于实时要求不高的参数,可以在这里更新 */ void app_hart_inspection(void) { hart_device_attribute.internal++; app_hart_update_time(); // 更新时间 hart_cache_detection(); // HART缓存区探测,如果缓存区过期则回收 rt_save.hart_run_time_h = rt_save.dev_run_time_h / 18; // 1:18,运行时间 详见参数读取-129 RUN_TIME_18HR // 是否写保护 driver_icon_enable.bits.write_protect = hart_device_attribute.flash_variable.write_protect_code == WRITE_PROTECT_CODE_WRITE_PROTECT ? 1 : 0; // 是否锁定 driver_icon_enable.bits.lock = hart_device_attribute.flash_variable.lock_code == LOCK_DEVICE_CODE_0 ? 0 : 1; // 扩展设备类型 if (hart_device_attribute.flash_variable.extended_device_type != udevice.dev_model) { hart_device_attribute.flash_variable.extended_device_type = udevice.dev_model; hart_long_addr_set(); hart_storage_write_item(HART_STORAGE_PARAMS, HPB_EXTENDED_DEVICE_TYPE, (uint8_t *)&hart_device_attribute.flash_variable.extended_device_type); hart_storage_write_item(HART_STORAGE_PARAMS, HPB_LONG_ADDRESS, hart_device_attribute.flash_variable.long_address); } if (hart_device_attribute.internal % HART_INTERNAL == 0) // 需要延时判断的 { if (hart_device_attribute.device_status.reset == TRUE) { LL_mDelay(200); sys_soft_reset(); } else if (hart_device_attribute.device_status.busy == TRUE) { perform_self_test_finish(); menus_rebuild(); } } update_device_status(); // 扩展现场设备状态 48号指令 spec_table_data_mapping(TRUE); // udevice中数据映射到规格表 // // 每60次进入,执行一次检查ram和存储中数据是否一致 // if (hart_device_attribute.internal % (HART_INTERNAL * 20) == 0) // { // hart_storage_variable_t *p1 = &hart_device_attribute.flash_variable; // if (storage_check_all(hart_attribute_storage, (uint8_t *)p1) == FALSE) // { // rt_data.flag.bits.hart_attribute_storage = FALSE; // } // hart_device_variable_t *p2 = hart_device_attribute.device_variable; // if (storage_check_all(hart_variable_storage, (uint8_t *)p2) == FALSE) // { // rt_data.flag.bits.hart_variable_storage = FALSE; // } // hart_device_constant_t *p3 = hart_device_attribute.device_constant; // if (storage_check_all(hart_constant_storage, (uint8_t *)p3) == FALSE) // { // rt_data.flag.bits.hart_constant_storage = FALSE; // } // hart_device_standard_variable_t *p4 = hart_device_attribute.device_standard_variable; // if (storage_check_all(hart_standard_variable_storage, (uint8_t *)p4) == FALSE) // { // rt_data.flag.bits.hart_standard_variable_storage = FALSE; // } // } } // 更新实时时间 void app_hart_update_time(void) { BOOL change = FALSE; uint8_t y, h, m, s; real_time_clock_t *p = &hart_device_attribute.real_time_clock; uint8_t *date = hart_device_attribute.flash_variable.date; y = rt_save.real_time.date.year; covert_rtc_year(&y); if (date[2] != y || date[1] != rt_save.real_time.date.month || date[0] != rt_save.real_time.date.day) { change = TRUE; } date[2] = y; date[1] = rt_save.real_time.date.month; date[0] = rt_save.real_time.date.day; p->date[0] = hart_device_attribute.flash_variable.date[0]; p->date[1] = hart_device_attribute.flash_variable.date[1]; p->date[2] = hart_device_attribute.flash_variable.date[2]; h = rt_save.real_time.date.hour; m = rt_save.real_time.date.minute; s = rt_save.real_time.date.second; convert_timestrap(&p->time, h, m, s, 0); p->rtc_flags = REAL_TIME_CLOCK_FLAGS_1; if (change == TRUE) { hart_storage_write_item(HART_STORAGE_PARAMS, HPB_DATE, hart_device_attribute.flash_variable.date); } } // 判断下一篇存储数据是否已经写过数据 BOOL app_hart_storage_is_written(uint32_t address, uint16_t length) { uint8_t *data; uint16_t count = 0; ErrorStatus rst = ERROR; BOOL res = FALSE; count = length / LL_FLASH_PAGE_SIZE; data = osel_mem_alloc(LL_FLASH_PAGE_SIZE); DBG_ASSERT(data != NULL __DBG_LINE); for (uint16_t i = 0; i < count; i++) { rst = LL_FLASH_Read(address + i * LL_FLASH_PAGE_SIZE, data, LL_FLASH_PAGE_SIZE); if (rst == SUCCESS) { for (uint16_t j = 0; j < LL_FLASH_PAGE_SIZE; j++) { if (data[j] != 0xff) { res = TRUE; break; } } } else { res = TRUE; } if (res == TRUE) { break; } res = FALSE; } osel_mem_free(data); return res; } /** * @brief 获取更多状态标志 * @param {uint8_t} *rev_buf * @return {*} * @note */ static void hart_get_device_specific_status(uint8_t *rev_buf) { hart_device_specific_status_u st; st.bits.u1.travel_sensor_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_MAGNET); st.bits.u1.pressure_sensor_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_PRESS_SENSOR); st.bits.u1.temperature_sensor_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TEMPERATURE_SENSOR); st.bits.u1.critical_nvm_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_CRITICAL_NVM); st.bits.u1.drive_current_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_IP_DRIVER); st.bits.u1.reference_voltage_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_VREF); st.bits.u1.mlfb_sensor_alarm = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_MICRO_LOOP); st.bits.u1.flash_integrity_failure = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_FLASH_INTEGRITY); st.bits.u2.auto_cal_in_progress_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_AUTO_CALIBRATION); st.bits.u2.nvm_protective_mode = get_diagnosis_fault_result_of_enable_state(INDICATE_NVM_PROTECT_MODE); st.bits.u2.pressure_fallback_active_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_PRESS_ACTIVE); st.bits.u2.diagnostics_in_progress_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_TEST_PROGRESS); st.bits.u2.calibration_in_progress_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_CALIBRATION); st.bits.u2.alert_record_not_empty_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_ALERT_RECORD_NOT_EMPTY); st.bits.u3.alert_record_full_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_ALERT_RECORD_FULL); st.bits.u3.cycle_counter_high_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_ACT_SUM); st.bits.u3.instrument_time_is_approximate_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_DEV_REALTIME); st.bits.u3.non_critical_nvm_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_NON_CRITICAL_NVM); st.bits.u3.offline_failed_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_OFFLINE); st.bits.u3.travel_accumulator_high_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TRAVEL_SUM); st.bits.u4.diagnostic_data_available_alert = get_diagnosis_fault_result_of_enable_state(INDICATE_DIAG_DATA_AVAILABLE); st.bits.u4.end_point_pressure_deviation_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_PRESS_ERROR); st.bits.u4.integrator_saturated_high_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_UI_SATURATED_HIGH); st.bits.u4.integrator_saturated_low_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_UI_SATURATED_LOW); st.bits.u4.supply_pressure_high_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_SUPPLY_UPPER); st.bits.u4.supply_pressure_low_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_SUPPLY_LOWER); st.bits.u5.drive_signal_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_DRIVE_SIGNAL); st.bits.u5.travel_alert_hi = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TRAVEL_HI); st.bits.u5.travel_alert_hi_hi = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TRAVEL_HI_HI); st.bits.u5.travel_alert_lo = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TRAVEL_LO); st.bits.u5.travel_alert_lo_lo = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TRAVEL_LO_LO); st.bits.u5.travel_deviation_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_TRAVEL_ERROR); st.bits.u5.travel_limit_cutoff_hi_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_LIMIT_CUTOFF_HI); st.bits.u5.travel_limit_cutoff_lo_alert = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_LIMIT_CUTOFF_LO); st.bits.u6.output_circuit_error = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_OUTPUT_CIRCUIT_ERROR); st.bits.u6.output_pressure_limiting = get_diagnosis_fault_result_of_enable_state(DIAGNOSIS_OUTPUT_PRESS_LIMIT); osel_memcpy(rev_buf, (uint8_t *)&st, ARRAY_LEN(st.data)); } /** * @brief 更新设备状态 * @return {*} * @note */ static void update_device_status(void) { additional_device_status_t *p = &hart_device_attribute.device_status.additional_device_status; // 设备特定状态 - 48号指令 { hart_get_device_specific_status(p->device_specific_status); } // 扩展设备状态 { diag_class_e status = get_diagnosis_fault_priority(); switch (status) { case DIAGNOSIS_CLASS_FAIL: p->extended_device_status = EXTENDED_DEVICE_STATUS_4; // 设备故障 break; case DIAGNOSIS_CLASS_SPEC: p->extended_device_status = EXTENDED_DEVICE_STATUS_5; // 超出规格 break; case DIAGNOSIS_CLASS_CHECK: p->extended_device_status = EXTENDED_DEVICE_STATUS_6; // 功能检查 break; case DIAGNOSIS_CLASS_MAINT: p->extended_device_status = EXTENDED_DEVICE_STATUS_1; // 需要维护 break; default: p->extended_device_status = EXTENDED_DEVICE_STATUS_0; // 正常 break; } } // 标准化状态0 { p->standardized_status0 = STANDARDIZED_STATUS0_0; // 非易失性存储器缺陷 BOOL eeprom_status = FALSE; eeprom_status = fal_execution_status_get(FAL_EXECUTION_EEPROM_M95_1); if (eeprom_status == TRUE) { eeprom_status = fal_execution_status_get(FAL_EXECUTION_EEPROM_M95_2); if (eeprom_status == TRUE) { eeprom_status = fal_execution_status_get(FAL_EXECUTION_EEPROM_FM24); if (eeprom_status == TRUE) { // TODO: eeprom_lc02b } } } if (eeprom_status == FALSE) { p->standardized_status0 = STANDARDIZED_STATUS0_2; // 非易失性存储器缺陷 } // 电源条件超出范围 if (rt_data.loop_current < LOOP_CURRENT_MIN || rt_data.loop_current > LOOP_CURRENT_MAX) { p->standardized_status0 = STANDARDIZED_STATUS0_5; // 电源条件超出范围 } if (hart_device_attribute.flash_variable.write_protect_code == WRITE_PROTECT_CODE_WRITE_PROTECT || hart_device_attribute.flash_variable.lock_code != LOCK_DEVICE_CODE_0) { p->standardized_status0 = STANDARDIZED_STATUS0_8; // 设备配置已锁定。设备处于写保护状态或已锁定 } } }