二進位制逆序(位元組反轉)
阿新 • • 發佈:2018-12-27
1 理論分析
二進位制逆序,顧名思義就是將低位和高位交換,例如0x23 = 0010 0011 B,逆序後就是1100 0100 B。位元組反轉在“小端”格式和“大端”格式之間的資料轉換是一個必要的操作。
一種比較笨的辦法就是將位元組裡的每一位提取出來,再重新組合,這種方法較為耗費時間,對低端微控制器而言極為不利。實際上通過與運算(&)和移位運算,可以輕鬆的做到這一點。
主要原理:先交換每相鄰兩位上的數,以後把互相交換過的數看成一個整體,繼續進行以2位為單位的交換操作,之後以4為單位,以此類推。 以211= 11010011 B為例:
狀態 | ||||||||
---|---|---|---|---|---|---|---|---|
1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 11010011<—原數 |
1 1 | 1 0 | 0 0 | 1 1 | 11100011<—第一次運算後 | ||||
1 0 1 1 | 1 1 0 0 | 10111100<—第二次運算後 | ||||||
1 1 0 0 1 0 1 1 | 11001011<—第三次運算後 |
2 程式實現
/* ****************************************************************/
/**
** @brief CRC校驗函式
** @details 需要進行8位位元組大小端逆序和,16位位元組大小端逆序
** @note
*/
/* ***************************************************************/
unsigned int _CRC16(unsigned char *puchMsg, unsigned int usDataLen)
{
unsigned int wCRCin = 0xFFFF;
unsigned int wCPoly = 0x1021;
unsigned char wChar = 0x0000;
while (usDataLen--)
{
wChar = *(puchMsg++);
/* 8位交換大小端 */
/* InvertUint8(&wChar,&wChar); */
// 交換每兩位
wChar = ((wChar >> 1) & 0x55) | ((wChar & 0x55) << 1);
// 交換每四位中的前兩位和後兩位
wChar = ((wChar >> 2) & 0x33) | ((wChar & 0x33) << 2);
// 交換每八位中的前四位和後四位
wChar = ((wChar >> 4) & 0x0F) | ((wChar & 0x0F) << 4);
wCRCin ^= (wChar << 8);
for(int i = 0;i < 8;i++)
{
if(wCRCin & 0x8000)
wCRCin = (wCRCin << 1) ^ wCPoly;
else
wCRCin = wCRCin << 1;
}
}
/* 16位交換大小端 */
/* InvertUint16(&wCRCin,&wCRCin); */
// 交換每兩位
wCRCin = ((wCRCin >> 1) & 0x5555) | ((wCRCin & 0x5555) << 1);
// 交換每四位中的前兩位和後兩位
wCRCin = ((wCRCin >> 2) & 0x3333) | ((wCRCin & 0x3333) << 2);
// 交換每八位中的前四位和後四位
wCRCin = ((wCRCin >> 4) & 0x0F0F) | ((wCRCin & 0x0F0F) << 4);
// 交換相鄰的兩個位元組
wCRCin = ((wCRCin >> 8) & 0x00FF) | ((wCRCin & 0x00FF) << 8);
return (wCRCin);
}
3,博主注
可以把整個過程看出一個遞迴過程理解起來會容易很多,比如:
00111101先分成0011-1101兩部分調換1101-0011
1101先分成11-01兩部分調換01-11(0011同理)
01分成0-1調換成1-0(11同理)
可以用遞迴函式完成這個過程,但32位以內都是沒有必要的。