串口通讯数据流追加CRC(校验和)C++
Appending CRC (Checksum) to data stream serial port communication C++
我正在将 CRC 附加到数据流。我正在为 Linux 和 Windows.
使用 RS-232 的串口库
我想得到和comport工具图片上显示的一样的值:
我正在使用 const char[4086]="123456789";
作为缓冲区。
返回的 CRC 是 bb3d,然后我将其从 unsigned short
转换为 char *
。
#define SERIALPORT_BUFSIZE 4088
char *im_buf = (char *)malloc(SERIALPORT_BUFSIZE + 8);
char *tx_buf = (char *)malloc(SERIALPORT_RCV_BUFSIZE + 8);
const char buf[SERIALPORT_BUFSIZE]="123456789";
strcpy(im_buf, buf);
WriteToSerialPort(); // call to function
void SerialPortCom::WriteToSerialPort(void)
{
if(!port_open) return;
int i,n, tmp, tmp2;
if(newline == 1)
{
strcat(im_buf, "0a");
}
else if(newline == 2)
{
strcat(im_buf, "0d");
}
else if(newline == 3)
{
strcat(im_buf, "0d0a");
}
n = strlen(im_buf) / 2;
if(n < 1) return;
for(i=0; i< n; i++)
{
tmp = im_buf[i*2];
if((tmp >= '0') && (tmp <= '9'))
{
tmp -= '0';
}
else if((tmp >= 'a') && (tmp <= 'f'))
{
tmp -= ('a' - 10);
}
else if((tmp >= 'A') && (tmp <= 'F'))
{
tmp -= ('A' - 10);
}
tmp *= 16;
tmp2 = im_buf[(i*2)+1];
if((tmp2 >= '0') && (tmp2 <= '9'))
{
tmp2 -= '0';
}
else if((tmp2 >= 'a') && (tmp2 <= 'f'))
{
tmp2 -= ('a' - 10);
}
else if((tmp2 >= 'A') && (tmp2 <= 'F'))
{
tmp2 -= ('A' - 10);
}
tmp += tmp2;
tx_buf[i] = tmp;
}
//generate crc
unsigned short crc = GetCrc16(im_buf, strlen(im_buf));
//append crc
memcpy( tx_buf + n, &crc, 2 );
//send to serial port
RS232_SendBuf(comport_nr, (unsigned char *)tx_buf, n+2);
}
我得到的:(12 34 56 78 70 11 4A 3D
)
我想要的:(12 34 56 78 7B 34 FD FD FD FD
)
如何达到预期效果?
unsigned short SerialPortCom::GetCrc16(const char* InStr,unsigned int len)
{
//Crc16
unsigned short Crc16Table[256];
unsigned int i,j;
unsigned short Crc;
unsigned char CRCHigh = 0xFF, CRCLow = 0xFF;
for (i = 0; i < 256; i++)
{
Crc = i;
for (j = 0; j < 8; j++)
{
if(Crc & 0x1)
Crc = (Crc >> 1) ^ 0xA001;
else
Crc >>= 1;
}
Crc16Table[i] = Crc;
}
//CRC16
Crc=0x0000;
for(i=0; i<len; i++)
{
Crc = (Crc >> 8) ^ Crc16Table[(Crc & 0xFF) ^(uint8_t) InStr[i]];
}
//Crc ^= 0x0000;
return Crc;
}
首先,一些注意事项:
- 您的输入是 ASCII 十六进制。每个字符都是一个半字节,但是您输入的字符串的字符数是奇数:您丢弃了最后一个字符。
- 您期望的是
12 34 56 78 7B 34
:0x347B
是 0x12 0x34 0x56 0x78
的 CRC。额外的 FD
s 看起来像是一些不相关的缓冲区末端(或另一个错误?)。
你程序的问题:
您需要一个数据缓冲区才能使用 RS232_SendBuf
发送。您将 ASCII 码转换为数据并将其放入 tx_buf
,然后获取其 CRC。很好,但是您使用 strcat
将 CRC 附加到缓冲区;你不能那样做,strcat
用于文本。 strcat
需要两个以空字符结尾的字符串,但您有两个数据缓冲区。
您的 CRC 函数也有问题:您有一个多余的掩码 & 0x7F
,它删除了每个 CRC 字节的最后一位。 0xFF
掩码就足够了(实际上什至不需要)。
您还使用 new char[2]
分配了一个缓冲区,但从未 delete
它。这会起作用,但它很难看。
请注意,您的 CRC 只有两个字节;只是 return Crc
直接作为 unsigned short
.
之后,只需使用 memcpy
.
将您的 CRC 附加到您的缓冲区
在你的情况下,那将是 memcpy( tx_buf + n, &my_crc_short, 2 );
我正在将 CRC 附加到数据流。我正在为 Linux 和 Windows.
使用 RS-232 的串口库我想得到和comport工具图片上显示的一样的值:
我正在使用 const char[4086]="123456789";
作为缓冲区。
返回的 CRC 是 bb3d,然后我将其从 unsigned short
转换为 char *
。
#define SERIALPORT_BUFSIZE 4088
char *im_buf = (char *)malloc(SERIALPORT_BUFSIZE + 8);
char *tx_buf = (char *)malloc(SERIALPORT_RCV_BUFSIZE + 8);
const char buf[SERIALPORT_BUFSIZE]="123456789";
strcpy(im_buf, buf);
WriteToSerialPort(); // call to function
void SerialPortCom::WriteToSerialPort(void)
{
if(!port_open) return;
int i,n, tmp, tmp2;
if(newline == 1)
{
strcat(im_buf, "0a");
}
else if(newline == 2)
{
strcat(im_buf, "0d");
}
else if(newline == 3)
{
strcat(im_buf, "0d0a");
}
n = strlen(im_buf) / 2;
if(n < 1) return;
for(i=0; i< n; i++)
{
tmp = im_buf[i*2];
if((tmp >= '0') && (tmp <= '9'))
{
tmp -= '0';
}
else if((tmp >= 'a') && (tmp <= 'f'))
{
tmp -= ('a' - 10);
}
else if((tmp >= 'A') && (tmp <= 'F'))
{
tmp -= ('A' - 10);
}
tmp *= 16;
tmp2 = im_buf[(i*2)+1];
if((tmp2 >= '0') && (tmp2 <= '9'))
{
tmp2 -= '0';
}
else if((tmp2 >= 'a') && (tmp2 <= 'f'))
{
tmp2 -= ('a' - 10);
}
else if((tmp2 >= 'A') && (tmp2 <= 'F'))
{
tmp2 -= ('A' - 10);
}
tmp += tmp2;
tx_buf[i] = tmp;
}
//generate crc
unsigned short crc = GetCrc16(im_buf, strlen(im_buf));
//append crc
memcpy( tx_buf + n, &crc, 2 );
//send to serial port
RS232_SendBuf(comport_nr, (unsigned char *)tx_buf, n+2);
}
我得到的:(12 34 56 78 70 11 4A 3D
)
我想要的:(12 34 56 78 7B 34 FD FD FD FD
)
如何达到预期效果?
unsigned short SerialPortCom::GetCrc16(const char* InStr,unsigned int len)
{
//Crc16
unsigned short Crc16Table[256];
unsigned int i,j;
unsigned short Crc;
unsigned char CRCHigh = 0xFF, CRCLow = 0xFF;
for (i = 0; i < 256; i++)
{
Crc = i;
for (j = 0; j < 8; j++)
{
if(Crc & 0x1)
Crc = (Crc >> 1) ^ 0xA001;
else
Crc >>= 1;
}
Crc16Table[i] = Crc;
}
//CRC16
Crc=0x0000;
for(i=0; i<len; i++)
{
Crc = (Crc >> 8) ^ Crc16Table[(Crc & 0xFF) ^(uint8_t) InStr[i]];
}
//Crc ^= 0x0000;
return Crc;
}
首先,一些注意事项:
- 您的输入是 ASCII 十六进制。每个字符都是一个半字节,但是您输入的字符串的字符数是奇数:您丢弃了最后一个字符。
- 您期望的是
12 34 56 78 7B 34
:0x347B
是0x12 0x34 0x56 0x78
的 CRC。额外的FD
s 看起来像是一些不相关的缓冲区末端(或另一个错误?)。
你程序的问题:
您需要一个数据缓冲区才能使用 RS232_SendBuf
发送。您将 ASCII 码转换为数据并将其放入 tx_buf
,然后获取其 CRC。很好,但是您使用 strcat
将 CRC 附加到缓冲区;你不能那样做,strcat
用于文本。 strcat
需要两个以空字符结尾的字符串,但您有两个数据缓冲区。
您的 CRC 函数也有问题:您有一个多余的掩码 & 0x7F
,它删除了每个 CRC 字节的最后一位。 0xFF
掩码就足够了(实际上什至不需要)。
您还使用 new char[2]
分配了一个缓冲区,但从未 delete
它。这会起作用,但它很难看。
请注意,您的 CRC 只有两个字节;只是 return Crc
直接作为 unsigned short
.
之后,只需使用 memcpy
.
将您的 CRC 附加到您的缓冲区
在你的情况下,那将是 memcpy( tx_buf + n, &my_crc_short, 2 );