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

958 lines
30 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_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 <stdlib.h>
#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)
{
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 (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 (rt_data.flag.bits.ble_on == TRUE)
{
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)
{
system_clock_config_low();
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_PACKED20_LEN];
char str[HART_LONG_ADDRESS_LEN * 2 + 1];
osel_memset((uint8_t*)device_id, 0, ARRAY_LEN(device_id));
osel_memset((uint8_t*)str, 0, ARRAY_LEN(str));
hart_long_address_to_string(str, hart_device_attribute.flash_variable.long_address, HART_LONG_ADDRESS_LEN);
sprintf(device_id, "%s-%s", DESCRIPTOR, str);
__NOP();
#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",
"AT+MAC?\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: // 设置发射功率
{
sprintf(data, test_cmd[AT_GET_MAC]);
len = osel_mstrlen((unsigned char*)data);
bluetooth_output((uint8_t*)data, len);
break;
}
case AT_GET_MAC:
{
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]);
rt_data.flag.bits.hart_on = TRUE;
}
// HART协议使用的串口为模拟IO口
void hart_uart_dinit(void)
{
rt_data.flag.bits.hart_on = FALSE;
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)
{
hart_storage_variable_t* p = &hart_device_attribute.flash_variable;
// 记录消息
if (dbg_assert_line != 0)
{
uint32_t stmp = _get_timestamp();
uint8_t message[HART_PACKED32_LEN];
osel_memset(message, 0, HART_PACKED32_LEN);
uint16_t line = dbg_assert_line;
sprintf((char*)message, "RESET[%d]:%d", line, stmp);
osel_memcpy(p->message, message, HART_PACKED32_LEN); // 消息
hart_storage_write_item(HART_STORAGE_PARAMS, HPB_MESSAGE,
hart_device_attribute.flash_variable.message);
hart_device_status_set_operational_state(DEVICE_OPERATIONAL_STATE_7);
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.private_command = HART_SOFTWARE_TEST_ENABLE == FALSE ? TRUE : FALSE; // 是否支持大命令
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 = TIM_CYCLE(HART_TIM); // 定时器周期
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);
set_tim_hart_out(SystemCoreClock);
return TRUE;
}
/**
* @brief HART检测任务
* @return {*}
* @note 对于实时要求不高的参数,可以在这里更新
*/
void app_hart_inspection(void)
{
hart_device_attribute.internal++;
hart_cache_detection(); // HART缓存区探测如果缓存区过期则回收
rt_data.hart_run_time_h = rt_save.dev_run_time_h / 18; // 1:18运行时间 详见参数读取-129 RUN_TIME_18HR
// 扩展设备类型
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中数据映射到规格表
// 同步params和hart变量数据
if (hart_device_attribute.internal % HART_INTERNAL == 0)
{
params_hart_variable_sync();
}
// 每60次进入执行一次检查ram和存储中数据是否一致
if (hart_device_attribute.internal % (HART_INTERNAL * 20) == 0)
{
params_hart_storage_check();
}
}
// 更新HART软件时间和RTC同步
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;
osel_memset((uint8_t*)&st, 0, HART_PACKED6_LEN);
st.bits.u1.travel_sensor_failure = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_SENSOR);
st.bits.u1.pressure_sensor_failure = get_diagnosis_alarm(DIAGNOSIS_PRESS_SENSOR);
st.bits.u1.temperature_sensor_failure = get_diagnosis_alarm(DIAGNOSIS_TEMPERATURE_SENSOR);
st.bits.u1.critical_nvm_failure = get_diagnosis_alarm(DIAGNOSIS_CRITICAL_NVM);
st.bits.u1.drive_current_failure = get_diagnosis_alarm(DIAGNOSIS_IP_DRIVER);
st.bits.u1.reference_voltage_failure = get_diagnosis_alarm(DIAGNOSIS_VREF);
st.bits.u1.mlfb_sensor_alarm = get_diagnosis_alarm(DIAGNOSIS_MICRO_LOOP);
st.bits.u1.flash_integrity_failure = get_diagnosis_alarm(DIAGNOSIS_FLASH_INTEGRITY);
st.bits.u2.auto_cal_in_progress_alert = get_diagnosis_alarm(INDICATE_AUTO_CALIBRATION);
st.bits.u2.nvm_protective_mode = get_diagnosis_alarm(INDICATE_NVM_PROTECT_MODE);
st.bits.u2.pressure_fallback_active_alert = get_diagnosis_alarm(INDICATE_PRESS_ACTIVE);
st.bits.u2.diagnostics_in_progress_alert = get_diagnosis_alarm(INDICATE_TEST_PROGRESS);
st.bits.u2.calibration_in_progress_alert = get_diagnosis_alarm(INDICATE_CALIBRATION);
st.bits.u2.alert_record_not_empty_alert = get_diagnosis_alarm(INDICATE_ALERT_RECORD_NOT_EMPTY);
st.bits.u3.alert_record_full_alert = get_diagnosis_alarm(INDICATE_ALERT_RECORD_FULL);
st.bits.u3.cycle_counter_high_alert = get_diagnosis_alarm(DIAGNOSIS_ACT_SUM);
st.bits.u3.instrument_time_is_approximate_alert = get_diagnosis_alarm(DIAGNOSIS_DEV_REALTIME);
st.bits.u3.non_critical_nvm_alert = get_diagnosis_alarm(DIAGNOSIS_NON_CRITICAL_NVM);
st.bits.u3.offline_failed_alert = get_diagnosis_alarm(INDICATE_OFFLINE);
st.bits.u3.travel_accumulator_high_alert = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_SUM);
st.bits.u4.diagnostic_data_available_alert = get_diagnosis_alarm(INDICATE_DIAG_DATA_AVAILABLE);
st.bits.u4.end_point_pressure_deviation_alert = get_diagnosis_alarm(DIAGNOSIS_PRESS_ERROR);
st.bits.u4.integrator_saturated_high_alert = get_diagnosis_alarm(DIAGNOSIS_UI_SATURATED_HIGH);
st.bits.u4.integrator_saturated_low_alert = get_diagnosis_alarm(DIAGNOSIS_UI_SATURATED_LOW);
st.bits.u4.supply_pressure_high_alert = get_diagnosis_alarm(DIAGNOSIS_SUPPLY_UPPER);
st.bits.u4.supply_pressure_low_alert = get_diagnosis_alarm(DIAGNOSIS_SUPPLY_LOWER);
st.bits.u5.drive_signal_alert = get_diagnosis_alarm(DIAGNOSIS_DRIVE_SIGNAL);
st.bits.u5.travel_alert_hi = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_HI);
st.bits.u5.travel_alert_hi_hi = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_HI_HI);
st.bits.u5.travel_alert_lo = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_LO);
st.bits.u5.travel_alert_lo_lo = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_LO_LO);
st.bits.u5.travel_deviation_alert = get_diagnosis_alarm(DIAGNOSIS_TRAVEL_ERROR);
st.bits.u5.travel_limit_cutoff_hi_alert = get_diagnosis_alarm(DIAGNOSIS_LIMIT_CUTOFF_HI);
st.bits.u5.travel_limit_cutoff_lo_alert = get_diagnosis_alarm(DIAGNOSIS_LIMIT_CUTOFF_LO);
st.bits.u6.output_circuit_error = get_diagnosis_alarm(DIAGNOSIS_OUTPUT_CIRCUIT_ERROR);
st.bits.u6.output_pressure_limiting = get_diagnosis_alarm(DIAGNOSIS_OUTPUT_PRESS_LIMIT);
osel_memcpy(rev_buf, (uint8_t*)&st, HART_PACKED6_LEN);
}
/**
* @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);
osel_memcpy(diagnosis_get()->device_specific_status.data, p->device_specific_status, HART_PACKED6_LEN);
}
// 扩展设备状态
{
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 = eeprom_m95_status_get(M95_1);
if (eeprom_status == TRUE)
{
eeprom_status = eeprom_m95_status_get(M95_2);
if (eeprom_status == TRUE)
{
eeprom_status = eeprom_fm24_status_get();
if (eeprom_status == TRUE)
{
eeprom_status = eeprom_lc02b_status_get();
}
}
}
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; // 设备配置已锁定。设备处于写保护状态或已锁定
}
}
}