NEC協議載波:38khz
其邏輯1與邏輯0的表示如圖所示:
邏輯1為2.25ms,脈沖時間560us;邏輯0為1.12ms,脈沖時間560us。所以我們根據脈沖時間長短來解碼。推薦載波占空比為1/3至1/4。
NEC協議格式:
首次發送的是9ms的高電平脈沖,其后是4.5ms的低電平,接下來就是8bit的地址碼(從低有效位開始發),而后是8bit的地址碼的反碼(主要是用於校驗是否出錯)。然后是8bit 的命令碼(也是從低有效位開始發),而后也是8bit 的命令碼的反碼。
以上是一個正常的序列,但可能存在一種情況:你一直按着1個鍵,這樣的話發送的是以110ms為周期的重復碼,如下圖:
就是說,發了一次命令碼之后,不會再發送命令碼,而是每隔110ms時間,發送一段重復碼。
重復碼由9ms高電平和2.25ms的低電平以及560us的高電平組成。
需要注意的是:1838紅外一體接收頭為了提高接受靈敏度。輸入高電平,其輸出的是相反的低電平。
搞了一個下午和晚上,NEC解碼出來還是有點細微差錯。查了很久,也沒有收獲。心里有點小郁悶。今早起來,仔細地看了看他人的參考代碼。突然被下面一個小小的細節折服了。
請注意這段代碼:
1 void hal_NEC_decode(uchar *addr,uchar *addrt,uchar *comm,uchar *commt) 2 { 3 uchar i,j,k; 4 uchar tmp1=0; 5 6 while(NECFinshFlag==0); 7 NECFinshFlag=0; 8 9 for(i=0,k=1;i<4;i=i+1) 10 { 11 for(j=1;j<=8;j++) 12 { 13 if(NECTimerTable[k++] > 7) 14 { 15 tmp1 |=0x80; 16 } 17 tmp1 >>=1; 18 } 19 switch(i) 20 { 21 case 0:*addr=tmp1;break; 22 case 1:*addrt=tmp1;break; 23 case 2:*comm=tmp1;break; 24 case 3:*commt=tmp1;break; 25 } 26 tmp1=0; 27 } 28 }
最后tmp1的值是被右移了1位。所以改為下代碼
1 void hal_NEC_decode(uchar *addr,uchar *addrt,uchar *comm,uchar *commt) 2 { 3 uchar i,j,k; 4 uchar tmp1; 5 6 while(NECFrameFlag==0); 7 NECFrameFlag=0; 8 9 for(i=0,k=1;i<4;i=i+1) 10 { 11 tmp1=0; 12 for(j=0;j<8;j++) 13 { 14 tmp1 >>=1;//事先右移一位,防止最后一次循環的出錯 15 if(NECTimerTable[k++] >8) 16 { 17 tmp1 |=0x80; 18 } 19 } 20 switch(i) 21 { 22 case 0:*addr=tmp1;break; 23 case 1:*addrt=tmp1;break; 24 case 2:*comm=tmp1;break; 25 case 3:*commt=tmp1;break; 26 } 27 } 28 }
僅僅修改了這么一個代碼順序,程序就能比較完美的解析NEC協議來了。可見寫程序,小小的細節也是非常重要,可能會牽扯到整個的成功。
總結:以后編寫按1bit(不管是從LSB還是MSB開始)接收組成一個字節的程序,要格外的注意循環左移或者右移的情況。實現將臨時變量移動一下,免得最后1位還需要移動而造成的錯誤。
最后附上NEC協議的命令碼(市面上常見的遙控板)