#include "../inc/hart_master.h" #include "../inc/hart_master_rsp.h" static hart_master_init_t *handle; BOOL(*hart_command_rsp_ptr_arr[HART_COMMAND_MAX]) (const hart_command_rsp_t *const data, hart_response_t *resp); // 统计在线设备数量 static uint16_t hart_master_online_device_count(void) { uint16_t count = 0; for (uint8_t i = 0; i < HART_IO_MAXIMUM_NUMBER_CARDS; i++) { io_system_card_t *card = &hart_master_attribute.io_system.cards[i]; for (uint8_t j = 0; j < HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD; j++) { io_system_channel_t *channel = &card->channels[j]; for (uint8_t k = 0; k < HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL; k++) { io_system_device_t *device = &channel->devices[k]; if (device->online) count++; } } } return count; } // 获取设备 static io_system_device_t *hart_master_get_device(uint8_t card_index, uint8_t channel_index, uint8_t device_index) { if (card_index >= HART_IO_MAXIMUM_NUMBER_CARDS) return NULL; if (channel_index >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD) return NULL; if (device_index >= HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL) return NULL; io_system_card_t *card = &hart_master_attribute.io_system.cards[card_index]; io_system_channel_t *channel = &card->channels[channel_index]; io_system_device_t *device = &channel->devices[device_index]; return device; } // 获取通道消息计数 static io_system_message_count_t *hart_master_get_channel_message_count(uint8_t card_index, uint8_t channel_index) { if (card_index >= HART_IO_MAXIMUM_NUMBER_CARDS) return NULL; if (channel_index >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD) return NULL; io_system_card_t *card = &hart_master_attribute.io_system.cards[card_index]; io_system_channel_t *channel = &card->channels[channel_index]; return &channel->message_count; } // 获取设备通过索引 static io_system_device_info_t *hart_master_get_device_by_identifier(uint16_t identifier) { io_system_device_info_t *device_info = osel_mem_alloc(sizeof(io_system_device_info_t)); for (uint8_t i = 0; i < HART_IO_MAXIMUM_NUMBER_CARDS; i++) { io_system_card_t *card = &hart_master_attribute.io_system.cards[i]; for (uint8_t j = 0; j < HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD; j++) { io_system_channel_t *channel = &card->channels[j]; for (uint8_t k = 0; k < HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL; k++) { io_system_device_t *device = &channel->devices[k]; if (device->identifier == identifier) { device_info->card_index = i; device_info->channel_index = j; device_info->device = device; return device_info; } } } } return NULL; } static BOOL hart_master_command_undef_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { return FALSE; } /** * @brief 读取I/O系统功能 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_74_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_CARDS; // I/O卡的最大数量 *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD; // 每个I/O卡的最大通道数 // 每个通道的最大子设备数 *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_DEVICES_CHANNEL; // 每个通道最大设备数 // 检测到的设备数量(计数包括I/O系统本身) uint16_t count = hart_master_online_device_count(); *resp->data_p++ = HI_UINT16(count + 1); *resp->data_p++ = LO_UINT16(count + 1); // I/O系统支持的最大延迟响应数 *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_DELAY_RESPONSE; // 信道通信的主模式。0=二级主机;1=主控形状(默认) if (count == 0) { *resp->data_p++ = 250; // 如果I/0系统没有到子设备的物理HART通信通道,则主模式必须返回250“未使用 } else { *resp->data_p++ = handle->address_bit; } // 向子设备发送命令时要使用的重试计数。有效范围为2到5。默认情况下重试3次。 *resp->data_p++ = HART_IO_MAXIMUM_NUMBER_RETRY_COUNT; } else { } return TRUE; } /** * @brief 轮询子设备 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_75_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { if (data->data_length < sizeof(hart_command_75_t)) { resp->code = RESPONSE_COMMUNICATION_CODE_5; return TRUE; } if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } uint8_t card_index, channel_index, device_index; io_system_device_t *device; card_index = data->data.command_75.card; channel_index = data->data.command_75.channel; device_index = data->data.command_75.poll_address; if (card_index >= HART_IO_MAXIMUM_NUMBER_CARDS) { resp->code = RESPONSE_COMMUNICATION_CODE_21; return TRUE; } if (channel_index >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD) { resp->code = RESPONSE_COMMUNICATION_CODE_22; return TRUE; } device = hart_master_get_device(card_index, channel_index, device_index); if (device == NULL) { resp->code = RESPONSE_COMMUNICATION_CODE_9; return TRUE; } if (device->online == FALSE) { resp->code = RESPONSE_COMMUNICATION_CODE_9; return TRUE; } *resp->data_p++ = 254; // 默认254 *resp->data_p++ = HI_UINT16(device->extended_device_type); // 扩展设备类型 *resp->data_p++ = LO_UINT16(device->extended_device_type); *resp->data_p++ = device->m2s_preambles_limit_count; // 主设备到从设备的最少同步前导码数量 *resp->data_p++ = device->hart_revision; // 本设备实施的HART协议主要版本号。对于HART版本7。该值必须是数字7 *resp->data_p++ = device->device_revision; // 设备版本 *resp->data_p++ = device->device_software_revision; // 设备软件版本,254,255保留 *resp->data_p++ = device->device_hardware_revision.version; // (高5bits)硬件版本号,31保留;(低3bits)5.10 物理信号 resp->data_p++; // 保留 osel_memcpy(resp->data_p, device->device_id, 3); // 设备ID,长ID的后3个字节 resp->data_p += 3; if (device->hart_revision == HART_PROTOCOL_VERSION_7) { *resp->data_p++ = device->s2m_preambles; // 从设备到主设备的响应前导码个数 *resp->data_p++ = device->last_device_variable; // 上一个设备变量,这表示应用程序应在现场设备中找到的最后一个设备变量代码(在执行Command 54时读取设备的变量) *resp->data_p++ = HI_UINT16(device->configuration_update_count); // 配置被更新的次数 *resp->data_p++ = LO_UINT16(device->configuration_update_count); *resp->data_p++ = device->extended_device_status; // 扩展现场设备状态未指定的任何位都是未定义的,必须设置为零。 *resp->data_p++ = HI_UINT16(device->manufacturer_identification_code); // 制造商标识码 *resp->data_p++ = LO_UINT16(device->manufacturer_identification_code); *resp->data_p++ = HI_UINT16(device->private_label_distributor_code); // 私有标签分销商代码 *resp->data_p++ = LO_UINT16(device->private_label_distributor_code); *resp->data_p++ = device->device_profile; // 设备配置文件 } } else { } return TRUE; } /** * @brief 读取子设备标识摘要 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_84_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { uint16_t identifier; if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { if (data->data_length < sizeof(hart_command_84_t)) { resp->code = RESPONSE_COMMUNICATION_CODE_5; return TRUE; } if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } io_system_device_info_t *info; identifier = B2S_UINT16(data->data.command_84.identifier); info = hart_master_get_device_by_identifier(identifier); if (info == NULL) { resp->code = RESPONSE_COMMUNICATION_CODE_9; return TRUE; } // 回复数据 *resp->data_p++ = HI_UINT16(info->device->identifier); *resp->data_p++ = LO_UINT16(info->device->identifier); *resp->data_p++ = info->card_index; *resp->data_p++ = info->channel_index; *resp->data_p++ = HI_UINT16(info->device->manufacturer_identification_code); *resp->data_p++ = LO_UINT16(info->device->manufacturer_identification_code); *resp->data_p++ = HI_UINT16(info->device->extended_device_type); *resp->data_p++ = LO_UINT16(info->device->extended_device_type); osel_memcpy(resp->data_p, info->device->device_id, 3); resp->data_p += 3; *resp->data_p++ = 0; // 保留 osel_memcpy(resp->data_p, info->device->long_tag, HART_PACKED32_LEN); resp->data_p += HART_PACKED32_LEN; *resp->data_p++ = info->device->device_revision; *resp->data_p++ = info->device->device_profile; *resp->data_p++ = HI_UINT16(info->device->private_label_distributor_code); *resp->data_p++ = LO_UINT16(info->device->private_label_distributor_code); osel_mem_free(info); } else { } return TRUE; } /** * @brief 读取I/O通道统计信息 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_85_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { io_system_message_count_t *message_count; if (data->data_length < sizeof(hart_command_85_t)) { resp->code = RESPONSE_COMMUNICATION_CODE_5; return TRUE; } if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } if (data->data.command_85.card >= HART_IO_MAXIMUM_NUMBER_CARDS) { resp->code = RESPONSE_COMMUNICATION_CODE_21; return TRUE; } if (data->data.command_85.channel >= HART_IO_MAXIMUM_NUMBER_CHANNELS_CARD) { resp->code = RESPONSE_COMMUNICATION_CODE_22; return TRUE; } message_count = hart_master_get_channel_message_count(data->data.command_85.card, data->data.command_85.channel); if (message_count == NULL) { resp->code = RESPONSE_COMMUNICATION_CODE_2; return TRUE; } *resp->data_p++ = data->data.command_85.card; *resp->data_p++ = data->data.command_85.channel; *resp->data_p++ = HI_UINT16(message_count->stx); *resp->data_p++ = LO_UINT16(message_count->stx); *resp->data_p++ = HI_UINT16(message_count->ack); *resp->data_p++ = LO_UINT16(message_count->ack); *resp->data_p++ = HI_UINT16(message_count->ostx); *resp->data_p++ = LO_UINT16(message_count->ostx); *resp->data_p++ = HI_UINT16(message_count->oack); *resp->data_p++ = LO_UINT16(message_count->oack); *resp->data_p++ = HI_UINT16(message_count->back); *resp->data_p++ = LO_UINT16(message_count->back); } else { } return TRUE; } /** * @brief 读取子设备统计信息 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_86_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { uint16_t identifier; if (data->data_length < sizeof(hart_command_86_t)) { resp->code = RESPONSE_COMMUNICATION_CODE_5; return TRUE; } if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } io_system_device_info_t *info; identifier = B2S_UINT16(data->data.command_86.identifier); info = hart_master_get_device_by_identifier(identifier); if (info == NULL) { resp->code = RESPONSE_COMMUNICATION_CODE_2; return TRUE; } *resp->data_p++ = HI_UINT16(info->device->identifier); *resp->data_p++ = LO_UINT16(info->device->identifier); *resp->data_p++ = HI_UINT16(info->device->message_count.stx); *resp->data_p++ = LO_UINT16(info->device->message_count.stx); *resp->data_p++ = HI_UINT16(info->device->message_count.ack); *resp->data_p++ = LO_UINT16(info->device->message_count.ack); *resp->data_p++ = HI_UINT16(info->device->message_count.back); *resp->data_p++ = LO_UINT16(info->device->message_count.back); osel_mem_free(info); } else { } return TRUE; } /** * @brief 写入I/O系统重试计数 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_87_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { uint8_t master_mode = 0; if (data->data_length < sizeof(hart_command_87_t)) { resp->code = RESPONSE_COMMUNICATION_CODE_5; return TRUE; } if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } master_mode = data->data.command_87.master_mode; if (master_mode != HART_IO_PRIMARY_MODE && master_mode != HART_IO_SECONDARY_MODE) { resp->code = RESPONSE_COMMUNICATION_CODE_2; return TRUE; } hart_master_attribute.io_system.master_mode = master_mode; // 回复数据 *resp->data_p++ = master_mode; } else { } return TRUE; } /** * @brief 写入I/O系统重试计数 * @param {hart_command_rsp_t} *data * @param {hart_response_t} *resp * @return {*} */ BOOL hart_master_command_88_rsp(const hart_command_rsp_t *const data, hart_response_t *resp) { if (data->delimiter.bits.frame_type == HART_STX_FRAME) // 请求帧, 主->从 { uint8_t retry_count = 0; if (data->data_length < sizeof(hart_command_88_t)) { resp->code = RESPONSE_COMMUNICATION_CODE_5; return TRUE; } if (FALSE == is_broadcast_address((uint8_t *)data->address, data->address_length)) { return FALSE; } retry_count = data->data.command_88.retry_count; if (retry_count < 2) { resp->code = RESPONSE_COMMUNICATION_CODE_4; return TRUE; } if (retry_count > 5) { resp->code = RESPONSE_COMMUNICATION_CODE_3; return TRUE; } hart_master_attribute.io_system.retry_count = retry_count; // 回复数据 *resp->data_p++ = retry_count; } else { } return TRUE; } BOOL hart_master_rsp_init(const hart_master_init_t *const init) { if (!DBG_ASSERT(init != NULL __DBG_LINE)) return FALSE; handle = (hart_master_init_t *)init; for (uint16_t i = 0; i < HART_COMMAND_MAX; i++) { hart_command_rsp_ptr_arr[i] = hart_master_command_undef_rsp; } hart_command_rsp_ptr_arr[HART_COMMAND_74] = hart_master_command_74_rsp; hart_command_rsp_ptr_arr[HART_COMMAND_75] = hart_master_command_75_rsp; hart_command_rsp_ptr_arr[HART_COMMAND_84] = hart_master_command_84_rsp; hart_command_rsp_ptr_arr[HART_COMMAND_85] = hart_master_command_85_rsp; hart_command_rsp_ptr_arr[HART_COMMAND_86] = hart_master_command_86_rsp; hart_command_rsp_ptr_arr[HART_COMMAND_87] = hart_master_command_87_rsp; hart_command_rsp_ptr_arr[HART_COMMAND_88] = hart_master_command_88_rsp; return TRUE; }