HART协议详解:HART与MCU通信代码解析举例

这篇具有很好参考价值的文章主要介绍了HART协议详解:HART与MCU通信代码解析举例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

HART协议详解:HART与MCU通信代码解析举例

HART协议

HART(Highway Addressable Remote Transducer),可寻址远程传感器高速通道的开放通信协议,Hart协议比较大的特点在于支持模拟信号和数字信号同时传递。

参考:

blog.csdn.net/weixin_33775572/article/details/91708920
blog.csdn.net/lixiaojie123123/article/details/73302900

文档:
HART协议文档汇总(包括笔记、命令等文档)

download.csdn.net/download/weixin_53403301/87537915

先介绍下HART协议的通信原理:
主要分为两个部分:

  1. 数模转换测量数据
  2. 基于频率数据传输

HART协议类似于早期坐机电话协议 早期的电话传输的是声音模拟量,包括了电压、频率,以此来反应不同的声音。而后加入了“来电显示”等数字量,就要采用HART协议类似的方式来传输,即在模拟量的基础上加上数字量。

对于HART协议 其模拟量输出的为4-20mA电流,对其进行数模转换即可得到对应的数据,比如100psi的压力传感器,20mA对应的就是100psi,4mA对应的就是0psi。
HART协议详解:HART与MCU通信代码解析举例

对于基于频率的数据传输 HART协议将不同的频率作为数据0和1 通常是使用1200Hz表示1,2200Hz表示0
HART协议详解:HART与MCU通信代码解析举例
依次排列下来即可得到数据

将电流量与频率量叠加,即模拟量与数字量同时传输,构成完整的HART协议
HART协议详解:HART与MCU通信代码解析举例
HART协议的数字量空闲时为1,即频率恒定1200Hz,而当表示8位数据时,则需要一个起始位0和一个停止位0 中间8位才是数据位

如AD5700芯片:
HART协议详解:HART与MCU通信代码解析举例
HART协议详解:HART与MCU通信代码解析举例
比如发一个0xAA 则HART总线上 表示的数据如下:
1111 0 1010 1010 0 1111
其中0 1010 1010 0部分为传输部分 1010 1010为数据部分0xAA
1111为空闲时的状态

HART协议的模拟量部分就很好理解了 就是数模转换而已 不用再过多介绍

在使用HART器件时 通常都是用MCU连接一个HART协议的调制解析器 然后再连接到HART器件

HART协议的调制解析器有很多种 比如可以采用AD5700+AD5421构成的HART组合 但都大同小异 都是采用UART的方式进行与MCU的通信(如果用AD5421组合则是SPI)

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

整体的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),其结构为
    HART协议详解:HART与MCU通信代码解析举例

    一般我们不用到突发模式,这里的80表示的就是(主机1—-设备地址(0))
    长指令时:地址码由5个字节表示,其结构为
    HART协议详解:HART与MCU通信代码解析举例

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

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

  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”。

将数据依次排列:
HART协议详解:HART与MCU通信代码解析举例

第一列为前导字符
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协议详解:HART与MCU通信代码解析举例
以下代码为串口信号解析:

#include<stdio.h>
#include<stdint.h>
#include <string.h>

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_Struct;

