51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机技术文章 > AVR单片机 > 详细内容
ATMEGA8单片机的输入捕获(ICP)解码万能红外线遥控器
发布时间:2009/8/6  阅读次数:3695  字体大小: 【】 【】【

万能遥控器在使用前一般要进行设置,针对RM-2008这款万能遥控,设置方法如下:

先按住“设置”键不放,再按下“电源”(“开/关”)键,工作指示灯亮起,然后释放两键,在此时进入代码输入状态,依次键入 0 0 0 指示灯熄灭,设置成功!

说明一下:0 0 0 编码shi日立公司初期de红外编码方式,也就shi网上到处都通用de红外编码方式(如下图),另外本程序只能对此编码进行解码

数据头de时间:Th=9+4.5=13.5ms

       数据“0”de时间:T0=0.565+0.56=1.125ms

       数据“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             // 倍数
#define Screen           0x16             // 屏幕
#define Audio             0x1d             // 伴音
#define NICAM             0x13             // 丽音
#define TV_Vedio       0x0f         // 电视/视频
#define Sleep             0x0e       //睡眠

/*----------------------常用参数定义-------------------*/

#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信号指示灯操作函数---------*/

#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字节de无符号long类型变量来存储代码

volatile unsigned char *IRcodePointer ;        //定义一个无符号de单字节指针变量,
                           //用此地址变量来分别读取IRCodede
                           //4个字节 其中操作码为 IRcodePointer[2]
                           //用户码为 IRcodePointer[0]

volatile unsigned char IRReceiveEffective=0;         //IR信号接收有效 当程序响应接收以后请马上清零 这样才会继续接收下一IR码

volatile unsigned char IRReceiveCurrentBit=0; //IR信号当前接收位 0时表示第0位即同步码(4.5ms高电平)

volatile unsigned int Pulse_length=0;                   //捕获de脉冲宽度

volatile unsigned char ICP_Parity=0;                     //捕获中断奇偶次计数 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);

/*----------------------常用函数定义------------------*/

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


/*----------------------系统初始化函数定义------------------*/

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位数据
           {
             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; //数据有效
                   }
                 delay_nms(5); //因为32位数据后面还有一个信号上跳变,所以要适当延时,延时0.65ms以上即可
               }
           }
       }
}
}

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


int main(void)
{

wdt_disable();

IO_INIT();

Uart_Init();


TCCR1B=_BV(WGM12)|_BV(CS11);//采用8分频 这样de话 TCNT1de计数时基为 1us
OCR1A=8000; //TCNT1 计数上限 设置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;         //处理完数据以后关闭IR信号指示灯
       }
    
}
}


/*----------------------串口函数实体------------------*/

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;
}


我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号