HART协议通用结构体及地址、常量的定义

在HART模块中,通常是通过UART发送一个字节,且需要11位二进制数据,第一位起始位,第二到九位共八位是要发送的数据,第十位是校验位<奇校验>,第十一位是停止位。

整体的HART命令字段由以下组成:
PREAMBLE START ADDR COM BCNT STATUS DATA CHK
对应序文 定界符 地址 命令号 数据长度 响应码 数据字节 奇偶校验(异或校验)
以上便是一个完整的Hart通信数据帧格式,其中Status(通信状态)只有在从机对主机通信时才会加入的。

  1. PREAMBLE 前导字符,作为通信同步的需要,是5到20个字节的0XFF,通常采用5个字节; 也就是5个0xFF

  2. START 起始字节符,将告之使用的结构为“长”还是“短”,消息源是否是“突发”模式消息。主机到从机为短结构时,起始位为 0X02,长帧时为 0X82。从机到主机的短结构值为 0X06,长结构值为0X86。而为“突发”模式的短结构值为 0X01,长结构为 0X81。一般设备进行通讯接收到 2 个0XFF 字节后,就将侦听起始位。

  3. ADDR 地址字符,包含了主机地址和从机地址,短结构中占 1 字节,长结构中占 5 字节。
    主机到从机为短结构时,起始位为02,长帧时为82。
    从机到主机的短结构值为06,长结构值为86
    “突发”模式的短结构值为01,长结构为81
    短指令时:地址码由一个字节表示(如80),其结构为

    一般我们不用到突发模式,这里的80表示的就是(主机1—-设备地址(0))
    长指令时:地址码由5个字节表示,其结构为

    另外,长结构的低 38 位如果都是 0 的话表示的是广播地址,即消息发送给所有的设备。

  4. COM 命令字节,范围为 253 个,用 HEX 的 0~FD 表示。31,127,254,255 为预留值。PS:一开始对此处提到的命令很困惑,就在心里发问,每个命令都什么含义?所有的厂家都支持么?终于,在一篇名为HCF_SPEC 99官方文档中找到

  5. BCNT 数据总长度,它的值表示的是 BCNT 下一个字节到最后(不包括校验字节)的字节数,其实说了这么多,无非是因为从机回传的数据中多了一个状态码,明确也是要算在数据长度的。接收设备用他可以鉴别出校验字节,也可以知道消息的结束。因为规定数据最多为 25 字节,所以它的值是从 0~27。

  6. STATUS 状态字节,也叫做“响应码”,顾名思义,只存在于从机响应主机消息的时候,用 2 字节表示。他将报告通讯中的错误、接收命令的状态(如:设备忙、无法识别命令等)和从机的操作状态。 如果我们在通讯过程中发现了错误,首字节的最高位(第 7 位)将置 1,其余的 7 位将汇报出错误的细节,而第 2 个字节全为 0。否则,当首字节的最高位为 0 时,表示通讯正常,其余的 7 位表示命令响应情况,第 2 个字节表示场设备状态的信息。UART 发现的通讯错误一般有:奇偶校验、溢出和结构错误等。命令响应码可以有 128 个,表示错误和警告,他们可以是单一的意义,也可以有多种意义,我们通过特殊命令进行定义、规定。现场设备状态信息用来表示故障和非正常操作模式。此处依然是一个专门的文档来叙述 HCF_SPEC_307 。

  7. DATA 数据字节,首先需说明的是并非所有的命令和响应都包含数据字节,它最多不超过 25 字节(随着通讯速度的提高,正在要求放宽这一标准)。数据的形式可以是无符号的整数(可以是8,16,24,32 b),浮点数(用 IEEE754 单精浮点格式)或 ASCII 字符串,还有预先制定的单位数据列表。具体的数据个数根据不同的命令而定!此处查阅官方文档 HCF_SPEC_183<数据格式表> 此中数据量相当大 HCF_SPEC 99 HCF_SPEC 127 HCF_SPEC-151;

  8. CHK 奇偶校验,方式是纵向奇偶校验,从起始字节开始到奇偶校验前一个字节为止。

在这些数据中,除了数据长度对应的数据位不同,起始字节符对应的地址字符也不同,在做命令解析的时候 要根据起始字节和数据大小来判断数据位的位置

例子:
FF FF FF FF FF 82 A6 06 BC 61 4E 01 00 B0
上面是主机到从机发送的一条消息。前 5 个字节值都为 FF,显然他是前导字节。接着的 82 起始字节,表示主机到从机发出的长结构的消息。
后 5 个字节 “A6,06,BC,61,4E”是地址字节化为二进制表示如下:
A6 06 BC 61 4E
1010 0110 0000 0110 1011 1100 0110 0001 0100 1110
可见首字节 A6 的最高位为 1 表示主机,次高位为 0 表示非突发模式,后面的 38 位二进制数表示设备的惟一标号:“100110”是生产厂家代码,值为 38,是 Rosemount 公司的代码;后一字节 06 是设备型号代码,06 代表的型号是3051C;后面的 3 个字节是设备识别号,本例中的值为 12345678;再接下来的 01 是命令字节,表示 1 号命令,该命令的返回内容可在文档资料中找到 HCF_SPEC 127,即读取 PV 值,后面的 00 是表示数据的长度;本例中无数据,值为 0;最后是校验字节 B0;

