1. 程式人生 > >新塘N76E003紅外遙控解碼程式

新塘N76E003紅外遙控解碼程式

       一直用的STM8S003的微控制器,後來價格漲到三塊多不得不換。拿上新塘N76E003晶片,資源中規中矩,相比用習慣Cortex® M 核心微控制器和STM8,用這個晶片資源就有些少了,先來個簡單的紅外遙控解碼。(打算用外部IO中斷來觸發解碼的,除錯時發現會無規律的觸發IO中斷,只得用IO掃描方式去解紅外遙控訊號。)

以日本NEC的編碼協議組成: 引導碼,16bit使用者碼(地址碼),8bit命令碼(功能碼)及其反碼

1、引導碼由一個9ms的載波波形和4.5ms的關斷時間構成(9ms低電平+4.5ms高電平)。

2、地址碼共16bit(8位系統碼和8位系統反碼),低位在前,高位在後。

遙控碼特徵:

採用脈寬調製的序列碼,以脈寬為0.565ms、間隔0.56ms、週期為1.125ms的組合表示二進位制的“0”;以脈寬為0.565ms、間隔1.685ms、週期為2.25ms的組合表示二進位制的“1”。0與1前端的低電平持續都是0.56ms,那麼就是後面的高電平持續時間不同,0為0.56ms,1為1.685ms。

程式有個問題:資料接收方向當時搞反了,接收回來的資料剛好是高低位位置互換,不影響使用就沒去改。

//-----------------my_IR.c------------------------------------------------------------

#include "my_IR.h"/*------------------------------------------------------NEC協議紅外遙控解碼計數使用資源:Timer0由於設定Timer0定時值,計算出來的值不正確,超時在Timer3中斷裡處理--------------------------------------------------------*/#define REMOTE_ID 0x0 sbit IR_IO=P0^0;bit bIR_scan=0; bit bIR=0;UINT8 IR_cont=0;UINT8 IR_code=0; //遙控按鍵值//-----------------------------------------------UINT16 Dval; //計數器的值unsigned long RmtRec=0; //接收到的資料uint16_t TIM0_GetCounter(void){ uint16_t tmpcntr = 0; tmpcntr = ((uint16_t)TH0 << 8); tmpcntr = tmpcntr| (uint16_t)(TL0); return ((uint16_t)tmpcntr*0.75);}UINT8 IR_SCAN(void){ UINT8 i=0; UINT8 t1,t2; if(bIR_scan==0) return 0; bIR_scan=0; RmtRec=0; if(IR_IO==0) { clr_TR0; clr_TF0; TL0 =0; TH0 =0; set_TR0; //Start Timer0 bIR=0;IR_cont=0; while ((IR_IO==0)&&(bIR != 1)); //Check Timer0 Time-Out Flag clr_TR0; //Stop Timer0 clr_TF0; Dval=TIM0_GetCounter(); if(Dval>8600&&Dval<9300) //9ms { TL0 =0; TH0 =0; set_TR0; //Start Timer0 bIR=0;IR_cont=0; while ((IR_IO==1)&&(bIR != 1)); //Check Timer0 Time-Out Flag clr_TR0; //Stop Timer0 clr_TF0; Dval=TIM0_GetCounter(); if(Dval>4200&&Dval<4700) //4.5ms { //---------------------------------------------------------- do{ TL0 =0; TH0 =0; set_TR0; //Start Timer0 bIR=0;IR_cont=0; while ((IR_IO==0)&&(bIR != 1)); //Check Timer0 Time-Out Flag clr_TR0; //Stop Timer0 clr_TF0; Dval=TIM0_GetCounter(); if(Dval<300&&Dval>800) //560us { return 0; } TL0 =0; TH0 =0; set_TR0; //Start Timer0 bIR=0;IR_cont=0; while ((IR_IO==1)&&(bIR != 1)); //Check Timer0 Time-Out Flag clr_TR0; //Stop Timer0 clr_TF0; Dval=TIM0_GetCounter(); if(Dval>300&&Dval<800) //560為標準值,560us { RmtRec<<=1; RmtRec|=0; //接收到0 i++; }else if(Dval>1400&&Dval<1800) //1680為標準值,1680us { RmtRec<<=1; RmtRec|=1; //接收到1 i++; } else if(Dval>2200&&Dval<2600) //得到按鍵鍵值增加的資訊 2500為標準值2.5ms { } }while(i<32); //-------------------------------------------------------------------- t1=RmtRec>>24; //得到地址碼 t2=(RmtRec>>16)&0xff; //得到地址反碼 if((t1==(UINT8)~t2)&&t1==REMOTE_ID)//檢驗遙控識別碼(ID)及地址 { t1=RmtRec>>8; t2=RmtRec; IR_code=t1; if(t1==(UINT8)~t2)return 1;//鍵值正確 } //--------------------------------------------------------------------- } } } return 0;}void my_IR_Init(void){ P00_Input_Mode; clr_T0M; //T0M=0, Timer0 Clock = Fsys/12 TMOD |= 0x01; //Timer0 is 16-bit mode set_TR0; //Start Timer0 TL0 =LOBYTE(TIMER_DIV12_VALUE_40ms); //Find define in "Function_define.h" "TIMER VALUE" TH0 =HIBYTE(TIMER_DIV12_VALUE_40ms); //clr_TR0; //Stop Timer0}

//-----------------my_IR.c

------------------------------------------------------------

#ifndef __MY_IR_H#define __MY_IR_H#include "n76e003.h"//extern bit bIR_scan; extern bit bIR;extern UINT8 IR_cont;extern UINT8 IR_code;void my_IR_Init(void);UINT8 IR_SCAN(void);#endif /*__MY_IR_H*/