HART协议贴的人少,现在发一个。只用了部分命令。
#include "use.h"
#include "Ver.H"
#include <string.h>
#include <ctype.h>
#include <HART_COM.h>
#include "include.h"
/*
FF FF FF FF FF 06 01 03 10 00 DC 00 00 00 00 ED 8F C2 43 00 00 00 00 00 00 A0 40 34
FF FF FF FF FF 06 01 03 10 00 DC 00 00 00 00 ED 8F C2 43 00 00 00 00 00 00 A0 40 34 、
HART命令0:读标识码
返回扩展的设备类型代码,版本和设备标识码。
请求:无
响应:
字节0: 254
字节1: 制造商ID(Enum)
字节2: 设备类型(Enum)
字节3: 请求的最小前导符数(主->从)
字节4: 通用命令文档版本号
字节5: 设备规范版本号
字节6: 设备软件版本号
字节7: (前五个bit)设备硬件版本号
(后三个bit)物理信号类型(Enum)
字节8: 设备标志
字节9-11: 设备ID号
*/
void HART_GET_RD_0_TO_MAST(unsigned char adr,unsigned char com){
const char COMM0[]={
254,adr0,2,MAX_0xff,HART_VER,6,7,0xf1,adr1,adr2,adr3,0 //预留出最后一个字节放菜单地址!
};
unsigned char buf[100],b[30],cnt,b_cnt;
//****************************************************************
//装配工作参数 浮点数
memcpy(b,COMM0,sizeof(COMM0));
b_cnt =sizeof(COMM0);
b[b_cnt-1] =adr; //最后的字节放菜单地址!
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0); //0=响应码!
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
//**********************************************************************************
//装配工作参数 返回16个字节,4个浮点数
unsigned char Init_WORK_Data_B(unsigned char *buf){
float b;
b=LedMenu.B;
buf[0]='m';
Get_MinFloat_MCU(buf+1,(unsigned char *)&b);
return 5; //返回5个字节
}
//**********************************************************************************
//装配工作参数 返回8个字节,2个浮点数
unsigned char Init_WORK_Data_Ao(unsigned char *buf){
float b;
b=LedMenu.AD;
Get_MinFloat_MCU(buf,(unsigned char *)&b);
b=LedMenu.C;
Get_MinFloat_MCU(buf+4,(unsigned char *)&b);
return 8; //返回8个字节
}
/**********************************************************************************
//从应答工作数据
4个字节:
1-4:浮点数的数据
***********************************************************************************/
void HART_GET_WORK_B_TO_MAST(unsigned char adr,unsigned char com){
unsigned char buf[100],cnt,b[20],b_cnt;
//****************************************************************
//装配工作参数 浮点数
b_cnt =Init_WORK_Data_B(b);
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0);
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
/**********************************************************************************
//从应答工作数据
4个字节:
1-4:浮点数的数据
***********************************************************************************/
void HART_GET_WORK_Ao_TO_MAST(unsigned char adr,unsigned char com){
unsigned char buf[100],cnt,b[20],b_cnt;
//****************************************************************
//装配工作参数 浮点数
b_cnt =Init_WORK_Data_Ao(b);
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0); //0=响应码!
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
/***************************************************************************************
HART命名13:读标签Tag,描述符Description和日期Date
读设备的Tag,Description and Date。
请求:无
响应:
字节0-5: 标签Tag,ASCII
字节6-17: 描述符,ASCII
字节18-20:日期,分别是日、月、年-1900
****************************************************************************************/
unsigned char Init_MAST_Data(char *buf){
memcpy(buf,MAST_Tag,8);
Get_ASCII_6bit(buf);
memcpy(buf+6,MAST_Description,16);
Get_ASCII_6bit(buf+6);
buf[18]=MAST_Day;
buf[19]=MAST_Mon;
buf[20]=MAST_Use_Year;
return 21;
}
//***************************************************************************************
//返回=0;不相等!==1是相等
unsigned char JB_TAG_Name(char *buf){
char s[10],t[50];
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
memcpy(t,buf,6); //命令只有6个字节TAG
Decode_ASCII_6bit(t,s);
if(strcmp(s,MAST_Tag)) return 0;
return 1; // 相等返回1!
}
//***************************************************************************************
void HART_GET_RD_13_TO_MAST(unsigned char adr,unsigned char com){
unsigned char buf[100],cnt,b[50],b_cnt;
//****************************************************************
//装配工作参数 浮点数
b_cnt =Init_MAST_Data((char *)b);
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0); //0=响应码!
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
/**********************************************************************************
读设备含有的消息。
请求:无
响应:
字节0-23: 设备消息,ASCII
设备的值字节;
P----- 0-3 设备的值字节(单位代码字节 );
t----- 5-8
S-- 改成P3菜单中的t1
K---9 改成P3菜单中的to
FO----- 15-18设备的值字节(单位代码字节 );
FS----- 20-23H-
HART命令12:读消息(Message)
读设备含有的消息。
请求:无
响应:
字节0-23: 设备消息,ASCII
***********************************************************************************/
void HART_GET_RD_12_TO_MAST(unsigned char adr,unsigned char com){
unsigned char buf[100],cnt,b[50],b_cnt;
b_cnt=sprintf((char *)b,"P:%d T%4.2f K%4.2f Fo%4.2f Fs%4.2f ",Mp1.P,Mp1.t0,Mp1.bo,Mp1.Fo,Mp1.Fs);
if(b_cnt>31) b[32]=0;
Get_ASCII_6bit((char *)b);
b_cnt=24;
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0);
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
//*****************************************************
//得到菜单数据;返回=0 无数据;=1是整数;=2是浮点数!
unsigned char Hart_get_Mp1(unsigned char id,unsigned char *pInt,float *pFloat){
unsigned char j=0;
unsigned char *xP;
float *xF;
MP1 mp1;
if(id>=MaxK) return 0;
//*********************************************************************************
memcpy((unsigned char *)&mp1,(unsigned char *)&Mp1,sizeof(MP1));
mp1.C=LedMenu.C;
mp1.AD=LedMenu.AD;
xP=GetAdr(id,(unsigned char *)&mp1);
if (MenuAsc[id].Type <=Int4){ //整数处理
*pInt=*xP;
j=1;
}else{ //浮点数处理
xF=(float *)xP;
*pFloat=*xF;
j=2;
}
return j;
}
//*********************************************************************888
//判别序号可写 return 0 = 可以写入
const unsigned char IDK_MENU[]={
2,3,5,6,8,9,14,17,18,19,20,21,25,26,27,28,29,30
};
unsigned char JB_Id_En_Wr(unsigned char id){
unsigned char i;
for(i=0;i<sizeof(IDK_MENU);i++){
if(id==IDK_MENU[i]) return 1;
}
return 0;
}
//*****************************************************
//得到菜单数据;返回=0 无数据;=1是整数;=2是浮点数!
unsigned char Hart_wr_Mp1(unsigned char id,float f1){
unsigned char j=0;
unsigned char *xP;
float *xF;
if(id>=MaxK) return 0;
//*********************************************************************************
//添加写入控制2016-7-11
if(JB_Id_En_Wr(id)) return 0;
//*********************************************************************************
xP=GetAdr(id,(unsigned char *)&Mp1);
if (MenuAsc[id].Type <=Int4){ //整数处理
if(f1<MenuAsc[id].Min) f1=MenuAsc[id].Min;
if(f1>MenuAsc[id].Max) f1=MenuAsc[id].Max;
*xP=(unsigned char)f1;
j=1;
}else{ //浮点数处理
xF=(float *)xP;
if(f1<MenuAsc[id].Min) f1=MenuAsc[id].Min;
if(f1>MenuAsc[id].Max) f1=MenuAsc[id].Max;
*xF=f1;
j=2;
}
return j;
}
/*****************************************************************************************
命令60:读模拟输出AO和量程的百分比
读模拟输出值和所选模拟输出的量程百分比。这个模拟输出总是匹配设备相关的物理模拟输出,
包括报警条件和设置值。量程的百分比没有限制在0-100%之间,但是不能超过传感器的高低限。
请求:
字节0: 模拟输出号代码
响应:
字节0: 模拟输出号代码
字节1: 模拟输出单位代码
字节2-5: 模拟输出值
字节6-9: 模拟输出量程百分比 发送短消息
******************************************************************************************/
void HART_GET_RD_60_TO_MAST(unsigned char adr,unsigned char com,unsigned char id){
unsigned char buf[100],cnt,b[100],b_cnt,i,dat;
float f1;
//****************************************************************
//装配工作参数 浮点数
memset(b,0,sizeof(b));
i=Hart_get_Mp1(id,&dat,&f1);
if(i==0) b_cnt=0;//无数据!
if(i==1){
b[0]=id;
b[1]=id+'=';
f1=dat;
Get_MinFloat_MCU(b+2,(unsigned char *)&f1);
b_cnt=10;
}
if(i==2){
b[0]=id;
b[1]='=';
Get_MinFloat_MCU(b+2,(unsigned char *)&f1);
b_cnt=10;
}
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0);
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
/**********************************************************************************
命令64:写模拟输出附加阻尼值
为所选模拟输出写附加阻尼值。附加的阻尼值表示一个时间常数。
请求:
字节0: 模拟输出号代码
字节1-4: 模拟输出附加阻尼值,单位秒
响应:
字节0: 模拟输出号代码
字节1-4: 模拟输出附加阻尼值,单位秒
*************************************************************************************/
void HART_GET_WR_64_TO_MAST(unsigned char adr,unsigned char com,unsigned char *p){
unsigned char buf[100],cnt,id,i,b[50],b_cnt;
float f1;
//****************************************************************
memset(b,0,sizeof(b));
id=p[0];
f1=Get_MaxFloat_MCU(&p[1]); //得到数据
i=Hart_wr_Mp1(id,f1);
if(i==0){
b_cnt=0;
}else{
b[0]=id;
Get_MinFloat_MCU(b+1,(unsigned char *)&f1);
b_cnt=5;
WriteToEexx(0);
}
//************************************************************
cnt =HART_Format_HEAD(buf,adr,com,b_cnt,0);
memcpy(buf+cnt,b,b_cnt);
HART_Send_OUT(buf,cnt+b_cnt);
}
/**********************************************************************************
//从应答工作数据
4个字节:
1-4:浮点数的数据
***********************************************************************************/
void HART_RESET_TO_MAST(unsigned char adr,unsigned char com){
unsigned char buf[100],cnt;
//****************************************************************
cnt =HART_Format_HEAD(buf,adr,com,0,0); //应答吗=00 OK 数据长度=0
HART_Send_OUT(buf,cnt);
//******************************************************************
//等待发送完毕,复位!
tDelay(2000);
//reset
NVIC_SystemReset();
}
#include "Ver.H"
#include <string.h>
#include <ctype.h>
#include <HART_COM.h>
#include "include.h"
/*******************************************************************
1、菜单中这几个参数项需要读出和修改:
P1中的:L,H,E,dr,P P2中的:Ed,SF,bo 一共7个参数项;
---这7个参数项不知道用什么命令来进行读写?
请你帮助考虑一下。
2、HART命令中,有如下命令应该要用到:
⑴ 0#命令---读标识码 (好像是个广播命令)
⑵ 3#命令---读主变量电流(测量值)
⑶ 6#命令---置随选地址(确定工作模式)
⑷ 15#命令---读主变量输出信息(上下限值)
⑸ 40#命令---进入/退出电流模式
⑹ 41#命令---执行设备自检
⑺ 42#命令---执行设备复位
******************************************************************/
//前面的4个地址是固定的,后面一个是可以改的!用MP1.ADR 代替了!
//#define adr0 0x02
//#define adr1 0x23
//#define adr2 0x34
//#define adr3 0x45
//#define MAX_0xff 5 //前导符的个数!
//#define HART_VER 5 // 版本
//----------------------------------------------------------------------------------
//static unsigned char fHART_LONG_ADR=0; //=0 短地址标至;=1 是长地址!
//static unsigned char cnt_0xff=MAX_0xff; //主机发送0XFF的个数,从机回复添加相同的个数 !
//**************************************************************************
extern unsigned char cnt_0xff; //主机发送0XFF的个数,从机回复添加相同的个数 !
extern unsigned char fHART_LONG_ADR; //=0 短地址标至;=1 是长地址!
//---------------------------------------------------------------------------------------------
unsigned char HART_Get_FF(unsigned char *p){
memset(p,0xff,cnt_0xff);
return cnt_0xff;
}
//**************************************************************************
//校验处理采用异或处理
unsigned char Get_XOR(unsigned char *p,unsigned char Long){
unsigned char i;
i=*p++;
Long--;
while(Long--){
i ^=*p++;
}
return i;
}
//*********************************************************************************
//装配HART文件头
unsigned char HART_Format_HEAD(unsigned char *buf,unsigned char adr,unsigned char com,unsigned char Long,unsigned int ask){
unsigned char cnt=0;
if(fHART_LONG_ADR){
buf[cnt++] = H_START_SLAVE_LONG; //下发送长地址命令!
buf[cnt++] = adr0 | 0x80; //读设备的地址!
buf[cnt++] = adr1; //读设备的地址!
buf[cnt++] = adr2; //读设备的地址!
buf[cnt++] = adr3; //读设备的地址!
buf[cnt++] = adr; //读设备的地址!
}else{
buf[cnt++] = H_START_SLAVE_SHORT; //下发送短命令!
buf[cnt++] = adr | 0x80; //读设备的地址!
}
buf[cnt++] = com; //读设备的标识符!
buf[cnt++] = Long+2; //数据长度+状态吗2个字节!
buf[cnt++] = (ask & 0xff00) >>8 ; //状态 00 =ok!
buf[cnt++] = ask & 0xff;
return cnt;
}
//***********************************************************
//压缩成6位ASCII,高位回复时判断添加D6=1
//不足4个整数位,添加'_'
void Get_ASCII_6bit(char *buf){
unsigned char i,j,cnt;
char s[40];
memset(s,'_',sizeof(s));
cnt=strlen(buf);
for(i=0;i<cnt;i++){
j=toupper(buf[i]);
s[i]=j;
}
cnt=cnt/4+1;
memset(buf,0,strlen(buf));
for(i=0;i<cnt;i++){
for(j=0;j<3;j++){
buf[i*3+j]=(s[i*4+j] & 0X3F)<<(2*j+2) | (((s[i*4+j+1] & 0X3F)<<2)>>(6-2*j));
}
}
}
//******************************************************************
//右移还原压缩码?
//******************************************************************
unsigned char RR_ASCII_6bit (char *buf,char *s){
union{
unsigned int i;
unsigned char s[4];
}dat;
unsigned char j;
dat.s[0]=s[3];
dat.s[1]=s[2];
dat.s[2]=s[1];
dat.s[3]=s[0];
j=4;
while(j--){
dat.i >>=2;
buf[3-j]=dat.s[j] & 0x3f;
if(buf[3-j] <' ') buf[3-j] |=0x40;
}
return 4;
}
//******************************************************************
//解码6位ASCII码 buf=原编码地址;TAG:解码放置的地址!
//******************************************************************
unsigned char Decode_ASCII_6bit(char *buf,char *Tag){
char s[40],len,i,j,cnt;
memset(s,0,sizeof(s));
strcpy(s,buf);
len=strlen(s);
cnt=len/3;
i=0;
for(j=0;j<cnt;j++){
i +=RR_ASCII_6bit (Tag+i,&s[j*3]);
}
return i;
}
//*********************************************************************************
//发送hart 数据包
void HART_Send_OUT(unsigned char *buf,unsigned char cnt){
unsigned char Buf[100],i;
buf[cnt]=Get_XOR(buf,cnt); //XOR校验!!!
i= HART_Get_FF(Buf); //添加0XFF开始!!
memcpy(Buf+i,buf,++cnt); //数据合并!!!
//--------------------------------------------------------------
//发送!
UART_SendStart(COM0,Buf,cnt+i);
}
//******************************************************************************
//FF的数据处理 cnt=有多少个OXFF
unsigned char *JB_FF(unsigned char *p,unsigned char *cnt){
char i=20;
while(i--){
*cnt=19-i;
if( *p++ !=0xff) return --p;
}
return NULL;
}
一周热门 更多>