#define WD_END (5u+1u) // 5ms
#define RM_OFTM 60u // 20ms
#define RM_OFTM_R 100u // 100ms
/*以下的時序值都經過特殊處理*/
#define RC_HEADER0 (13300000ul/RC_CLK) //13.3MS
#define RC_HEADER1 (13700000ul/RC_CLK) //13.7MS
#define RC_REPEAT0 (11050000ul/RC_CLK) //11.05MS
#define RC_REPEAT1 (11450000ul/RC_CLK) //11.45MS
#define RC_CODE1 (2250000ul/RC_CLK) //2.25MS
#define RC_CODE1_GOSA ( 200000ul/RC_CLK) //0.2MS
#define RC_CODE0 (1125000ul/RC_CLK) //1.125MS
#define RC_CODE0_GOSA ( 100000ul/RC_CLK) //0.1MS
#define RC_CODE_0_1 (2000000ul/RC_CLK) //2 MS
對以上定義補充說明:程式中RC_CLK是 1185ul,這是因為分頻運算後1/27M×32=1.185(周期乘以MCU位元,注意單位跟M對應的是US)。這是表示一個CLK是對應1.185微秒,由於遙控計時器是對RCLK進行計數,所以要有一個轉換,M×RCLK(對應的時間)=13.3MS,即M=13.3M/RCLK=13.3×1000US/1.185US得對應的參考值。
/*定義解碼所需的標誌*/
static U32 InputData; //轉儲資料
static U8 rcv_header = WRONG; //解出頭碼標誌
static U8 rcv_repeat = WRONG; //解出重發標誌
static U8 BitCount; //位計數器
static U8 RcOffTimer; //遙控發碼的剩餘時間
U8 OneCodeTime;
void remocon_initial (void)
{
/*初始化IR相應的寄存器*/
BitCount = 0;
}
#pragma INTERRUPT remocon_edge //邊沿中斷觸發函數,由電平跳變即執行
void remocon_edge (void)
{
/*在IR寄存器檢測正常的情況下,繼續執行*/
U16 pls_cnt = IR_MFTCMPRLD;
if( (RC_HEADER0 <= pls_cnt) && (pls_cnt <= RC_HEADER1) )
{
//Header Pulse,判斷頭脈衝,由於反向後IR PIN預設是高電平,該寄存器主要用來
rcv_header = TRUE; //獲得一次由低到高的跳變時間,NEC預設是13.5MS,13.3<13.7
//由於接下來就是資料碼,所以不需要時延RcOffTimer。
}
Else if( (RC_REPEAT0 <= pls_cnt) && (pls_cnt <= RC_REPEAT1) )
{
//Repeat Pulse,同理用來檢測重發碼,NEC標準為11.5MS,必須處於RC_REPEAT0
rcv_repeat = TRUE; //與RC_REPEAT1之間,即視為識別
RcOffTimer = RM_OFTM_R; //由於重發後相鄰的一次脈衝在100MS之後,所以有//必要延時,避免重複資料偵測。
}
Else if( rcv_header == TRUE ) //頭碼判斷出來之後
{
if( BitCount < 32 ) //位長32位是標準,如果未到,繼續檢測完。
{
if((pls_cnt>=(RC_CODE0-RC_CODE0_GOSA))&&((RC_CODE1+RC_CODE1_GOSA) >= pls_cnt))
{
InputData >>= 1; //需處理新的一位,將以前的資料右移,注意發送順序//和預存程序是反向的。
if ( pls_cnt >= RC_CODE_0_1 ) //如果時延大於2MS,足可以判定該次接//收的是1
{
InputData |= 0x80000000;//將最高接收位置1,說明該次讀出的是1
}
BitCount++; //位計數器加1
RcOffTimer = RM_OFTM; // RcOffTimer的作用很奇特,其實在每解出一//個位後,該值被重設。當解出最後一個BIT後,該值才不再改變,被後//面的 //1MS處理函數處理消耗完剩下的時間,再集中判斷處理。該值不一//定很准,因為跟之前的01數目有關係,所以只能提供大概值。
}
}
OneCodeTime = WD_END; //一次解碼過程完成,做個標記值,供後面消耗時間再//判斷
}
}
Void remocon_1ms (void) //該函數處在一個1MS的控制台中,迴圈執行。其中的兩個子///////過程一個用來處理單發,一個處理重發。
{
if( OneCodeTime != 0 ) //在一次所有的碼發完之後,OneCodeTime值固定下來,
{
OneCodeTime- -; //延遲穩定6MS之後開始解資料
if( OneCodeTime == 0 )
{
if( BitCount >= 32 ) //在完整接收和正確發碼的情況下,最後一次邊沿觸發//完後,BitCount是32,當然有多32位的情況下,會忽略掉後面的(偶爾)
{
RcOffTimer = RM_OFTM; //進入該判斷,表示正確接收開始解碼,其後// RcOffTimer是為了消耗掉一次發碼後剩餘的時間
if( (InputData & 0x0000FFFFu) == CUSTOMER_CODE )//如果客戶碼是//匹配的,注意順序我們從示波器上讀的值是從右往左存,所以客戶碼轉//成16進位時從高位往低位組合。
{
if( (U8)((((InputData & 0xFF000000) ^ ((InputData & 0x00FF0000u) << 8)) >> 24) ) == 0xFF ) //如果資料碼和資料碼的反碼相匹配,滿足異或為1
{
RcData = (U16)((InputData & 0x00FF0000u) >> 16); //真正////解出了一個碼值
InputData = 0; //清空轉儲變數
}
}
}
BitCount = 0; //不管有沒有正確解出資料,在一次完整的發出資料後,要//清空BitCount和rcv_header,表示當前該次解碼結束,如果<32,無效忽略,//是一種容錯機制
rcv_header = WRONG;
}
if( RcOffTimer != 0 ) //用於消耗掉剩餘時間
{
RcOffTimer--;
if( RcOffTimer == 0 )
{
if( rcv_repeat == TRUE ) //如果在耗時這段時間內(顯然比重發間隔要//長),重發鍵仍然按著,RcData仍然有效。
{
rcv_repeat = WRONG; //rcv_repeat清空,判斷下一個重發耗時間隔//是否有效
RcOffTimer = RM_OFTM_R;
}
Else //如果時間耗完後,rcv_repeat仍然0,說明沒有連按,清RcData
{
RcData = NP;
}
}
}
}//此處有誤
需要注意的是,NEC的大體過程是上面,但在時延上(不一定是那些時間表示01),資料位元個數上(不一定是32位)。需要作些特殊處理。If•••else•••和if •••else if•••的差別,一般情況下兩者是可以通用的,但後者有個缺點是沒有出口,一旦出現兩個都不符合的值出現,將沒有任何子程式段處理,在編譯時間會警告某些後面用到的參數在子程式段中沒有初始化。