HART_Struct trans_HART_to_Struct(uint8_t * buf)
{
    HART_Struct HART_Stu;
    uint8_t i=0;
    uint8_t START_Num=0;
    uint8_t COM_Num=0;
    uint8_t CHK_Num=0;
    uint8_t Check_Sum=0;  
    if(buf[0]==0xFF)
    {                
        for(i=0;i<6;i++)
        {            
            if(buf[i]!=0xFF)
            {
                HART_Stu.START=buf[i];
                START_Num=i;                
                break;
            }
            START_Num=i;
        }

        if(START_Num<2)
        {
            return HART_Stu;
        }

        for(i=0;i<START_Num;i++)
        {
            HART_Stu.PREAMBLE[i]=buf[i];
        }
        
        if(HART_Stu.START<0x10)
        {
            COM_Num=START_Num+2;            
        }
        else
        {
            COM_Num=START_Num+6;            
        }
        for(i=0;i<COM_Num-START_Num-1;i++)
        {
            HART_Stu.ADDR[i]=buf[START_Num+1+i];
        }

        HART_Stu.COM=buf[COM_Num];
        HART_Stu.BCNT=buf[COM_Num+1];
        CHK_Num=COM_Num+HART_Stu.BCNT+2;
        HART_Stu.CHK=buf[CHK_Num];

        for(i=START_Num;i<CHK_Num;i++)
        {
            Check_Sum=Check_Sum^buf[i];
        }
        if(HART_Stu.CHK==Check_Sum)
        {
            if(HART_Stu.BCNT>0)
            {
                if(HART_Stu.BCNT>1 && (HART_Stu.START&0x0F)==0x06)
                {                  
                    for(i=0;i<2;i++)
                    {
                        HART_Stu.STATUS[i]=buf[COM_Num+2+i];
                    }
                    for(i=0;i<HART_Stu.BCNT-2;i++)
                    {
                        HART_Stu.DATA[i]=buf[COM_Num+4+i];
                    }
                }
                else
                {
                    for(i=0;i<HART_Stu.BCNT;i++)
                    {
                        HART_Stu.DATA[i]=buf[COM_Num+2+i];
                    }
                }
            }
            else
            {
                return HART_Stu;
            }
        }
        else
        {
            return HART_Stu;
        }
    }
    else
    {
        return HART_Stu;
    }
    return HART_Stu;
}

int8_t trans_HART_to_Buf(HART_Struct HART_Stu,uint8_t * buf)
{
    uint8_t i=0;
    uint8_t START_Num=0;
    uint8_t COM_Num=0;
    uint8_t CHK_Num=0;
    uint8_t Check_Sum=0;

    if(HART_Stu.PREAMBLE[0]==0xFF)
    {
        for(i=0;i<6;i++)
        {            
            if(HART_Stu.PREAMBLE[i]!=0xFF)
            {
                buf[i]=HART_Stu.START;
                START_Num=i;                
                break;
            }            
            START_Num=i;
        }

        if(START_Num<2)
        {
            return -1;
        }

        for(i=0;i<START_Num;i++)
        {
            buf[i]=HART_Stu.PREAMBLE[i];
        }        
        
        if(HART_Stu.START<0x10)
        {
            COM_Num=START_Num+2;
        }
        else
        {
            COM_Num=START_Num+6;
        }

        CHK_Num=COM_Num+HART_Stu.BCNT+2;
        buf[START_Num]=HART_Stu.START;

        for(i=0;i<COM_Num-START_Num-1;i++)
        {
            buf[START_Num+1+i]=HART_Stu.ADDR[i];
        }

        buf[COM_Num]=HART_Stu.COM;
        buf[COM_Num+1]=HART_Stu.BCNT;

        buf[CHK_Num]=HART_Stu.CHK;

        if(HART_Stu.BCNT>1 && (HART_Stu.START&0x0F)==0x06)
        {
            for(i=0;i<2;i++)
            {
                buf[COM_Num+2+i]=HART_Stu.STATUS[i];
            }
            for(i=0;i<HART_Stu.BCNT-2;i++)
            {
                buf[COM_Num+4+i]=HART_Stu.DATA[i];
            }
        }
        else
        {
            for(i=0;i<HART_Stu.BCNT;i++)
            {            
                buf[COM_Num+2+i]=HART_Stu.DATA[i];
            }
        }

        for(i=START_Num;i<CHK_Num;i++)
        {
            Check_Sum=Check_Sum^buf[i];
        }

        if(HART_Stu.CHK==Check_Sum)
        {
            return 1;
        }
        else
        {
            return -2;
        }
    }
    else
    {
        return -1;
    }

    return 0;
}

int main(void)
{
    unsigned char list[41]={0xFF,0xFF,0xFF,0xFF,0xFF,0x86,0xA6,0x06,0xBC,0x61,0x4E,0x01,0x07,0x00,0x00,0x06,0x40,0xB0,0x00,0x00,0x45};
    HART_Struct a;
    uint8_t buf[41];    
    memset(buf,0,sizeof(buf)/sizeof(buf[0]));
    a=trans_HART_to_Struct(list);
    printf("%02X\n",a.CHK);
    printf("%d\n",trans_HART_to_Buf(a,buf));
    printf("%02X\n",buf[8]);
    for(uint8_t i=0;i<41;i++)
    {
        if(buf[i]==list[i])
        {

        }
        else
        {
            printf("ERROR\n");
            break;
        }
    }
}