FF FF FF FF FF 86 A6 06 BC 61 4E 01 07 00 00 06 40 B0 00 00 45
上面表示的是从机到主机的一条消息。本例大部分与上例相似,不同的是数据字节不再为 0,其中的 06 表示单位 PSI;后面的 4 个字节是用浮点数表示的值 为 5.5。并且由于本例是由从机到主机的应答消息,所以存在着状态位,即本例中的“00 00”,表示“OK”。

将数据依次排列:

第一列为前导字符
00 60为状态码
41 3F A0 00到41 95 00 00为数据位 数据长度1A

上面是突发模式发出的一条消息。第 1 个字节 81 表示突发的长结构模式,与前例中相似的地方不再介绍。注意到状态字节“00 60”后的字节“41 3F A0 00”,他表示的是当前的电流值,是IEEE754格式的浮点数,计算后是 11.9766;后面的 27 表示单位 mA,像后面的 39 表示“%”一样。数据字节中的"42 47 60 00",“BF 06 60 00”,“41 95 00 00”分别表示"SV”,“TV”,"FV"表示方法与 PV 相同。经过解释后的消息可以表示为:“LBTXS/RdAllPv/026/0060/11.9766/mA/11.9766/%/49.8438/psi/-0.524902/%/18.625”。 所有的数据格式在文档资料Common Tables HCF_SPEC 183中。附命令3——属于通用命令,可在HCF_SPEC_127中查找


以下代码通用HART结构体定义:

#ifndef __HART_CMD_H__
#define __HART_CMD_H__
#include<stdint.h>#define HART_UART_BaudRate          1200    //波特率
#define HART_UART_WordLength        0       //数据长度 默认0就是8位
#define HART_UART_StopBits          0       //停止位 默认0就是1位
#define HART_UART_Parity            2       //校验位 0位无 1为偶校验 2为奇校验#define HART_ETC_START             0x23    //放在PREAMBLE之前
#define HART_ETC_STOP               0x40    //放在CHK之后#define HART_PREAMBLE              0xFF    //一般是五个
#define HART_PREAMBLE_Normal_Size   5
#define HART_PREAMBLE_Min_Size      2
#define HART_PREAMBLE_Max_Size      20#define HART_START_Master_LONG      0x82  //主机的消息
#define HART_START_Master_SHORT     0x02#define HART_START_Slave_LONG       0x86     //从机的消息
#define HART_START_Slave_SHORT      0x06#define HART_START_Burst_LONG       0x81     //突发模式
#define HART_START_Burst_SHORT      0x01//HART通用结构体 主要用于接收/发送时的数组和结构体之间的转换
typedef struct
{uint8_t PREAMBLE[5];uint8_t START;uint8_t ADDR[5];uint8_t COM;uint8_t BCNT;uint8_t STATUS[2];uint8_t DATA[25];uint8_t CHK;
}HART_Normal_Struct;//HART主机短结构体
typedef struct{const uint8_t PREAMBLE[5];           //5个OXFFconst uint8_t START;            //标志uint8_t ADDR;               //移位uint8_t COM;              //命令uint8_t BCNT;             //数据长度uint8_t DATA[16];     //数据uint8_t CHK;                //校验值
}HART_Master_SHORT_Struct;//HART从机短结构体
typedef struct{const uint8_t PREAMBLE[5];               //5个OXFFconst uint8_t START;                //标志uint8_t ADDR;                   //移位uint8_t COM;                //命令uint8_t BCNT;                   //数据长度uint8_t STATUS[2];        //状态 主机发送的消息中没有  响应码!uint8_t DATA[16];           //数据uint8_t CHK;                    //校验值
}HART_Slave_SHORT_Struct;//HART主机长结构体
typedef struct{const uint8_t PREAMBLE[5];               //5个OXFFconst uint8_t START;                //标志uint8_t ADDR[5];            //长地址uint8_t COM;               //命令uint8_t BCNT;                   //数据长度uint8_t DATA[25];         //数据uint8_t CHK;                    //校验值
}HART_Master_LONG_Struct;//HART从机长结构体
typedef struct{const uint8_t PREAMBLE[5];               //5个OXFFconst uint8_t START;                //标志uint8_t ADDR[5];            //长地址uint8_t COM;               //命令uint8_t BCNT;                   //数据长度uint8_t STATUS[2];        //状态 主机发送的消息中没有uint8_t DATA[25];            //数据uint8_t CHK;                    //校验值
}HART_Slave_LONG_Struct;#endif

