從沒想過串口通信CRC校驗不通過是因為大小端引起的,真是好痛的領(lǐng)悟。。。假設(shè)你是玩單片機的,又和安卓屏或者其它類型的屏幕通信,那要注意了。對方的通信協(xié)議數(shù)據(jù)可能是這樣定義的:
data.D1_SN = Mcont.chipId;
data.D2_warning = Mcont.warning;
data.D3_fliter_time = Mcont.save_data.filter_time;
data.D4_ecell_time = Mcont.save_data.vtimer_all;
data.D5_mcu1_ver = MCU1_SVER;
data.D6_muc2_ver = Mcont.slave.D16_ver;
data.D7_main_state = Mcont.status;
data.D8_work_state = Mcont.point;
data.Dx:內(nèi)存有可能是一個字節(jié),也有可能是兩個以上的字節(jié),假設(shè)是兩個字節(jié),數(shù)據(jù)只發(fā)送一個uint16_t類型的數(shù)據(jù),數(shù)值為0x1234,那么這個數(shù)據(jù)通過串口實際的輸出是什么?
串口發(fā)送: 第一個字節(jié) 第二個字節(jié)
0x12 0x34(大端)
0x34 0x12(小端)
實際痛苦的經(jīng)歷是這樣的,接收數(shù)據(jù)和發(fā)送方確認是對的,但是CRC校驗無論如何都通不過,經(jīng)過一番仔細操作后發(fā)現(xiàn),CRC校驗高低字節(jié)順序是不對的,于是呼呼呼。。。問發(fā)送端要了他的CRC校驗代碼(實錘了):
//***CRC校驗 CRC16-MODBUS類型 eof為幀尾0表示沒有 web尾0x23 endian 大小端模式 0大端 1小端**********************************************
void addCrc16_MODBUS(uint8_t *data1, uint16_t len,uint8_t eof,uint8_t endian)
{
uint16_t i, pos, crc = 0xFFFF;
for (pos = 0; pos < len; pos++)
{
if ((signed char)data1[pos] < 0)
{
crc ^= (int)((signed char)data1[pos]) + 256;
}
else
crc ^= (int)((signed char)data1[pos]);
for (i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
if(endian)
{
data1[len] = crc;
data1[len + 1] = crc >> 8;
}
else{
data1[len] = crc >> 8;
data1[len + 1] = crc;
}
if(eof)
data1[len + 2] = eof; //幀尾
}
第一次見CRC還有帶大小端轉(zhuǎn)換的功能,長見識了:
我們接觸大部分單片機都是小端模式,但是也有大端模式例如經(jīng)典的51單片機。
如何寫一段代碼判斷設(shè)備是大端還是小端模式:
#include <stdio.h>
int main(){
union{
int n;
char ch;
} data;
data.n = 0x00000001; //也可以直接寫作 data.n = 1;
if(data.ch == 1){
printf("Little-endian\n");
}else{
printf("Big-endian\n");
}
return 0;
}
在電腦上的運行結(jié)果是:
Little-endian
實際大小端模式在內(nèi)存中的區(qū)別如下: