機電之家資源網
單片機首頁|單片機基礎|單片機應用|單片機開發(fā)|單片機文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開發(fā)
培訓信息
贊助商
ATMEGA8單片機的輸入捕獲(ICP)解碼萬能紅外線遙控器
ATMEGA8單片機的輸入捕獲(ICP)解碼萬能紅外線遙控器
 更新時間:2009-12-2 16:24:36  點擊數(shù):0
【字體: 字體顏色

萬能遙控器在使用前一般要進行設置,針對RM-2008這款萬能遙控,設置方法如下:

先按住“設置”鍵不放,再按下“電源”(“開/關”)鍵,工作指示燈亮起,然后釋放兩鍵,在此時進入代碼輸入狀態(tài),依次鍵入 0 0 0 指示燈熄滅,設置成功!

說明一下:0 0 0 編碼shi日立公司初期de紅外編碼方式,也就shi網上到處都通用de紅外編碼方式(如下圖),另外本程序只能對此編碼進行解碼

數(shù)據(jù)頭de時間:Th=9+4.5=13.5ms

    數(shù)據(jù)“0”de時間:T0=0.565+0.56=1.125ms

    數(shù)據(jù)“1”de時間:T1=1.685+0.56=2.245ms

本程序通過使用輸入捕獲功能(ICP)捕捉紅外信號de高電平脈寬,達到解碼de目de;如果捕獲到de脈寬shi4.5ms 則表示此信號為同步碼,如果捕獲到de脈寬shi1.685ms de話則表示 “1” 否則表示“0”

測試電路如下:

使用DNW 串口調試軟件時de效果

/////////////////////////////////只有一個文件main.c///////////////////////////////////

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <stdio.h>


/*----------------------遙控操作值--------------------*/

//        key        code (hex)
#define Key_1       0x01
#define Key_2       0x02
#define Key_3       0x03
#define Key_4       0x04
#define Key_5       0x05
#define Key_6       0x06
#define Key_7       0x07
#define Key_8       0x08
#define Key_9       0x09
#define Key_0       0x00
#define Menu      0x5c       // 菜單
#define Menu_up   0x56       // 菜單上
#define Menu_down   0x57       // 菜單下
#define Menu_left   0x5f       // 菜單左
#define Menu_right 0x5b       // 菜單右
#define Menu_ok     0x16       // 菜單確認
#define Channel_up 0x1b       // 頻道+
#define Channel_down 0x1f       // 頻道-
#define Sound_up      0x1e       // 音量+
#define Sound_down   0x1a       // 音量-
#define Open_Close 0x12       // 開/關
#define Mute        0x10       // 靜音
#define Pic_in_pic 0x51          //畫中畫
#define Standard    0x58       // 制式
#define Return      0x52       // 返回
#define Times       0x0b       // 倍數(shù)
#define Screen      0x16       // 屏幕
#define Audio       0x1d       // 伴音
#define NICAM       0x13       // 麗音
#define TV_Vedio    0x0f     // 電視/視頻
#define Sleep       0x0e    //睡眠

/*----------------------常用參數(shù)定義-------------------*/

#define P0 0
#define P1 1
#define P2 2
#define P3 3
#define P4 4
#define P5 5
#define P6 6
#define P7 7

#define FREQ 8 //定義單片機工作頻率為 8M
#define uint unsigned int
#define uchar unsigned char

#define Start_T1 TCCR1B|=_BV(CS11);TCNT1=0//復位預計分頻器并開啟定時器T1
#define Stop_T1 TCCR1B&=~_BV(CS11) //關閉定時器T1

/*-----------------IR信號指示燈操作函數(shù)---------*/

#define EN_IR_LED DDRB|=_BV(P1)
#define CLR_IR_LED PORTB&=~_BV(P1)
#define SET_IR_LED PORTB|=_BV(P1)

/*----------------------某些端口操作-------------------*/

volatile unsigned char i,j,k;

volatile unsigned long IRcode;                //定義一個長度為4字節(jié)de無符號long類型變量來存儲代碼

volatile unsigned char *IRcodePointer ;     //定義一個無符號de單字節(jié)指針變量,
              //用此地址變量來分別讀取IRCodede
              //4個字節(jié) 其中操作碼為 IRcodePointer[2]
              //用戶碼為 IRcodePointer[0]