代码经检验后顺利通过不报错

附录:压缩字符串、大小端格式转换

压缩字符串

首先HART数据格式如下:
HART协议详解:HART与MCU通信代码解析举例
HART协议详解:HART与MCU通信代码解析举例
重点就是浮点数和字符串类型
Latin-1就不说了 基本用不到

浮点数

浮点数里面 如 0x40 80 00 00表示4.0f

在HART协议里面 浮点数是按大端格式发送的 就是高位先发送 低位后发送

发送出来的数组为:40,80,00,00

但在C语言对浮点数的存储中 是按小端格式来存储的 也就是40在高位 00在低位
浮点数:4.0f
地址0x1000对应00
地址0x1001对应00
地址0x1002对应80
地址0x1003对应40

若直接使用memcpy函数 则需要进行大小端转换 否则会存储为:
地址0x1000对应40
地址0x1001对应80
地址0x1002对应00
地址0x1003对应00

大小端转换:

void swap32(void * p)
{
   uint32_t *ptr=p;
   uint32_t x = *ptr;
   x = (x << 16) | (x >> 16);
   x = ((x & 0x00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF);

   *ptr=x;
}

压缩Packed-ASCII字符串

本质上是将原本的ASCII的最高2位去掉 然后拼接起来 比如空格(0x20)
四个空格拼接后就成了
1000 0010 0000 1000 0010 0000
十六进制:82 08 20
对了一下表 0x20之前的识别不了
也就是只能识别0x20-0x5F的ASCII表
HART协议详解:HART与MCU通信代码解析举例

压缩/解压函数后面再写:

//传入的字符串和数字必须提前声明 且字符串大小至少为str_len 数组大小至少为str_len%4*3 str_len必须为4的倍数
uint8_t Trans_ASCII_to_Pack(uint8_t * str,uint8_t * buf,const uint8_t str_len)
{
   if(str_len%4)
   {
      return 0;
   }
	 
   uint8_t i=0;
   memset(buf,0,str_len/4*3);	  
   for(i=0;i<str_len;i++)
   {
      if(str[i]==0x00)
      {
         str[i]=0x20;
      }
   }

   for(i=0;i<str_len/4;i++)
   {
      buf[3*i]=(str[4*i]<<2)|((str[4*i+1]>>4)&0x03);
      buf[3*i+1]=(str[4*i+1]<<4)|((str[4*i+2]>>2)&0x0F);
      buf[3*i+2]=(str[4*i+2]<<6)|(str[4*i+3]&0x3F);
   }

   return 1;
}

//传入的字符串和数字必须提前声明 且字符串大小至少为str_len 数组大小至少为str_len%4*3 str_len必须为4的倍数
uint8_t Trans_Pack_to_ASCII(uint8_t * str,uint8_t * buf,const uint8_t str_len)
{
   if(str_len%4)
   {
      return 0;
   }

   uint8_t i=0;

   memset(str,0,str_len);

   for(i=0;i<str_len/4;i++)
   {
      str[4*i]=(buf[3*i]>>2)&0x3F;
      str[4*i+1]=((buf[3*i]<<4)&0x30)|(buf[3*i+1]>>4);
      str[4*i+2]=((buf[3*i+1]<<2)&0x3C)|(buf[3*i+2]>>6);
      str[4*i+3]=buf[3*i+2]&0x3F;
   }

   return 1;
}


大小端转换

在串口等数据解析中 难免遇到大小端格式问题

什么是大端和小端

所谓的大端模式,就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

所谓的小端模式,就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

简单来说:大端——高尾端,小端——低尾端

举个例子,比如数字 0x12 34 56 78在内存中的表示形式为:

1)大端模式:

低地址 -----------------> 高地址

0x12 | 0x34 | 0x56 | 0x78

2)小端模式:

低地址 ------------------> 高地址

0x78 | 0x56 | 0x34 | 0x12

可见,大端模式和字符串的存储模式类似。

