搜索
bottom↓
回复: 28

分享: STM32L151+HART协议

  [复制链接]

出0入20汤圆

发表于 2017-7-13 10:16:25 | 显示全部楼层 |阅读模式
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();
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入20汤圆

 楼主| 发表于 2017-7-13 10:16:43 | 显示全部楼层
#include         "use.h"
#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;
}

出0入20汤圆

 楼主| 发表于 2017-7-13 10:17:25 | 显示全部楼层
#include         "use.h"
#include        "Ver.H"
#include         <HART_COM.h>
#include        "include.h"
//----------------------------------------------------------------------------------
unsigned char fHART_LONG_ADR=0;                                 //=0 短地址标至;=1 是长地址!
unsigned char cnt_0xff=MAX_0xff;                                 //主机发送0XFF的个数,从机回复添加相同的个数 !

//**************************************************************************************
//hart 命令处理 p指向 地址,长=最后一个地址 ;短地址=015
//**************************************************************************************
unsigned char Hart_Command_Do(unsigned char  *p ){
        unsigned char com;

        com=p[0];
        //**********************************************************
        switch (com){
                case 0:{                //0#命令!
                                //----------------------------------------------------------------------
                                //读取设备参数
                                HART_GET_RD_0_TO_MAST(Mp1.Ar,com);
                                break;
                }
                case HART_COM_RD_WORK_B:{
                                //----------------------------------------------------------------------
                                //读取工作参数
                                HART_GET_WORK_B_TO_MAST(Mp1.Ar,com);
                                break;
                }
                case HART_COM_RD_WORK_Ao:{
                                //----------------------------------------------------------------------
                                //读取工作参数
                                HART_GET_WORK_Ao_TO_MAST(Mp1.Ar,com);
                                break;
                }
               
                case HART_COM_RD_11:{
                                //----------------------------------------------------------------------
                                //判断是否是TAG
                                if(JB_TAG_Name((char *)&p[2]))                HART_GET_RD_0_TO_MAST(Mp1.Ar,0);//com==11
                                break;
                       
                }                case HART_COM_RD_12:{
                                //----------------------------------------------------------------------
                                //读取工作参数menu0
                                HART_GET_RD_12_TO_MAST(Mp1.Ar,com);
                                break;
                }
               
                case HART_COM_RD_13:{
                                //----------------------------------------------------------------------
                                //读取工作参数menu0
                                HART_GET_RD_13_TO_MAST(Mp1.Ar,com);
                                break;
                }

                case HART_COM_RD_60:{
                                //----------------------------------------------------------------------
                                //读取工作参数menu0 根据主机的代号!
                                HART_GET_RD_60_TO_MAST(Mp1.Ar,com,p[2]);
                                break;
                }
               
                case HART_COM_WR_64:{
                                //----------------------------------------------------------------------
                                //写菜单参数
                                HART_GET_WR_64_TO_MAST(Mp1.Ar,com,&p[2]);
                                break;
                }
               
                case HART_COM_WR_17:{
                                //----------------------------------------------------------------------
                                //读取工作参数menu1
                                //HART_GET_WR_17_TO_MAST(Mp1.Ar,com,p);
                                break;
                }
                case HART_COM_WR_RESET:{
                                //----------------------------------------------------------------------
                                //复位
                                HART_RESET_TO_MAST(Mp1.Ar,com);
                                break;
                }               
        }
        return 1;       
}
//******************************************************************************
//接收HART的数据处理
//生成发送数据        返回[0=说明没有数据 =1接收到了数据;2=数据校验错误!]
//*******************************************************************
unsigned char GET_hart_DO(unsigned char *Buf,unsigned char CNT){
        unsigned char crc,ret,buf[100];
        unsigned char *p;
       
        if(CNT < 10) return 3;                  //数据长度不等于!
        memcpy(buf,Buf,CNT);
        p=JB_FF(buf,&ret);                                         //检测前端的FF的个数,返回FF下一个地址位置,无FF,返回NULL;
        cnt_0xff=ret;                                                                //保存前导FF的个数!!
        if(ret==0)  return 5;
        if(p==NULL) return 4;
        crc=Get_XOR(p,CNT-1-ret);                //校验处理!
        if(crc !=Buf[CNT-1]) return 6;
        //**********************************************************************************************************
        //数据正确的长短地址处理!
        if(p[0] == H_START_MAST_SHORT){
                fHART_LONG_ADR=0;
                if((p[1] & B0011_1111)==0){
                        //p[6]=0; //0#命令! 广播地址!
                        ret=Hart_Command_Do(&p[6]);                //最低位是可变地址!
                }else{
                        if((p[1] & B0011_1111)        != Mp1.Ar) return 2;        //无论长短地址,均比较最后一个地址!
                        ret=Hart_Command_Do(&p[2]);
                }
        }
        if(p[0] == H_START_MAST_LONG){
                fHART_LONG_ADR=1;
                if ((p[1] & B0011_1111) ==0 &&  p[2]==0 && p[3]==0 && p[4]==0 && p[5]==0){
                        //p[6]=0; //0#命令! 广播地址!
                        ret=Hart_Command_Do(&p[6]);                //最低位是可变地址!
                }else{
                        if(p[5] != Mp1.Ar) return 2;        //无论长短地址,均比较最后一个地址!
                        ret=Hart_Command_Do(&p[6]);
                }
        }
        return ret;
}
//********************************************************************************
//从机不断查询
void JB_GetHART_DATA(void){
        unsigned char i;
        unsigned char   Buf[200];
        static unsigned int DelayTimer=0;
       
        if(Mp1.tr==0){        //总线
                memset(Buf,0,sizeof(Buf));
                i=HART_GET_UART_DATA(Buf);
                if(i==0) return ;
                GET_hart_DO(Buf,i);
        }
        //--------------------------------------------------------
        if(Mp1.tr==1){        //自动重发
                if (++DelayTimer >=(1500/TK/LedMenu.TK0)){
                        DelayTimer=0;       
                        HART_GET_WORK_B_TO_MAST(Mp1.Ar,HART_COM_RD_WORK_B);//HART_COM_RD_WORK_B
                }
        }
}