volatile unsigned char IRReceiveEffective=0;     //IR信號接收有效 當程序響應接收以后請馬上清零 這樣才會繼續(xù)接收下一IR碼

volatile unsigned char IRReceiveCurrentBit=0; //IR信號當前接收位 0時表示第0位即同步碼(4.5ms高電平)

volatile unsigned int Pulse_length=0;          //捕獲de脈沖寬度

volatile unsigned char ICP_Parity=0;           //捕獲中斷奇偶次計數(shù) 1時為偶次 并在此時判斷脈寬

volatile unsigned char Received_Key_Temp;      //紅外接收操作鍵緩存

const unsigned char String[]={"You Have Press Key : "};


/*----------------------串口定義-------------------*/

unsigned char SetPrintfConvertMode=0; //使用printf作其他轉換,并非輸出到UART

void Uart_Init(void);

int System_putchar(char c, FILE *stream);
int System_getchar(FILE *stream);

FILE mystd = FDEV_SETUP_STREAM(System_putchar, System_getchar,_FDEV_SETUP_RW);

/*----------------------常用函數(shù)定義------------------*/

void delay_nms(unsigned int ms)                //N ms延時函數(shù)
{
for(i=0;i<ms;i++)
   _delay_loop_2(FREQ*250);
}


/*----------------------系統(tǒng)初始化函數(shù)定義------------------*/

void IO_INIT(void)
{
PORTB|=_BV(P0); //設置ICP引腳內部上拉 經過試驗驗證,上拉會提高紅外接收靈敏度
}


ISR(TIMER1_COMPA_vect)   
{
IRReceiveCurrentBit=0;//重置IR接收位為第0位,為下次接收做準備
TIMSK&=~_BV(OCIE1A); //關閉溢出中斷
TCCR1B|=_BV(ICES1); //設置輸入捕獲 上升沿有效
ICP_Parity=0;     

Stop_T1;   
CLR_IR_LED;
}

ISR(TIMER1_CAPT_vect)
{
if(!IRReceiveEffective)
{
   if(ICP_Parity==0)
    {
     ICP_Parity++;
     TIMSK|=_BV(OCIE1A);
     TCCR1B&=~_BV(ICES1); //設置輸入捕獲 下降沿有效
     Start_T1 ;  
    }
   else
    {
    

Stop_T1;

ICP_Parity=0;
     TCCR1B|=_BV(ICES1);//設置輸入捕獲 上升沿有效
     Pulse_length=ICR1;
     if(IRReceiveCurrentBit==0)
      {
       if(Pulse_length>=3500&&Pulse_length<5500)// 如果shi引導碼 (4.5ms) 進入下一個bitde讀取
        IRReceiveCurrentBit++;
      }
     else if(IRReceiveCurrentBit<33) //接收32位數(shù)據(jù)
      {
       IRcode>>=1;
       if(Pulse_length<1900&&Pulse_length>1400) //判斷shi否為 1 ( 1.685 ms)
        IRcode|=0x80000000;
       IRReceiveCurrentBit++;
       if(IRReceiveCurrentBit==33)
        {
         IRReceiveCurrentBit=0; //重置IR接收位為第0位,為下次接收做準備
         if(IRcodePointer[0]==(unsigned char)(~IRcodePointer[1])&&IRcodePointer[2]==(unsigned char)(~IRcodePointer[3]))
          {
           SET_IR_LED;    //開啟IR信號指示燈
           IRReceiveEffective=1; //數(shù)據(jù)有效
          }
         delay_nms(5); //因為32位數(shù)據(jù)后面還有一個信號上跳變,所以要適當延時,延時0.65ms以上即可
        }
      }
    }
}
}

/////////////////////////////////////////////////////////////////


