简单的串行通信。 & 使用 C 计算 CRC16
Simple serial comm. & Calculating CRC16 using C
我有一个传感器,我希望从中获取一些数据。我想问它日期或要数据。
传感器采用RS-232; 9600 8N1 进行通信。
通信包由header、payload和CRC[=54=组成].该手册提供了 header 和 payload 以供您执行任何操作。每个通信包的组成如下:
<SOH> header <STX> payload <ETB> CRC16 <ETX>
<SOH>
: 0x01
<STX>
: 0x02
<ETB>
: 0x17
<ETX>
: 0X03
如果你想查询日期,手册给出了一个例子,它告诉你 header 是 0x31,有效载荷是 0x41。
因此发送传感器的命令为:\x01\x31\x02\x41\x17\CRC16\x03
现在举个例子,手册也给你计算了CRC16,在ASCII中是A0D5。 CRC16需要传输little endian。
现在完整的命令是:
\x01\x31\x02\x41\x17\x44\x35\x41\x30\x03
该手册没有提供任何其他 CRC16 计算,它希望用户这样做很好:)
来自手册:每个数据包都由以十六进制 ASCII 编码(四个字符)传输的 16 位 CRC 验证。 CRC 是根据header+有效负载连接计算得到的
WORD CRC16_Compute( BYTE *pBuffer, WORD length )
{
BYTE i;
BOOL bs;
WORD crc=0;
while( length-- )
{
crc ^= *pBuffer++;
for( i = 0; i < 8; i++ )
{
bs = crc & 1;
crc >>= 1;
if( bs )
{
crc ^= 0xA001;
}
}
}
return crc;
}
那是 C 中的 CRC 计算器,我不太懂,但是他们只提供了这段代码片段,没有上下文。
在 ASCII 中,他们使用 1+A (0x31+0x41) 得到 2 个字节,A0D5。有人可以向我解释一下 CRC 代码的作用吗,谢谢!
#include <stdio.h>
typedef unsigned char BYTE;
typedef unsigned int BOOL;
typedef unsigned int WORD;
WORD CRC16_Compute( BYTE *pBuffer, WORD length )
{
BYTE i;
BOOL bs;
WORD crc=0;
while( length-- )
{
crc ^= *pBuffer++;
for( i = 0; i < 8; i++ )
{
bs = crc & 1;
crc >>= 1;
if( bs )
{
crc ^= 0xA001;
}
}
}
return crc;
}
int main ( void )
{
unsigned char data[2];
unsigned char sdata[9];
unsigned int x;
unsigned int z;
unsigned int i;
data[0]=0x31;
data[1]=0x41;
x = CRC16_Compute(data,2);
x&=0xFFFF;
printf("0x%X\n",x);
z=0;
sdata[z++]=0x01;
sdata[z++]=data[0];
sdata[z++]=0x02;
sdata[z++]=data[1];
sdata[z++]=0x17;
sdata[z ]=((x>> 4)&0xF)+0x30; if(sdata[4]>0x39) sdata[4]+=7; z++;
sdata[z ]=((x>> 0)&0xF)+0x30; if(sdata[5]>0x39) sdata[5]+=7; z++;
sdata[z ]=((x>>12)&0xF)+0x30; if(sdata[6]>0x39) sdata[6]+=7; z++;
sdata[z ]=((x>> 8)&0xF)+0x30; if(sdata[7]>0x39) sdata[7]+=7; z++;
sdata[z++]=0x03;
for(i=0;i<z;i++) printf("%02X ",sdata[i]); printf("\n");
return(0);
}
运行它
gcc so.c -o so
./so
0xA0D5
01 31 02 41 17 44 35 41 30 03
那个正确答案怎么样....
你需要知道的一切都在你的问题中,只要按照它说的去做。几分钟粗略地把它放在一起。
CRC is calculated from the header+payload concatenated
data[0]=0x31;
data[1]=0x41;
这是header和payload,它根据提供的CRC码给出正确的答案。
然后你用其他物品构建数据包。如果你 google ASCII table 你可以看到 'D' 'A' '0' '5' 的值并且可以弄清楚如何从 0xD 到 0x44 和 0xA 到 0x41但首先看0x0到0x30和0x5到0x35,0-9很容易但是0x0A给出0x3A但需要是0x41,所以你调整。
所以代码根据描述的评论按照描述的方式工作,我不知道这个传感器,他们这样做的方式看起来很愚蠢,但对他们提供示例和 crc16 的详细信息有好处多个标准变化,包括初始值,因此再次对他们有好处,因为他们可以节省大量时间来弄清楚...
我有一个传感器,我希望从中获取一些数据。我想问它日期或要数据。
传感器采用RS-232; 9600 8N1 进行通信。
通信包由header、payload和CRC[=54=组成].该手册提供了 header 和 payload 以供您执行任何操作。每个通信包的组成如下:
<SOH> header <STX> payload <ETB> CRC16 <ETX>
<SOH>
: 0x01<STX>
: 0x02<ETB>
: 0x17<ETX>
: 0X03
如果你想查询日期,手册给出了一个例子,它告诉你 header 是 0x31,有效载荷是 0x41。
因此发送传感器的命令为:\x01\x31\x02\x41\x17\CRC16\x03
现在举个例子,手册也给你计算了CRC16,在ASCII中是A0D5。 CRC16需要传输little endian。
现在完整的命令是:
\x01\x31\x02\x41\x17\x44\x35\x41\x30\x03
该手册没有提供任何其他 CRC16 计算,它希望用户这样做很好:)
来自手册:每个数据包都由以十六进制 ASCII 编码(四个字符)传输的 16 位 CRC 验证。 CRC 是根据header+有效负载连接计算得到的
WORD CRC16_Compute( BYTE *pBuffer, WORD length )
{
BYTE i;
BOOL bs;
WORD crc=0;
while( length-- )
{
crc ^= *pBuffer++;
for( i = 0; i < 8; i++ )
{
bs = crc & 1;
crc >>= 1;
if( bs )
{
crc ^= 0xA001;
}
}
}
return crc;
}
那是 C 中的 CRC 计算器,我不太懂,但是他们只提供了这段代码片段,没有上下文。
在 ASCII 中,他们使用 1+A (0x31+0x41) 得到 2 个字节,A0D5。有人可以向我解释一下 CRC 代码的作用吗,谢谢!
#include <stdio.h>
typedef unsigned char BYTE;
typedef unsigned int BOOL;
typedef unsigned int WORD;
WORD CRC16_Compute( BYTE *pBuffer, WORD length )
{
BYTE i;
BOOL bs;
WORD crc=0;
while( length-- )
{
crc ^= *pBuffer++;
for( i = 0; i < 8; i++ )
{
bs = crc & 1;
crc >>= 1;
if( bs )
{
crc ^= 0xA001;
}
}
}
return crc;
}
int main ( void )
{
unsigned char data[2];
unsigned char sdata[9];
unsigned int x;
unsigned int z;
unsigned int i;
data[0]=0x31;
data[1]=0x41;
x = CRC16_Compute(data,2);
x&=0xFFFF;
printf("0x%X\n",x);
z=0;
sdata[z++]=0x01;
sdata[z++]=data[0];
sdata[z++]=0x02;
sdata[z++]=data[1];
sdata[z++]=0x17;
sdata[z ]=((x>> 4)&0xF)+0x30; if(sdata[4]>0x39) sdata[4]+=7; z++;
sdata[z ]=((x>> 0)&0xF)+0x30; if(sdata[5]>0x39) sdata[5]+=7; z++;
sdata[z ]=((x>>12)&0xF)+0x30; if(sdata[6]>0x39) sdata[6]+=7; z++;
sdata[z ]=((x>> 8)&0xF)+0x30; if(sdata[7]>0x39) sdata[7]+=7; z++;
sdata[z++]=0x03;
for(i=0;i<z;i++) printf("%02X ",sdata[i]); printf("\n");
return(0);
}
运行它
gcc so.c -o so
./so
0xA0D5
01 31 02 41 17 44 35 41 30 03
那个正确答案怎么样....
你需要知道的一切都在你的问题中,只要按照它说的去做。几分钟粗略地把它放在一起。
CRC is calculated from the header+payload concatenated
data[0]=0x31;
data[1]=0x41;
这是header和payload,它根据提供的CRC码给出正确的答案。
然后你用其他物品构建数据包。如果你 google ASCII table 你可以看到 'D' 'A' '0' '5' 的值并且可以弄清楚如何从 0xD 到 0x44 和 0xA 到 0x41但首先看0x0到0x30和0x5到0x35,0-9很容易但是0x0A给出0x3A但需要是0x41,所以你调整。
所以代码根据描述的评论按照描述的方式工作,我不知道这个传感器,他们这样做的方式看起来很愚蠢,但对他们提供示例和 crc16 的详细信息有好处多个标准变化,包括初始值,因此再次对他们有好处,因为他们可以节省大量时间来弄清楚...