请教坛里很多MODBUS计算CRC16的方法两个uint8_t return能得到uint16_t吗?
本帖最后由 mangolu 于 2021-1-18 01:13 编辑请教坛里很多MODBUS计算CRC16的方法两个uint8_t return (CRCcode_L << 8 | CRCcode_H)能得到uint16_t?
代码如下:
/**************************************************************************************************
NAME : comp_crc16
INPUT : unsigned char *pack 数据缓冲首地址, unsigned char num 数据字节数
OUTPUT : unsigned int 计算结果,低位在前 高位在后(MODBUS 规定)。
FUNCTION :
CRC16 计算 MODBUS使用公式:X16+X15+X2+1 。此不同于CITT公式
**************************************************************************************************/
unsigned int comp_crc16(unsigned char *pack, unsigned char num)
{
unsigned char CRCcode_H = 0XFF; // 高CRC字节初始化
unsigned char CRCcode_L = 0XFF; // 低CRC 字节初始化
unsigned char index; // 数据索引
while (num--)
{
index = CRCcode_L ^ (*pack++);
CRCcode_L = CRCcode_H ^ CRC_H;
CRCcode_H = CRC_L;
}
return (CRCcode_L << 8 | CRCcode_H); // MODBUS 规定低位在前
}
按照我的理解,CRCcode_L为uint8_t,左移8位后应应该为0x00吧?两个uint8_t相或后,能返回uint16_t值?我看了坛里很多代码都是这样的。
而freemodbus里的代码为:
USHORT
usMBCRC16( UCHAR * pucFrame, USHORT usLen )
{
UCHAR ucCRCHi = 0xFF;
UCHAR ucCRCLo = 0xFF;
int iIndex;
while( usLen-- )
{
iIndex = ucCRCLo ^ *( pucFrame++ );
ucCRCLo = ( UCHAR )( ucCRCHi ^ aucCRCHi );
ucCRCHi = aucCRCLo;
}
return ( USHORT )( ucCRCHi << 8 | ucCRCLo );
}
明显这里的代码采用了强制类型转换,这样的结果才是正确的。
我就很疑惑,坛里很多人的代码真能正常计算吗? 符合C语言标准的当然是必须可以,不符合标准的编译器要特立独行就不一定了。 return (( USHORT )ucCRCHi << 8 | ucCRCLo ); 才是正确的写法。前面都需要依赖C语言的自动整型提升 看你的函数声明的返回类型,这里有个隐含的类型转换,最后一步运算两个byte都升到unsigned int类型计算了. 楼主C语言基础不牢啊。建议时常复习一下K&R的那本C语言圣经,基础不牢,地动山摇嘛 直接用freemodbus里面的一个专门计算crc的c文件就可以了,直接调用函数 本帖最后由 kation122 于 2021-1-18 10:56 编辑
班门弄斧,抛砖引玉,分享使用联合体来做 2byte to uint16,4byte to uint32 的方法,
不浪费MCU 移位运算,不逻辑运算,简洁明了,稳定使用多年,抛砖引玉,请各位大侠点评。
# define LSB 1
# define MSB 0
typedef unsigned char U8;
typedef unsigned int U16;
typedef union UU16
{
U16 U16;
U8 U8;
} UU16;
//-----------------------------//
UU16 CRC;
CRC.U8=0XAB;
CRC.U8=0X34;
return CRC.U16;
这里CRC.U16 的值就是0XAB34,数据类型是unsigned int ,
//-----------------------------//
CRC.U16=0XBD56;
CRC.U8值就是0XBD
CRC.U8值就是0X56
编译器大小端不同,只需要调整# define LSB ,# define MSB两个参数。 Error.Dan 发表于 2021-1-18 08:48
看你的函数声明的返回类型,这里有个隐含的类型转换,最后一步运算两个byte都升到unsigned int类型计算了. ...
哦,原来这里还有个隐形转换,这个一直没有注意过。 kation122 发表于 2021-1-18 10:50
班门弄斧,抛砖引玉,分享使用联合体来做 2byte to uint16,4byte to uint32 的方法,
不浪费MCU 移位运算 ...
这个方法不错,谢谢
页:
[1]