int main(void)
{

wdt_disable();

IO_INIT();

Uart_Init();


TCCR1B=_BV(WGM12)|_BV(CS11);//采用8分頻 這樣de話 TCNT1de計數(shù)時基為 1us
OCR1A=8000; //TCNT1 計數(shù)上限 設置IR接收超時 這里設置 8ms

TIMSK|=_BV(TICIE1);//開啟輸入捕獲中斷

TCCR1B|=_BV(ICES1);//輸入捕獲 上升沿有效

EN_IR_LED; //IR信號指示燈允許
CLR_IR_LED; //關閉IR信號指示燈

IRcodePointer=&IRcode;

sei();

while(1)
{
   if(IRReceiveEffective)
    {
     Received_Key_Temp=IRcodePointer[2];//把接收到de操作鍵放入緩存
     IRReceiveEffective=0; //允許下一次接收
     switch(Received_Key_Temp)
      {
       case Key_1      : printf("\n%sKey_1",String);break;
       case Key_2      : printf("\n%sKey_2",String);break;
       case Key_3      : printf("\n%sKey_3",String);break;
       case Key_4      : printf("\n%sKey_4",String);break;
       case Key_5      : printf("\n%sKey_5",String);break;
       case Key_6      : printf("\n%sKey_6",String);break;
       case Key_7      : printf("\n%sKey_7",String);break;
       case Key_8      : printf("\n%sKey_8",String);break;
       case Key_9      : printf("\n%sKey_9",String);break;
       case Key_0      : printf("\n%sKey_0",String);break;
       case Menu       : printf("\n%sMenu",String);break;
       case Menu_up    : printf("\n%sMenu_up",String);break;
       case Menu_down : printf("\n%sMenu_down",String);break;
       case Menu_left : printf("\n%sMenu_left",String);break;
       case Menu_right : printf("\n%sMenu_right",String);break;
       case Menu_ok    : printf("\n%sMenu_ok",String);break;
       case Channel_up : printf("\n%sChannel+",String);break;
       case Channel_down   : printf("\n%sChannel-",String);break;
       case Sound_up     : printf("\n%sSound+",String);break;
       case Sound_down   : printf("\n%sSound-",String);break;
       case Open_Close : printf("\n%sOpen_Close",String);break;
       case Mute       : printf("\n%sMute",String);break;
       case Standard   : printf("\n%sStandard",String);break;
       case Return     : printf("\n%sReturn",String);break;
       case Times      : printf("\n%sTimes",String);break;
       //case Screen     : printf("\n%sScreen",String);break;//Screen 與 menu_ok 值相同
       case Audio      : printf("\n%sAudio",String);break;
       case NICAM      : printf("\n%sNICAM" ,String);break;
       case TV_Vedio   : printf("\n%sTV_Vedio",String);break;
       case Sleep      : printf("\n%sSleep",String);break;
       case Pic_in_pic : printf("\n%sPic_in_pic",String);break;
       default:printf("\n%sOther Key 0x%x",String,Received_Key_Temp);break;
      }
    CLR_IR_LED;     //處理完數(shù)據(jù)以后關閉IR信號指示燈
    }
  
}
}


/*----------------------串口函數(shù)實體------------------*/

void Uart_Init(void)
{
UCSRB=_BV(RXEN)|_BV(TXEN);
UBRRL=25;   //8M 19200
stdout=&mystd;
stdin=&mystd;
}

int System_putchar(char c, FILE *stream)
{
if(SetPrintfConvertMode==1)
{
    
}
else
{
   if (c == \n)
   System_putchar(\r, stream);
   loop_until_bit_is_set(UCSRA, UDRE);
   UDR = c;
}
return 0;
}


int System_getchar( FILE *stream)
{
loop_until_bit_is_set(UCSRA,RXC);
return UDR;
}

  • 上一篇: ATmega8單片機萬年歷C程序(內部RTC)
  • 下一篇: 沒有了
  • 發(fā)表評論   告訴好友   打印此文  收藏此頁  關閉窗口  返回頂部
    熱點文章
     
    推薦文章
     
    相關文章
    網友評論:(只顯示最新5條。)
    關于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機電之家 | 會員助手 | 免費鏈接

    點擊這里給我發(fā)消息66821730(技術支持)點擊這里給我發(fā)消息66821730(廣告投放) 點擊這里給我發(fā)消息41031197(編輯) 點擊這里給我發(fā)消息58733127(審核)
    本站提供的機電設備,機電供求等信息由機電企業(yè)自行提供,該企業(yè)負責信息內容的真實性、準確性和合法性。
    機電之家對此不承擔任何保證責任,有侵犯您利益的地方請聯(lián)系機電之家,機電之家將及時作出處理。
    Copyright 2007 機電之家 Inc All Rights Reserved.機電之家-由機電一體化網更名-聲明
    電話:0571-87774297 傳真:0571-87774298
    杭州濱興科技有限公司提供技術支持

    主辦:杭州市高新區(qū)(濱江)機電一體化學會
    中國行業(yè)電子商務100強網站

    網站經營許可證:浙B2-20080178-1