C++ 将CRC(校验和)附加到数据流串行端口通信C++;

C++ 将CRC(校验和)附加到数据流串行端口通信C++;,c++,checksum,crc,C++,Checksum,Crc,我将CRC附加到数据流中。我正在使用一个用于Linux和Windows的RS-232串行端口库 我希望获得与comport工具图片上显示的值相同的值: 我使用的是constchar[4086]=“123456789”作为缓冲区 返回的CRC是bb3d,然后我将其从无符号短字符转换为字符* #define SERIALPORT_BUFSIZE 4088 char *im_buf = (char *)malloc(SERIALPORT_BUFSIZE + 8); char *tx

我将CRC附加到数据流中。我正在使用一个用于Linux和Windows的RS-232串行端口库

我希望获得与comport工具图片上显示的值相同的值:

我使用的是
constchar[4086]=“123456789”作为缓冲区

返回的CRC是bb3d,然后我将其从
无符号短字符
转换为
字符*

#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);

}
首先,请注意:

  • 您的输入是ASCII十六进制。每个字符都是半字节,但输入字符串的字符数为奇数:丢弃最后一个字符
  • 您期望的是
    123456787b34
    0x347B
    0x120x34 0x560x78
    的CRC。额外的
    FD
    s看起来像是缓冲区的某个不相关端(或另一个bug?)
您的程序存在的问题:

您需要一个数据缓冲区来发送
RS232\u SendBuf
。您将ASCII码转换为数据,并将其放入
tx_buf
中,然后获取其CRC。这很好,但是您可以使用
strcat
将CRC附加到缓冲区;你不能那样做,
strcat
是用于文本的
strcat
需要两个以null结尾的字符串,但您有两个数据缓冲区

您的CRC函数也有一个问题:您有一个多余的掩码
&0x7F
,用于删除每个CRC字节的最后一位。
0xFF
掩码就足够了(实际上甚至不需要)

您还可以使用
新字符[2]
分配一个缓冲区,但决不能
删除它。那会管用,但很难看

请注意,您的CRC只有两个字节;只需将
Crc
直接作为
无符号短码返回即可

之后,只需使用
memcpy


在您的情况下,这将是
memcpy(tx_buf+n和my_crc_short,2)

感谢您的及时回复,我已经包括了我的crc功能,如果您能给我举个例子,我将不胜感激。我已经花了两个星期的时间在这上面了。thanks@MelFzllc编辑了我的答案。谢谢@elderbug你的例子很有见地。我对我的问题进行了编辑,以反映我从你的建议中所理解的内容。但是,我仍然没有得到值
7B34
我得到的是
3D BB
带有
char*im\u buf
的值和带有
char*tx\u buf
的各种值。有什么建议吗谢谢你这么做helpful@MelFzllc这是因为当您需要数据的CRC时,实际上计算ASCII文本“123456789”的CRC(
0x12 0x34 0x56 0x78
)。您需要为
tx\u buf
设置大小为
n
的CRC。通过为
tx\u buf
设置大小为
n
的CRC,您的意思是“无符号短CRC=GetCrc16(tx\u buf,strlen(tx\u buf))”<代码>RS232_SendBuf(组合编号,(无符号字符*)tx_buf,n+2)对吗?谢谢你的耐心和及时的回复,我仍然收到各种各样的通知,
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;
}