数据传输中的大小端

比如地址位、起止位一般都是大端格式
如:
起始位:0x520A
则发送的buf应为{0x52,0x0A}

而数据位一般是小端格式(单字节无大小端之分)
如:
一个16位的数据发送出来为{0x52,0x0A}
则对应的uint16_t类型数为: 0x0A52

而对于浮点数4.0f 转为32位应是:
40 80 00 00

以大端存储来说 发送出来的buf就是依次发送 40 80 00 00

以小端存储来说 则发送 00 00 80 40

由于memcpy等函数 是按字节地址进行复制 其复制的格式为小端格式 所以当数据为小端存储时 不用进行大小端转换
如:

uint32_t dat=0;
uint8_t buf[]={0x00,0x00,0x80,0x40};
   memcpy(&dat,buf,4);
   float f=0.0f;
   f=*((float*)&dat); //地址强转
   printf("%f",f);

或更优解:

   uint8_t buf[]={0x00,0x00,0x80,0x40};   
   float f=0.0f;
   memcpy(&f,buf,4);

而对于大端存储的数据(如HART协议数据 全为大端格式) 其复制的格式仍然为小端格式 所以当数据为小端存储时 要进行大小端转换
如:

uint32_t dat=0;
uint8_t buf[]={0x40,0x80,0x00,0x00};
   memcpy(&dat,buf,4);
   float f=0.0f;
   swap32(&dat); //大小端转换
   f=*((float*)&dat); //地址强转
   printf("%f",f);

或:

uint8_t buf[]={0x40,0x80,0x00,0x00};
   memcpy(&dat,buf,4);
   float f=0.0f;
   swap32(&f); //大小端转换
   printf("%f",f);

或更优解:

uint32_t dat=0;
uint8_t buf[]={0x40,0x80,0x00,0x00};
   float f=0.0f;
   dat=(buf[0]<<24)|(buf[0]<<16)|(buf[0]<<8)|(buf[0]<<0)
   f=*((float*)&dat);

总结

固 若数据为小端格式 则可以直接用memcpy函数进行转换 否则通过移位的方式再进行地址强转

对于多位数据 比如同时传两个浮点数 则可以定义结构体之后进行memcpy复制(数据为小端格式)

对于小端数据 直接用memcpy写入即可 若是浮点数 也不用再进行强转

对于大端数据 如果不嫌麻烦 或想使代码更加简洁(但执行效率会降低) 也可以先用memcpy写入结构体之后再调用大小端转换函数 但这里需要注意的是 结构体必须全为无符号整型 浮点型只能在大小端转换写入之后再次强转 若结构体内采用浮点型 则需要强转两次

所以对于大端数据 推荐通过移位的方式来进行赋值 然后再进行个别数的强转 再往通用结构体进行写入

多个不同变量大小的结构体 要主要字节对齐的问题
可以用#pragma pack(1) 使其对齐为1
但会影响效率

大小端转换函数

直接通过对地址的操作来实现 传入的变量为32位的变量
中间变量ptr是传入变量的地址文章来源地址https://www.toymoban.com/news/detail-473758.html

void swap16(void * p)
{
   uint16_t *ptr=p;
   uint16_t x = *ptr;
   x = (x << 8) | (x >> 8);

   *ptr=x;
}

void swap32(void * p)
{
   uint32_t *ptr=p;
   uint32_t x = *ptr;
   x = (x << 16) | (x >> 16);
   x = ((x & 0x00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF);

   *ptr=x;
}

void swap64(void * p)
{
   uint64_t *ptr=p;
   uint64_t x = *ptr;
   x = (x << 32) | (x >> 32);
   x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x >> 16) & 0x0000FFFF0000FFFF);
   x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x >> 8) & 0x00FF00FF00FF00FF);

   *ptr=x;
}

