在上一篇CRC-8裡面有個比較簡單的偵錯法,就是同位元檢查
同位元又分為奇同位元檢查和偶同位元檢查
不過我在看到一篇文章的時候,發現他程式的寫法好特別
裡面的範例是偶同位元檢查:
unsigned int parity_check(unsigned int data){
data ^= (data >> 1);
data ^= (data >> 2);
data ^= (data >> 4);
data ^= (data >> 8);
data ^= (data >> 16);
return (data & 0x1);
}
我改了一下,之後的比較都是以奇同位元檢查做比較
WORD parity_check(BYTE data){
WORD parity = data;
parity ^= (parity >> 1);
parity ^= (parity >> 2);
parity ^= (parity >> 4);
return ((~(parity & 0x01))& 0x01);
}
我還是搞不懂為什麼他要這樣寫
那就回到奇同位元的原理來寫最簡單的程式了
如果8位元有奇數個1,那同位元就補上0
反之,如果是偶數個1,那就補上1
那麼最簡單的程式就是利用for 回圈
WORD parity_check2(WORD data)
{
WORD i;
WORD parity = 0;
for (i = 0; i < 8; i++)
{
parity += data ;
data >>= 1;
}
return ((~(parity & 0x01))& 0x01);
}
可是這樣寫的話,效率真的是…… 爛透了
那就利用CRC查表的想法來實現
利用高4位元組和低4位元組做xor,最後查出相對應的同位元資料
因為已經知道同位的方式,所以可以自行建一張16byte的資料
當然,如果記憶體夠大,那麼建256個資料是最快的
const BYTE par_table[16]={
0x01,0x00,0x00,0x01,
0x00,0x01,0x01,0x00,
0x00,0x01,0x01,0x00,
0x01,0x00,0x00,0x01,
};
查表的程式就是
WORD parity_check3(WORD data)
{
WORD nibble = data>>4;
WORD parity = 0;
parity = (data & 0x0f) ^ nibble;
return (par_table[parity]);
}
可是我又發現,這張表就只有0和1的資料結果,如果把16byte 合成1個word的話,那就可以省去不少的空間
我又把剛剛建的表,照著順序把好,那這個常數資料就會是
const WORD PAR_word=0x9669;
最後我只要把運算好的資料結果,照著順序取出來,那麼就可以得到相同的結果了
WORD parity_check4(WORD data)
{
WORD nibble = data>>4;
WORD parity = 0;
parity = (data & 0x0f) ^ nibble;
return ( (PAR_word>>parity) & 0x01 );
}
這是一個不錯的練習動腦筋的範例程式~
最後我發現parity_check4的code size 和執行速度都是最佳的(以C30 compiler 做比較),真的,一樣的結果,但程式的執行效率還是有差,不過在理解上,我想還是以for 迴圈的寫法,是最容易懂的,但是只要多花一點時間,就可以得到不錯的成效了~
或許還有更好的寫法,但我大概就只有想到這些了~
PIC24有內建CRC的樣子,還沒用過。
回覆刪除[版主回覆12/06/2010 20:37:00]現在有些MCU有內建CRC,只是想試著練習自己用軟體實現看看
練習練習而已