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

469 lines
17 KiB
C
Raw 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.

#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保留;低3bits5.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;
}