451 lines
12 KiB
C
451 lines
12 KiB
C
/*
|
||
* @Author:
|
||
* @Date: 2023-03-20 19:27:00
|
||
* @LastEditors: xxx
|
||
* @LastEditTime: 2023-08-29 11:44:01
|
||
* @FilePath: \hart\hart\hart.c
|
||
* @Description: hart模块接口
|
||
* email:
|
||
* Copyright (c) 2023 by xxx, All Rights Reserved.
|
||
*/
|
||
|
||
#include "./inc/hart.h"
|
||
#include "./slave/inc/hart_slave_frame.h"
|
||
|
||
#define HART_INIT_FLAG (0x0520) ///< 初始化标志
|
||
|
||
static hart_init_t handle;
|
||
static hart_response_t response;
|
||
|
||
BOOL(*hart_command_ptr_arr[HART_COMMAND_MAX])
|
||
(const hart_command_req_t *const req, hart_response_t *resp);
|
||
|
||
/**
|
||
* @brief 获取HART句柄
|
||
*
|
||
* 该函数返回HART句柄的指针。
|
||
*
|
||
* @return 返回HART句柄的指针
|
||
*/
|
||
hart_init_t *hart_get_handle(void)
|
||
{
|
||
return &handle;
|
||
}
|
||
|
||
/**
|
||
* @brief hart模块初始化
|
||
* @param {hart_init_t} *init: 初始化参数
|
||
* @return: TRUE: 初始化成功
|
||
* FALSE: 初始化失败
|
||
*/
|
||
BOOL hart_init(const hart_init_t *const init)
|
||
{
|
||
// 将初始数据赋值给handle
|
||
if (!DBG_ASSERT(init != NULL __DBG_LINE))
|
||
return FALSE;
|
||
osel_memcpy((uint8_t *)&handle, (uint8_t *)init, sizeof(hart_init_t));
|
||
|
||
// 检查参数
|
||
if (!DBG_ASSERT((handle.dir == MODULE_MASTER) || (handle.dir == MODULE_SLAVE) __DBG_LINE))
|
||
return FALSE;
|
||
|
||
if (!DBG_ASSERT(handle.interface.response != NULL __DBG_LINE))
|
||
return FALSE;
|
||
|
||
// 缓存消息初始化
|
||
hart_cache_init();
|
||
#ifdef MASTER
|
||
if (handle.dir == MODULE_MASTER) // 主机模块初始化
|
||
{
|
||
handle.hart_module_u._master.address_bit = handle.master_address_bit;
|
||
if (handle.hart_module_u._master.address_bit != HART_MASTER)
|
||
{
|
||
handle.hart_module_u._master.address_bit = 0;
|
||
}
|
||
|
||
handle.hart_module_u._master.response_call = handle.interface.response;
|
||
handle.hart_module_u._master.response = &response;
|
||
if (!DBG_ASSERT(hart_master_init(&handle.hart_module_u._master) == TRUE __DBG_LINE))
|
||
return FALSE;
|
||
|
||
#if MOCK == 1
|
||
mock_master_attribute();
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
#ifdef SLAVE
|
||
hart_device_attribute.hart_protocol_version = &handle.hart_protocol_version;
|
||
hart_device_attribute.message_count.phack = 0; // 响应消息计数
|
||
hart_device_attribute.message_count.shack = 0; // 响应消息计数
|
||
if (!DBG_ASSERT((hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_5 ||
|
||
hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7) __DBG_LINE)) // 校验协议版本号,模块支持协议版本为5,7
|
||
return FALSE;
|
||
if (handle.dir == MODULE_SLAVE) // 从机模块初始化
|
||
{
|
||
|
||
#ifdef STM32
|
||
if (!DBG_ASSERT(handle.interface.flash_read != NULL __DBG_LINE)) // 从机模块必须实现flash_read接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.flash_write != NULL __DBG_LINE)) // 从机模块必须实现flash_write接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.flash_read_item != NULL __DBG_LINE)) // 从机模块必须实现flash_read接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.flash_write_item != NULL __DBG_LINE)) // 从机模块必须实现flash_write接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.perform_self_test != NULL __DBG_LINE)) // 从机模块必须实现perform_self_test接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.device_reset != NULL __DBG_LINE)) // 从机模块必须实现device_reset接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.squawk_control != NULL __DBG_LINE)) // 从机模块必须实现squawk_control接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.armed != NULL __DBG_LINE)) // 从机模块必须实现armed接口
|
||
return FALSE;
|
||
if (!DBG_ASSERT(handle.interface.user_common_event != NULL __DBG_LINE)) // 从机模块必须实现user_common_event接口
|
||
return FALSE;
|
||
#endif
|
||
|
||
handle.hart_module_u._slave.response_call = handle.interface.response;
|
||
handle.hart_module_u._slave.response = &response;
|
||
if (!DBG_ASSERT(hart_slave_init(&handle.hart_module_u._slave) == TRUE __DBG_LINE))
|
||
return FALSE;
|
||
|
||
#ifdef STM32
|
||
hart_slave_device_attribute_init();
|
||
if (!DBG_ASSERT(handle.interface.set_dynamics != NULL __DBG_LINE)) // 从机模块必须动态数据接口
|
||
return FALSE;
|
||
BOOL ret = FALSE;
|
||
BOOL ret2 = FALSE;
|
||
BOOL ret3 = FALSE;
|
||
|
||
// 从flash中读取设备属性
|
||
ret = handle.interface.flash_read(HART_STORAGE_PARAMS, (uint8_t *)&hart_device_attribute.flash_variable);
|
||
|
||
if (ret == TRUE)
|
||
{
|
||
if (hart_device_attribute.flash_variable.init_flag != HART_INIT_FLAG)
|
||
{
|
||
ret = FALSE;
|
||
}
|
||
}
|
||
|
||
if (ret == FALSE)
|
||
{
|
||
INIT:
|
||
if (!DBG_ASSERT(handle.interface.attribute_init != NULL __DBG_LINE))
|
||
return FALSE;
|
||
handle.interface.attribute_init();
|
||
handle.interface.variable_init();
|
||
}
|
||
else
|
||
{
|
||
ret = handle.interface.flash_read(HART_STORAGE_VARIABLE, (uint8_t *)&hart_device_attribute.device_variable);
|
||
if (ret == TRUE)
|
||
{
|
||
ret2 = handle.interface.flash_read(HART_STORAGE_CONSTANT, (uint8_t *)&hart_device_attribute.device_constant);
|
||
}
|
||
|
||
if (ret2 == TRUE)
|
||
{
|
||
ret3 = handle.interface.flash_read(HART_STORAGE_STANDARD_VARIABLE, (uint8_t *)&hart_device_attribute.device_standard_variable);
|
||
}
|
||
|
||
// 注:hart_device_attribute.device_variable[0].code != DIN_ANALOG_INPUT 这个判断是为了解决没有读到数据的情况,flash_variable可以设置crc32,这个变量是数组无法设定,用第一个和第二个变量判断
|
||
if (ret == FALSE || ret2 == FALSE || ret3 == FALSE ||
|
||
hart_device_attribute.device_variable[0].code != DIN_ANALOG_INPUT || hart_device_attribute.device_variable[1].code != DIN_INTERNAL_TEMPERATURE)
|
||
{
|
||
goto INIT;
|
||
}
|
||
}
|
||
|
||
// 动态属性
|
||
handle.interface.set_dynamics(&hart_device_attribute.dynamics);
|
||
|
||
hart_device_attribute.hart_protocol_version = &handle.hart_protocol_version;
|
||
hart_device_attribute.message_count.phack = 0; // 响应消息计数
|
||
hart_device_attribute.message_count.shack = 0; // 响应消息计数
|
||
#else
|
||
mock_data();
|
||
#endif
|
||
}
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief hart模块数据处理函数
|
||
* @param {uint8_t} uart_index: 串口索引
|
||
* @param {uint8_t} uart_error: 串口错误
|
||
* @param {uint8_t} *rxBuf: 接收到的数据
|
||
* @param {uint16_t} len: 接收到的数据长度
|
||
* @return: TRUE: 处理成功
|
||
* FALSE: 处理失败
|
||
*/
|
||
BOOL hart_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len)
|
||
{
|
||
if (!DBG_ASSERT(rxBuf != NULL __DBG_LINE))
|
||
return FALSE;
|
||
if (!DBG_ASSERT(len != 0 __DBG_LINE))
|
||
return FALSE;
|
||
|
||
if (!DBG_ASSERT((handle.dir == MODULE_MASTER) || (handle.dir == MODULE_SLAVE) __DBG_LINE))
|
||
return FALSE;
|
||
|
||
// 根据模块工作模式将数据分发给对应的主机或从机处理
|
||
#ifdef MASTER
|
||
if (handle.dir == MODULE_MASTER)
|
||
{
|
||
return hart_master_handle(rxBuf, len);
|
||
}
|
||
#endif
|
||
|
||
#ifdef SLAVE
|
||
if (handle.dir == MODULE_SLAVE)
|
||
{
|
||
return hart_slave_handle(uart_index, rxBuf, len);
|
||
}
|
||
#endif
|
||
return FALSE;
|
||
}
|
||
|
||
void hart_cache_data_send(uint64_t uuid)
|
||
{
|
||
hart_cache_t *p;
|
||
p = hart_cache_get(uuid);
|
||
if (NULL != p)
|
||
{
|
||
LOG_PRINT("%d", p->uuid);
|
||
#ifdef SLAVE
|
||
hart_slave_device_send(p);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取指定UART接口的错误计数
|
||
*
|
||
* 该函数用于获取指定UART接口的错误计数。
|
||
*
|
||
* @param uart_index UART接口的索引
|
||
*
|
||
* @return 返回指定UART接口的错误计数
|
||
*/
|
||
uint16_t hart_uart_error_count(uint8_t uart_index)
|
||
{
|
||
return handle.interface.uart_error_count(uart_index);
|
||
}
|
||
|
||
/**
|
||
* @brief 处理UART错误
|
||
*
|
||
* 该函数用于处理指定UART接口的错误。
|
||
*
|
||
* @param uart_index UART接口的索引
|
||
* @param errors 用于存储错误信息的指针
|
||
*/
|
||
void hart_uart_errors(uint8_t uart_index, hart_uart_error_t *errors)
|
||
{
|
||
handle.interface.uart_errors(uart_index, errors);
|
||
}
|
||
|
||
/**
|
||
* @brief 开始解析帧数据的计时
|
||
*
|
||
* 该函数用于启动帧数据解析的计时器。
|
||
*
|
||
* @param timer_period 计时器周期
|
||
*/
|
||
void frame_data_parse_time_start(uint16_t timer_period)
|
||
{
|
||
handle.interface.frame_data_parse_time_start(timer_period);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取时间戳
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
uint32_t hart_get_timestamp(void)
|
||
{
|
||
return handle.interface.get_timestamp();
|
||
}
|
||
|
||
/**
|
||
* @brief flash写入 hart内部使用
|
||
* @param {uint32_t} addr
|
||
* @param {uint8_t} *data
|
||
* @return {*}
|
||
*/
|
||
BOOL hart_storage_write(hart_storage_e index, uint8_t *data)
|
||
{
|
||
return handle.interface.flash_write(index, data);
|
||
}
|
||
/**
|
||
* @brief falsh读取 hart内部使用
|
||
* @param {uint32_t} addr
|
||
* @param {uint8_t} *dat
|
||
* @return {*}
|
||
*/
|
||
BOOL hart_storage_read(hart_storage_e index, uint8_t *data)
|
||
{
|
||
return handle.interface.flash_read(index, data);
|
||
}
|
||
|
||
BOOL hart_storage_write_item(hart_storage_e index, uint8_t item, uint8_t *data)
|
||
{
|
||
return handle.interface.flash_write_item(index, item, data);
|
||
}
|
||
BOOL hart_storage_read_item(hart_storage_e index, uint8_t item, uint8_t *data)
|
||
{
|
||
return handle.interface.flash_read_item(index, item, data);
|
||
}
|
||
/**
|
||
* @brief 自检
|
||
* @return {*}
|
||
*/
|
||
void hart_perform_self_test(void)
|
||
{
|
||
#ifdef SLAVE
|
||
hart_device_attribute.device_status.busy = TRUE;
|
||
handle.interface.perform_self_test();
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief 自检完成
|
||
* @return {*}
|
||
*/
|
||
void perform_self_test_finish(void)
|
||
{
|
||
#ifdef SLAVE
|
||
hart_device_attribute.device_status.busy = FALSE;
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @brief 设备复位
|
||
* @return {*}
|
||
*/
|
||
void hart_device_reset(void)
|
||
{
|
||
hart_device_attribute.device_status.reset = TRUE;
|
||
handle.interface.device_reset(); // 这里的接口不是真复位,而是在LCD上显示复位信息
|
||
}
|
||
|
||
/**
|
||
* @brief 呼叫
|
||
* @param {BOOL} open
|
||
* @param {uint8_t} second
|
||
* @return {*}
|
||
*/
|
||
void hart_squawk_control(BOOL open, uint8_t second)
|
||
{
|
||
handle.interface.squawk_control(open, second);
|
||
}
|
||
|
||
/**
|
||
* @brief 技术人员按下一个特殊的按钮或按钮组合,指示从机应响应command74
|
||
* @return {*}
|
||
*/
|
||
BOOL hart_armed(void)
|
||
{
|
||
return handle.interface.armed();
|
||
}
|
||
|
||
/**
|
||
* @brief 设置实时时钟
|
||
* @param {uint8_t} year
|
||
* @param {uint8_t} month
|
||
* @param {uint8_t} day
|
||
* @param {uint8_t} hour
|
||
* @param {uint8_t} min
|
||
* @param {uint8_t} sec
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void hart_set_real_time_clock(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
|
||
{
|
||
if (handle.interface.set_real_time_clock == NULL)
|
||
return;
|
||
|
||
handle.interface.set_real_time_clock(year, month, day, hour, min, sec);
|
||
}
|
||
|
||
/**
|
||
* @brief 获取实时时钟
|
||
* @param {uint8_t} *year
|
||
* @param {uint8_t} *month
|
||
* @param {uint8_t} *day
|
||
* @param {uint8_t} *hour
|
||
* @param {uint8_t} *min
|
||
* @param {uint8_t} *sec
|
||
* @return {*}
|
||
* @note
|
||
*/
|
||
void hart_get_real_time_clock(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
|
||
{
|
||
if (handle.interface.get_real_time_clock == NULL)
|
||
return;
|
||
|
||
handle.interface.get_real_time_clock(year, month, day, hour, min, sec);
|
||
}
|
||
|
||
BOOL hart_user_common_event(hart_interface_user_event_e event, const void *const data)
|
||
{
|
||
#ifdef STM32
|
||
if (handle.interface.user_common_event == NULL)
|
||
return FALSE;
|
||
return handle.interface.user_common_event(event, data);
|
||
#else
|
||
return TRUE;
|
||
#endif
|
||
}
|
||
|
||
BOOL get_device_lock(void)
|
||
{
|
||
return hart_device_attribute.flash_variable.lock_code == LOCK_DEVICE_CODE_0 ? FALSE : TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 定时器中断回调函数
|
||
*
|
||
* 当定时器触发中断时,该函数会被调用。
|
||
* 该函数为空实现,用户可以根据具体需求进行扩展。
|
||
*/
|
||
void hart_timer_interupt_cb(void)
|
||
{
|
||
if (hart_get_handle()->hart_timer.counter > 0)
|
||
{
|
||
hart_get_handle()->hart_timer.counter--;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 启动HART定时器
|
||
*
|
||
* 设置HART定时器的周期,并启动定时器。
|
||
*
|
||
* @param timer_period 定时器周期(单位:毫秒)
|
||
*/
|
||
void hart_timer_start(uint16_t timer_period)
|
||
{
|
||
hart_get_handle()->hart_timer.counter = timer_period / hart_get_handle()->hart_timer.timer_cycle;
|
||
}
|
||
|
||
/**
|
||
* 1. 每个字节间隔超过10毫秒就丢弃这组数据
|
||
* 2. 数据处理的时间,257毫秒,丢包
|
||
*/
|
||
BOOL hart_timeout_compare(void)
|
||
{
|
||
if (hart_get_handle()->hart_timer.counter == 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|