HART协议通用结构体及地址、常量的定义相关推荐

  1. Linux中的两个经典宏定义:获取结构体成员地址,根据成员地址获得结构体地址;Linux中双向链表的经典实现。...

    倘若你查看过Linux Kernel的源码,那么你对 offsetof 和 container_of 这两个宏应该不陌生.这两个宏最初是极客写出的,后来在Linux内核中被推广使用. 1. offse ...

  2. c语言把结构体首地址放入指针,C语言基础———指针,结构体指针,函数指针

    指针基础 一 指针就是地址,地址就是指针.指针存储的是内存的地址. 二 指针的定义 1.&表示取址运算符,&a 可以取到 a 在内存中的地址;打印地址的占位符为(%p),printf( ...

  3. HART协议数据格式避坑(C语言压缩字符串Packed-ASCII和ASCII转换)

    HART协议数据格式避坑(C语言压缩字符串Packed-ASCII和ASCII转换) 首先HART数据格式如下: 重点就是浮点数和字符串类型 Latin-1就不说了 基本用不到 浮点数 浮点数里面 如 ...

  4. Unity3d连接SQL Server数据库出现SocketException: 使用了与请求的协议不兼容的地址错误...

    这两天,同学问我Unity3d连接SQL Server的问题,当时我只是简单的说:"应该一样吧,就是那简单的几句啊".之后他让我试了下,我才发现有问题了.故此写下一篇博客,要牢记这 ...

  5. 结构体成员地址获得结构体起始地址

    经常我们在一些开源的或者内核代码中会看到. #define TYPE_STRUCT(ptr, type, member)((type *)((char*)(ptr)-(unsigned long)(& ...

  6. 通过结构体某个成员的地址计算结构体首地址 (转)

    最近在CU论坛上有很多人在问这样一个问题:给出一个结构体成员的地址计算该结构体的起始地址.其实这个题我之前也没有接触过,据说内核代码中有这样用的,但还没有看到.不过觉得这个题的解决方法还是有一定技巧的 ...

  7. 通过结构体某个成员的地址计算结构体首地址

    给出一个结构体成员的地址计算该结构体的起始地址,据说内核代码中有这样用的,但还没有看到.不过觉得这个题的解决方法还是有一定技巧的,就总结一下.下面是实现的代码. /* Author: Godbach ...

  8. 结构体第一个成员是结构体,则为父结构体首地址demo(六)

    //1.完整版 #include <stdio.h> #include <stdlib.h> struct audio_stream_in {ssize_t (*read)(s ...

  9. Modbus协议的数据模型和地址模型,Modbus寄存器40001,30001是什么意思?

    在使用Modbus协议的时候,经常会遇到诸如40001.30001,10001之类的地址,这些数字代表什么含义呢?这其实是Modbus协议的数据模型和地址模型. Modbus协议的数据模型 数据模型是 ...

最新文章

  1. 使用OpenCV实现道路车辆计数
  2. 使用js技术使字体闪烁
  3. 2013\National _C_C++_C\1.好好学习
  4. python线性加权模型_局部加权之线性回归(1) - Python实现
  5. MIT6.830 lab6 Rollback and Recovery 实验报告
  6. php指定时间 n天,PHP实现指定时间的n月之前的这一天的两种算法
  7. tp3.2 相同应用绑定多个入口文件,不同的入口文件可以绑定不同的模块
  8. Android常用提示框(dialog和popuwindow)
  9. Oracle 19c 安装步骤
  10. Redis下载安装全过程教程(非常详细,适用于个人学习使用)
  11. 图说Python菜鸟版:第18章 JSON文件解析
  12. 架构师之路 — 架构师的职责
  13. [4G5G专题-8]:RRU 峰均比降低技术CFR(波峰系数削减)
  14. 吊炸天的 JD-hotkey !京东开源!单机 QPS 高达 370000
  15. 3.19 使用钢笔工具绘制一枚诱人的梨子 [Illustrator CC教程]
  16. excel2016 for mac 二维表转一维表
  17. 个人总结-网络安全学习和CTF必不可少的一些网站
  18. MySQL数据库web客户端管理工具软件
  19. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux信号机制分析
  20. HTML5基础之常用标签以及标签选择器

热门文章

  1. 最少转弯问题(turn)
  2. python:xml.parsers.expat --- 使用 Expat 的快速 XML 解析
  3. 健身前需要做热身运动吗?有哪些准备?
  4. Kubernetes1.7新特性:支持绕过docker,直接通过containerd管理容器
  5. LPWA市场后起之秀 低功耗广域网技术ZETA抢攻物联网
  6. Flink Kafka
  7. 驱动音乐律动(全局)
  8. 树莓派学习笔记003-超声波距离传感器
  9. sockets是什么?
  10. MQTT心跳 Keep Alive