到了这里,关于HART协议详解:HART与MCU通信代码解析举例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单片机——通信协议(UART协议解析篇)

            在嵌入式系统设计中,UART通信是一种广泛使用的串行通信协议,它通过 两条信号线实现全双工 的数据传输和接收。UART通信协议以其简单、灵活和易于集成的特点,在嵌入式设备之间以及与外部设备进行通信时发挥着重要作用。本文将详细介绍 UART 通信的 工作原

    2024年02月04日
    浏览(37)
  • STM32F103单片机通过SPI全双工通信协议与W25Q64(FLASH)进行通信【串行同步通信(数据线与时钟线配合),(一主多从模式)】附相关驱动代码详解

    1.W25Qxx系列是一种低成本、小型化、使用简单的 非易失性存储器 ,常应用于数据存储、字库存储、固件程序存储等场景 2.存储介质: Nor Flash(闪存) 3.时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI) 4.存储容量(24位地址): W25Q40: 4Mbit / 512KByte W25Q80: 8Mbit / 1MByte W25Q16: 16

    2024年04月13日
    浏览(49)
  • 详解通信协议之IIC通信协议

    本文结合AT24C02对IIC通信协议原理进行了描述。 IIC通讯协议(Inter-Integrated Circuit)是由 Philips 公司开发双向同步半双工串行总线,只需要两根线(SDA、SCL)即可在连接于总线上的器件之间传送信息。IIC总线是一种共享的串行总线,是用于两个设备之间的短距离低速速率(250K左右)通

    2024年02月08日
    浏览(27)
  • Modbus通信协议+Modbus串口调试工具+Java版协议解析源码

    网络与串口二合一调试助手TCPCOM: https://download.csdn.net/download/liuyuan_java/87454762 Modbus调试工具,模拟串口调试工具 https://download.csdn.net/download/liuyuan_java/87427475 Configure Virtual Serial Port Driver (VSPD) 串口模拟工具 https://download.csdn.net/download/liuyuan_java/87426831 Java实现DL/T645-2007协议报文的

    2024年02月03日
    浏览(35)
  • 链接文件学习(七):英飞凌MCU Tasking编译器LSL链接文件解析 及代码变量定位方法

    目录   1、Tasking的链接文件 1.1、DSRAM中的数据存放 1.2、PFlash中的代码存放 1.3、LMU 1.4、PSRAM 1.5、UCB 2、代码与变量定位

    2024年02月07日
    浏览(43)
  • SECS/GEN HSMS半导体通信协议解析

    目录 一、协议族总体结构 二、HSMS消息格式(网口连接) 1、超时时间设置 2、在线,离线,连接,未连接 3、Message Header结构 三、SECS-II报文格式 相关手册及通信助手资源获取地址:SECS手册及模拟器 提取码:ahnj 下面是一些SECS/Gen的重要知识归纳(建议查询资料学习SECS后收藏

    2024年02月06日
    浏览(39)
  • 【FPGA开发】HDMI通信协议解析及FPGA实现

      笔者在这里使用的开发板是正点原子的达芬奇开发板,FPGA型号为XC7A35TFGG484-2。参考的课程是正点原子的课程手把手教你学达芬奇达芬奇Pro之FPGA开发篇。   HDMI,全称为High Definition Multimedia Interface,即高清多媒体接口。它不仅可以传输视频信号,还可以传输音频信号。上

    2024年02月21日
    浏览(31)
  • WebSocket ACK 协议解析:最大限度提高通信可靠性

    WebSocket ,作为一种在单一TCP连接上实现全双工通讯的协议,允许客户端与服务器之间自由地进行双向数据流动。一旦建立连接,数据可以无限制地在两者之间传输。但是,由于网络环境不总是完美无缺,讯息有时可能会在传递过程中丢失。这可能是因为网络拥堵、硬件故障或

    2024年01月19日
    浏览(38)
  • 深入解析OSI七层协议:实现网络通信的基石

    在计算机网络中,OSI(开放系统互联)七层协议是一种常用的网络通信模型,它将网络通信过程划分为七个不同的层级。每一层都有特定的功能和协议,共同构成了网络通信的基石。本文将详细介绍每一层的协议以及其原理,并探讨其在实际应用中的场景。 物理层是OSI模型的

    2024年02月05日
    浏览(40)
  • Mqtt通信协议详解

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级” 通讯协议 ,该协议构建于TCP/IP协议上。 mqtt实现:需要客户端和服务端,不同的客户端通过服务端来获取消息,服务端相当于是个中转站,与各个客户端相连

    2024年02月15日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包