出0入20汤圆

 楼主| 发表于 2017-7-13 10:18:43 | 显示全部楼层

#ifndef HART_H
#define HART_H
/*******************************************************************
(1)PREAMBLE 导言字节,一般是5~20个FF十六进制字节。他实际上是同步信号,各通讯设备可以据此略做调整,保证信息的同步。
在开始通讯的时候,使用的是20个FF导言,从机应答0信号时将告之主机他"希望"接收几个字节的导言,另外主机也可以用59号命令告诉从机应答时应用几位导言。
(2)START 起始字节,他将告之使用的结构为"长"还是"短"、消息源、是否是"突发"模式消息。主机到从机为短结构时,起始位为02,长帧时为82。
从机到主机的短结构值为06,长结构值为86。而为"突发"模式的短结构值为01,长结构为81。一般设备进行通讯接收到2个FF字节后,就将侦听起始位。
(3)ADDR 地址字节,他包含了主机地址和从机地址,如前所述,短结构中占1字节,长结构中占5字节。
无论长结构还是短结构,因为HART协议中允许2个主机存在,所以我们用首字节的最高位来进行区分,
值为1表示第一主机地址,第二主机用0表示。"突发"模式是特例,0,1值将交替出现,也就是说,在该模式下,赋予2个主机的机会均等。
次高位为1表示为"突发"模式,短结构用首字节的0~4位表示值为0~15的从机地址,第5,6位赋0;
而长结构用后6位表示从机的生产厂商的代码,第2个字节表示从机设备型号代码,后3~5个字节表示从机的设备序列号,构成"唯一"标志码。

PREAMBLE         START           ADDR                COM     BCNT     STATUS   DATA     PARITY
序文             定界符    地址    命令号   数据长度  响应码   数据字节  奇偶校验

1、菜单中这几个参数项需要读出和修改:
   P1中的:L,H,E,dr,P  P2中的:Ed,SF  一共7个参数项;
   ---这7个参数项不知道用什么命令来进行读写?
      请你帮助考虑一下。

2、HART命令中,有如下命令应该要用到:
   ⑴ 0#命令---读标识码 (好像是个广播命令)
   ⑵ 3#命令---读主变量电流(测量值)
   ⑶ 6#命令---置随选地址(确定工作模式)
   ⑷ 15#命令---读主变量输出信息(上下限值)
   ⑸ 40#命令---进入/退出电流模式
   ⑹ 41#命令---执行设备自检
   ⑺ 42#命令---执行设备复位

******************************************************************/
#define adr0                0x02
#define adr1                0x23
#define adr2                0x34
#define adr3                0x45

#define MAX_0xff                5                //前导符的个数!
#define HART_VER                5                // 版本

//***************************************************************************
#define  MAST_Tag                                                  "4LCD    "                                                //8个字节
#define  MAST_Description                  "low-power       "                //16个字节!
#define  MAST_Day                                                        23
#define  MAST_Mon                                                        05
#define  MAST_Year                                                (2016)
#define  MAST_Use_Year                                (MAST_Year-1900)
//***************************************************************************

#define HART_COM_RD_WORK_B                        1                        //HART的读1个工作参数命令!
#define HART_COM_RD_WORK_Ao                        2                        //HART的读2个工作参数命令!

#define HART_COM_RD_10                                        10                //HART的读4个工作参数命令!
#define HART_COM_RD_11                                        11                //HART的读4个工作参数命令!
#define HART_COM_RD_12                                        12                //HART的读4个工作参数命令!
#define HART_COM_RD_13                                        13                //HART的读4个工作参数命令!
#define HART_COM_RD_60                                        60                //HART的读1个工作参数命令!
#define HART_COM_WR_64                                        64                //HART的写一个工作参数命令!
#define HART_COM_WR_17                                        17                //HART的读4个工作参数命令!

#define HART_COM_WR_RESET                        42                        //HART的复位命令! 数据第一个字节必须是0XA5

#define H_START_MAST_SHORT        (0x02)         //主机的消息
#define H_START_MAST_LONG                (0x82)

