469 lines
17 KiB
C
469 lines
17 KiB
C
#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;
|
||
}
|