/* * @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.ack = 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.ack = 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; } }