#define H_START_SLAVE_SHORT (0x06)         //从机的消息
#define H_START_SLAVE_LONG        (0x86)

#define HART_GET_UART_DATA(a)                        Get_Receive_DATA_COM1(a)                //定义串口!
//#define HART_REC_UART_DATA(a,b)                UART_SendStart(COM0,a,b);
//----------------------------------------------------------------------------------

extern void HART_GET_RD_0_TO_MAST(unsigned char adr,unsigned char com);
extern void HART_GET_WORK_B_TO_MAST(unsigned char adr,unsigned char com);
extern void HART_GET_WORK_Ao_TO_MAST(unsigned char adr,unsigned char com);
extern void HART_GET_RD_13_TO_MAST(unsigned char adr,unsigned char com);
extern void HART_GET_RD_12_TO_MAST(unsigned char adr,unsigned char com);
extern void HART_GET_RD_60_TO_MAST(unsigned char adr,unsigned char com,unsigned char id);
extern void        HART_GET_WR_64_TO_MAST(unsigned char adr,unsigned char com,unsigned char *p);
extern void HART_RESET_TO_MAST(unsigned char adr,unsigned char com);
extern unsigned char Hart_Command_Do(unsigned char  *p );
extern unsigned char GET_hart_DO(unsigned char *Buf,unsigned char CNT);
extern unsigned char *JB_FF(unsigned char *p,unsigned char *cnt);
extern unsigned char Get_XOR(unsigned char *p,unsigned char Long);
extern unsigned char HART_Format_HEAD(unsigned char *buf,unsigned char adr,unsigned char com,unsigned char Long,unsigned int ask);
extern void HART_Send_OUT(unsigned char *buf,unsigned char cnt);
extern void Get_ASCII_6bit(char *buf);
extern unsigned char Decode_ASCII_6bit(char *buf,char *Tag);
extern unsigned char JB_TAG_Name(char *buf);



#endif

出0入20汤圆

 楼主| 发表于 2017-7-13 10:19:34 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2017-7-13 10:35:03 | 显示全部楼层
国内用hart协议的好像不太多,楼主在普及hart协议,赞一个。

出0入20汤圆

 楼主| 发表于 2017-7-13 10:44:06 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2017-7-13 13:33:40 | 显示全部楼层
楼主用的硬件接口是那颗芯片,价格多少?

出0入0汤圆

发表于 2017-7-13 15:09:42 | 显示全部楼层
楼主搞仪表的啊?

出0入0汤圆

发表于 2017-7-13 15:38:06 | 显示全部楼层
pygh 发表于 2017-7-13 13:33
楼主用的硬件接口是那颗芯片,价格多少?

同关注这个问题。。。。。

出0入0汤圆

发表于 2017-7-13 22:47:29 来自手机 | 显示全部楼层
关注硬件

出0入24汤圆

发表于 2017-7-13 22:53:28 | 显示全部楼层
Mark!感谢分享!

出0入0汤圆

发表于 2017-7-13 23:27:18 来自手机 | 显示全部楼层
谢谢分享,能否看看硬件是怎么样的

出5入42汤圆

发表于 2017-7-13 23:47:41 来自手机 | 显示全部楼层
赞一个,老板说了几年了,一直没搞。主要是需求并不强?迟迟没有动手。

出0入0汤圆

发表于 2017-7-14 15:47:33 | 显示全部楼层
这种协议用的人很少,值得关注下

出0入0汤圆

发表于 2017-9-8 16:46:42 | 显示全部楼层
hart,标记下

出0入0汤圆

发表于 2017-9-13 20:35:07 来自手机 | 显示全部楼层
学习了,值得深入研究!

出0入0汤圆

发表于 2017-9-13 21:22:22 | 显示全部楼层

HART协议 一般是什么产品上要用到了!

出0入0汤圆

发表于 2017-12-26 23:10:55 | 显示全部楼层
搞HART的这么少,楼主能分享资料。赞一个。

出10入95汤圆

发表于 2018-1-9 22:39:52 来自手机 | 显示全部楼层
多谢楼住分享

出0入0汤圆

发表于 2019-5-14 09:57:47 | 显示全部楼层
仪表通信国外用的比较多,模拟量上面叠加数字通信,注册协会会员成本有点高 哈哈哈

出0入0汤圆

发表于 2019-8-9 11:32:23 | 显示全部楼层
过程控制仪表行业用的协议。硬件价格很感人。

出0入0汤圆

发表于 2019-8-9 15:39:20 | 显示全部楼层
先收藏下,可能用的上。

出100入0汤圆

发表于 2019-12-14 13:29:25 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2019-12-14 14:00:53 来自手机 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2019-12-14 14:26:26 | 显示全部楼层
很好了!难得。国内这方面的不多!

出0入0汤圆

发表于 2019-12-14 16:21:54 | 显示全部楼层
感谢分享,虽然现在不用,难保以后用,收藏再说

出0入0汤圆

发表于 2021-1-7 13:27:34 | 显示全部楼层
不错,就是国内这个协议用的太少了

出0入0汤圆

发表于 2021-1-8 11:17:31 | 显示全部楼层
好东西 好东西
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 07:44

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表