51单片机红外遥控解码好例程
- 格式:pdf
- 大小:55.99 KB
- 文档页数:5
/ 亲,此程序以经过测试,可直接使用!!!/#include <reg51.h>#define uchar unsigned char#define uint unsigned intvoid delay(uchar x);sbit IRIN = P3^2;uchar IRCOM[4];void main(){ IE = 0x81;TCON = 0x01;IRIN=1;/* 此处可以根据按键码自由编写程序/以下为3*7遥控按键码//(也可以应用与其他类型遥控,本程序只以3*7遥控为例)/ / 0x45 0x46 0x47 // 0x44 0x40 0x43 // 0x07 0x15 0x09 // 0x16 0x19 0x0d // 0x0c 0x18 0x5e // 0x08 0x1c 0x5a // 0x42 0x52 0x4a /例如:while(1){switch(IRCOM[2]){case 0x45: P2=0x7f; break;case 0x44: P2=0xbf; break;case 0x07: P2=0xdf; break;case 0x16: P2=0xef; break;case 0x0c: P2=0xf7; break;case 0x08: P2=0xfb; break;case 0x42: P2=0xfd; break;case 0x52: P2=0xfe; break;case 0x4a: P2=0xff; break;case 0x5a: P2=0x00; break;}} */while(1);} //end main/**********************************************************/ void IR_IN(void) interrupt 0 //外部中断服务程序{unsigned char j,k,N=0;EX0 = 0;delay(15);if (IRIN==1){ EX0 =1;return;}//确认IR信号出现while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
车载红外遥控之51单片机对单片机的了解学习,是作为简单的遥控器解码学习的基础,因为本次DIY 是通过MCU 作为解码媒介的。
但实验中的DIY 方式又不必需要功能强大的ARM 系列单片机去实现,一般0851单片机就能解决。
本实验的演示功能是通过对红外遥控键值解码后,对设定的目标键值做出响应,实验中的响应是单片机对继电器的开合、通断控制,可以简单理解为单片机检测到遥控器某个指定的按键按下,则控制继电器实现开关的切换功能,实现过程如下:首先是选型,由于物资条件,我们考虑成本,所以选择的都是廉价器件,器件有车载MP3红外遥控,1318红外接收头,51系列的stc15F104w芯片,一个11.0592MHZ 的晶振,两个100pf容,一个继电器,一个二极管1N4148,一个三极管9012/S8550,两个200欧姆电阻。
收到的遥控编码信息发送至单片机,单片机对红外遥控的键值解码后在P3.5口输出控制信原理图所示。
最后,实现解码功能的51Figure 1原理图化定时器配置,之后是不断地轮询单片机的中断引脚,检测单片机的引脚状态是否改变,如果引脚状态被改变了,说明端口有数据到来,此时单片机的定时器将在中断中被激活。
定时器被激活的作用是用来给给每个二进制数据位进行定时的,将高低电平状态产生的时间存储到一个数组里面,最后将该时间值数组转换成高低电平状态。
左图是红外遥控采集单片机中断引脚的高低电平时间,并将得到的时间放在irdate 数组里,我们使用的红外遥控的编码是32位的编码。
由引导码、用户码、数据码和数据码反码组成32位的编码方式。
实验测试得到,引导码是有9ms 的高电平和4.5ms 的低电平组成。
用户码或数据码中的每一个位可以是位‘1’,也可以是位‘0’。
区分‘0’和‘1’是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式。
英文简写PPM 。
其脉冲调制是使用455KHz 晶体产生的载波脉冲实现。
总结:通过本次实验,了解到了红外遥控编码及解码的工作原理。
51单片机红外遥控解码程序类别:单片机/DSP 阅读:2975编者按:以下是网友编写的遥控解码程序!一种用延时等待的解码方法,比较容易理解,但缺点是占用CPU运行时间,第二种方法用定时器和外中断的解码方法,初学不易理解,但优点也很明显,第二种方法如果能解决连发解码就比较完美,更完善的红外遥控解码程序,请参考本站TOPA V-2008,TOP51-2005所配程序。
解码方法一;//单片机接收红外解读程序\\;硬件结构:8951,P0口数码管段码,P2.0-P2.3为位,P1为8个LED;P3.2为红外接收头,P2.7蜂鸣器,晶振12M;适用UPD6121 6122芯片接收;---------------------------------------------------------ORG 0000HAJMP MAIN ;转入主程序ORG 0003H ;外部中断P3.2脚INT0入口地址AJMP INT ;转入外部中断服务子程序(解码程序);以下为主程序进行CPU中断方式设置MAIN: SETB EA ;打开CPU总中断请求SETB IT0 ;设定INT0的触发方式为脉冲下降沿触发SETB EX0 ;打开INT0中断请求AJMP $;以下为进入P3.2脚外部中断子程序,也就是解码程序INT: CLR EA ;暂时关闭CPU的所有中断请求MOV R6,#10SB: ACALL YS1 ;调用882微秒延时子程序JB P3.2,EXIT ;延时882微秒后判断P3.2脚是否出现高; 电平如果有就退出解码程序DJNZ R6, SB ;重复10次,目的是检测在8820微秒内;如果出现高电平就退出解码程序;以上完成对遥控信号的9000微秒的初始低电平信号的识别。
JNB P3.2, $ ;等待高电平避开9毫秒低电平引导脉冲ACALL YS2 ;延时4.74毫秒避开4.5毫秒的结果码MOV R1,#1AH ;设定1AH为起始RAM区MOV R2,#4;PP: MOV R3,#8JJJJ: JNB P3.2,$ ;等待地址码第一位的高电平信号LCALL YS1 ;高电平开始后用882微秒的时间尺去判断信;号此时的高低电平状态MOV C,P3.2 ;将P3.2引脚此时的电平状态0或1存入C中JNC UUU ;如果为0就跳转到UUULCALL YS3;UUU: MOV A,@R1 ;将R1中地址的给ARRC A ;将C中的值0或1移入A中的最低位MOV @R1,A ;将A中的数暂时存放在R1中DJNZ R3,JJJJ ;接收地址码的高8位INC R1 ;对R1中的值加1,换下一个RAMDJNZ R2,PP ;接收完16位地址码和8位数据码和8位数据反; 码,存放在1AH/1BH/1CH/1DH的RAM中MOV A,1CH ;比较数据码和数据反码是否正确?CPL AXRL A,1DH ;将1CH的值取反后和1DH比较不同则无效丢弃,核对数据是否准确JNZ EXITMOV DPTR,#TAB ;表头地址送指针MOV A,1DHANL A,#0FH ;相与,得到低四位码MOVC A,@A+DPTRMOV 1EH,A ;查表得表码存入1EHMOV A,1DHSWAP AANL A,#0FHMOVC A,@A+DPTRMOV 1FH,A ;查表得高四位码存入1FMOV R7,#20HDISP:MOV P0,1FH ;送数码管显示CLR P2.1ACALL YS2SETB P2.1MOV P0,1EHCLR P2.2ACALL YS2SETB P2.2MOV P1,1DH ;将按键的键值通过P1口的8个LED显示出来!CLR P2.7 ;蜂鸣器鸣响-嘀嘀嘀-的声音,表示解码成功LCALL YS2SETB P2.7 ;蜂鸣器停止DJNZ R7,DISPEXIT: SETB EA ;允许中断RETI ;退出解码子程序YS1: MOV R4,#20 ;延时子程序1,精确延时882微秒D1: MOV R5,#20DJNZ R5,$DJNZ R4,D1RETYS2: MOV R4,#10 ;延时子程序2,精确延时4740微秒D2: MOV R5,#235DJNZ R5,$DJNZ R4,D2RETYS3: MOV R4,#2 ;延时程序3,精确延时1000微秒D3:MOV R5,#248DJNZ R5,$DJNZ R4,D3RETTAB: DB 0C0H,0DEH,0A2H,8AH,9CH,89H,81H,0DAH,80H,88H,90H,85H,0E1H,86H,0A1H,0B1H;数据表,0-9-A-FEND解码方法二你的解码程序和我现在用的解码程序大体是一样的,我自己实际做了一下,发现按下遥控器,接收到红外信号后,数码管闪的厉害。
用单片机解码红外遥控器用单片机解码红外遥控器遥控器使用方便,功能多.目前已广泛应用在电视机、VCD、DVD、空调等各种家用电器中,且价格便宜,市场上非常容易买到。
如果能将遥控器上许多的按键解码出来.用作单片机系统的输入.则解决了常规矩阵键盘线路板过大、布线复杂、占用I/O口过多的弊病。
而且通过使用遥控器,操作时可实现人与设备的分离,从而更加方便使用。
下面以TC9012编码芯片的遥控器为例。
谈谈如何用常用的51系统单片机进行遥控的解码。
一、编码格式1、0和1的编码遥控器发射的信号由一串O和1的二进制代码组成.不同的芯片对0和1的编码有所不同。
通常有曼彻斯特编码和脉冲宽度编码。
TC9012的O和1采用PWM方法编码,即脉冲宽度调制,其O码和1码如图1所示(以遥控接收输出的波形为例)。
O码由O.56ms低电平和0.56ms高电平组合而成.脉冲宽度为1.12ms.1码由0.56ms低电平和1.69ms高电平组合而成.脉冲宽度为2.25ms。
在编写解码程序时.通过判断脉冲的宽度,即可得到0或1。
2、按键的编码当我们按下遥控器的按键时,遥控器将发出如图2的一串二进制代码,我们称它为一帧数据。
根据各部分的功能。
可将它们分为5部分,分别为引导码、地址码、地址码、数据码、数据反码。
遥控器发射代码时.均是低位在前。
高位在后。
由图2分析可以得到.引导码高电平为4.5ms,低电平为4.5ms。
当接收到此码时.表示一帧数据的开始。
单片机可以准备接收下面的数据。
地址码由8位二进制组成,共256种.图中地址码重发了一次。
主要是加强遥控器的可靠性.如果两次地址码不相同.则说明本帧数据有错.应丢弃。
不同的设备可以拥有不同的地址码.因此。
同种编码的遥控器只要设置地址码不同,也不会相互干扰。
图中的地址码为十六进制的0EH(注意低位在前)。
在同一个遥控器中.所有按键发出的地址码都是相同的。
数据码为8位,可编码256种状态,代表实际所按下的键。
// c51红外解码、超声波测距程序#include <reg52.h>#define uchar unsigned char#define uint unsigned int#define count 4uchar data IRcode[4]; //定义一个4字节的数组用来存储代码uchar table[4];uchar enled[4]={0x1f,0x2f,0x4f,0x8f};uchar CodeTemp,temp,tt; //编码字节缓存变量uchari,j,k,temp,timeH,timeL,succeed_flag,flag,h,h1,h2,a,key,key1,key2; //延时用的循环变量uint distance,distance1,time; //距离,timesbit IRsignal=P3^2; //HS0038接收头OUT端直接连P3.2(INT0)sbit come=P3^3;sbit d=P1^1;//发送码sbit BZ=P1^0;sbit s=P3^7;//38ksbit ss=P3^6;//38kuchar m;// 开关控制//sbit n=P2;//电机反转code unsigned charseg7code[10]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28}; //显示段码/**************************** 定时器0中断************************/void timer0() interrupt 1{TH0=(65536-count)/256;TL0=(65536-count)%256;s=~s;//产生38K信号ss=~ss;//tt++;//发送超声波个数}/**************************** 延时0.9ms子程序************************/void Delay0_9ms(void){uchar j,k;for(j=18;j>0;j--)for(k=20;k>0;k--);}/***************************延时1ms子程序**********************/void Delay1ms(void){uchar i,j;for(i=2;i>0;i--)for(j=230;j>0;j--);}/***************************延时4.5ms子程序**********************/ void Delay4_5ms(void){uchar i,j;for(i=10;i>0;i--)for(j=225;j>0;j--);}/**************************** 解码延时子程序************************/ void Delay(void){uchar i,j,k;for(i=100;i>0;i--)for(j=100;j>0;j--)for(k=3;k>0;k--);}/**************************** 显示延时子程序************************/ void ledDelay(unsigned int tc) //延时程序{unsigned int i,j;for(i=0;i<10;i++)for(j=0;j<tc;j++);}/************************************************ ****************///定时器1中断,用做超声波测距无回波void timer1() interrupt 3{TR1=0;ET1=0;EX1=0;TH1=0;TL1=0;}/***********************显示程序*********************/ void Led(int date) //显示函数{ int i;table[0]=date/1000;table[1]=date/100%10;table[2]=date/10%10;table[3]=date%10;date=0;for(i=0;i<120;i++){P2=enled[i%4]&m;//P2口高四位控制数码管,低位陪分控制继电器P0=seg7code[table[i%4]]; //取出千位数,查表,输出。
精心整理纯软件解码---汇编版利用程序判电平和时间进行解码,缺点是浪费系统软件资源;优点是对系统硬件要求稍低ORG0000HT0ZDBIT20H.2XHBITP3.3;红外接收头数据接口RSBITP2.3RWBITP2.4============================================================JBXH,$;等待电平变低,解码从这开始CLRP2.0;开信号指示灯,表示正在接收信号MOVP0,#8EHSETBTR0;开T0中断LCALLYS3MSJBXH,DDXH;干扰检测LCALLYS3MSJBXH,DDXH;干扰检测DD1:JBT0ZD,DDXH;是否超出接收允许时间JNBXH,DD1;等待电平变高LCALLYS3MSJNBXH,DDXH;干扰检测DD2:JBT0ZD,DDXH;是否超出接收允许时间JBXH,DD2;等待电平变低JSSJ:;信号确认,开始接收数据ZJ:;MOVR7,#100;TSY:MOVR6,#255DJNZR6,$CPLBBDJNZR7,TSYMOVA,#0CDH;键值高位输出LCALLYJP_XZLMOVA,R4MOVB,#10HDIVABMOVCA,@A+DPTRLCALLYJP_XSJMOVA,#0CEH;键值低位输出LCALLYJP_XZLMOVA,BMOVCA,@A+DPTR LCALLYJP_XSJ; LCALLDYBF;调用灯控制子程序LJMPDDXH;返还等待下一次信号YS845:;延时845微秒MOVR7,#255RETRETDIVABMOVCA,@A+DPTR LCALLYJP_XSJMOVA,#0C1H;用户码前低位输出LCALLYJP_XZLMOVA,BMOVCA,@A+DPTR LCALLYJP_XSJMOVA,#0C4H;用户码后高位输出LCALLYJP_XZLMOVA,31HMOVB,#10HDIVABMOVCA,@A+DPTRLCALLYJP_XSJMOVA,#0C5H;用户码后低位输出LCALLYJP_XZLMOVA,BMOVCA,@A+DPTRLCALLYJP_XSJ;============此处专门针对我的开发板和遥控,不是解码的关键,只是一种应用举例BA7:CJNEA,#52H,BAB;是否8号键按下CPLP1.7;点亮1号灯BAB:RETCSH:;=============液晶初始化===============MOVA,#00111000B;8位数据,双行显示,5-7字型LCALLYJP_XZL;调用写液晶指令MOVA,#00001100B;显示屏开启,光标出现在地址计数器位置,光标不闪烁LCALLYJP_XZL;调用写液晶指令MOVA,#00000110B;光标右移一格,AC值加一,字符全部不动LCALLYJP_XZL;调用写液晶指令MOVA,#81H;LCALLYJP_XZLMOVA,#4CH;L的ASCII码LCALLYJP_XSJMOVA,#83H;LCALLYJP_XZLLCALLYJP_XZLMOVA,#61H;a的ASCII码LCALLYJP_XSJMOVA,#8EH;LCALLYJP_XZLMOVA,#6FH;o的ASCII码LCALLYJP_XSJMOVA,#0C2H;LCALLYJP_XZLMOVA,#48H;H的ASCII码LCALLYJP_XSJMOVA,#0C6H;LCALLYJP_XZLMOVA,#48H;H的ASCII码LCALLYJP_XSJMOVA,#0CAH;LCALLYJP_XZLMOVA,#4AH;J的ASCII码LCALLYJP_XSJMOVA,#0CBH;LCALLYJP_XZLMOVA,#5AH;Z的ASCII码RETRETCLRESETBRSCLRRWSETBEMOVP0,A;写数据CLRERET;=========查询忙碌标志============ CHECK_BUSY:PUSHACCBUSY_LOOP:CLRESETBRWCLRRSSETBEMOVA,P0;读取状态JBp0.7,BUSY_LOOPPOPACCLCALLDELRETDEL:MOVR6,#5RET/////////#definezd_cffsIT0///中断触发方式设置#definezd_dkEX0///中断打开设置////#definestc_dsqszAUXR&=0x7F;//定时器时钟12T模式,不需要可在AUXR....前加// ///**************************************************/****************************************************************** *****本程序使用外部中断加定时器来实现红外解码,占用系统软件资******** *****源极少,硬件方面占用了一个外部中断,定时器中断还可以进行******** *****一些简单的运用,软件部分可以做很多的动作,就看你发挥了!**************************************************************************/ #defineshi_jian定时器设置,请勿更改unsignedcharhwyhmh,hwyhml,hwjz,hwsj,hwjmws;///全局变量bithwjmok,yxjm;///全局变量,红外解码OK,允许解码voidmain(void){EA=1;//总中断打开zd_cffs=1;//外部中断_边沿触发方式zd_dk=1;//外部中断_打开ET0=1;//while(1)}}}定时器0{hwjz=0;TR0=0;//}voidZDhwjsCX(void)zd_rkdzusing3{unsignedinta=TH0*256+TL0;TL0=0;TH0=0;TR0=1;///开启T0if(a>shi_jian_*13000&&a<shi_jian_*14000)///if1分支2.判引导码13-14ms {hwsj=0;hwjmws=32;yxjm=1;}elseif(yxjm)///if1分支1.已收到引导码,允许解码{if(a>shi_jian_*11000&&a<shi_jian_*12000&&hwjmws==0)///if2分支1。
keilc51红外遥控解码程序keil c51红外遥控解码程序本keil c51程序适用uPC1621/uPC1622及兼容的红外遥控器芯片,占用外部中断0和定时器1,以中断方式解码,节省系统资源,以查询方式检测遥控信号是否有效.解码思路:红外线经一体化接受头解码放到后送到单片机的外部中断0,单片机设置外部中断下降沿触发,T0和T1为16位定时器,T0在系统启动后定时5ms.T1在外部中断0启动后开始定时,初值为0,每次在INT0中断后先读T1计数值,并重设初值为0,而且判断T1的计数值,18.unsigned char IR_repeat=0;19.unsigned char IR_ready=0;20.unsigned char IR_poweron=0;21.//bit ir_done=0;22.// time constants23.unsigned int IRtimer=0; // IR timeout24.25.//cpu初始化26.void cpu_init(void)27.{28.TMOD=0X11; // T0 and T1 十六位定时29.TH0=0xee; //fosc=11.0592M,timer=5ms30.TL0=0x00;31.TR0=1; // run timer 0;32.TF0=0;33.34.ET0=1; // enable tmr 0 overflow interrupt35.IT0=1; // int0 edge sensitive36.EX0=1; // enable "int0"37.EA=1; // global interupt enable38.}39.40.//T0中断41.void tmrint() interrupt 142.{43.TH0=0xee;44.TL0=0x00;45.if (IRtimer) //IR接收超时46.--IRtimer; //47.else48.{49.IRstate=IR_idle;50.// IR_poweron=0;51.}52.}53.54.//Fosc=11.0592MHz55.#define msec_12p5 0x2d0056.#define msec_15 0x360057.#define msec_9 0x206658.//#define msec_9 0x106659.#define msec_2p5 0x90060.#define msec_0p9 0x33d61.#define msec_1p68 0x61062.63.64.//void IRint() interrupt 0(void)65.66.//When the IR receive pin goes low and interrupt is ge nerated67.// IR is collected by starting timer 2 in the first falling edge of the pin68.// then on every other falling edge, the timer value i s saved and the timer restarted .69.// the captured time is then used to get the IR data70.// a "start of data" is 13.5Msec,a "1" is 2.25Msec,a "0" i s 1.12 msec and a "repeat" is 11.25msec.71.// the counter increments at 1.085 Usec72.// I allow a fairly large tolerance to time jitter but there are no false triggers seen.73.74.void IRint() interrupt 075.{76.static unsigned char bits;77.unsigned short time;78.switch(IRstate)79.{80.case IR_idle:81.TL1=0;82.TH1=0;83.TR1=1;84.IRstate=IR_waitstart;85.IRtimer=26;86.break;87.case IR_waitstart: //P2_4=!P2_4;88.TR1=0;89.time=TH1;90.time =(time <<8)+TL1;;91.TL1=0;92.TH1=0;93.TR1=1;94.if ((time > msec_12p5)&&(time < msec_15)) // greate r than 12.5Msec & less than 15 msec = start code95.{96.IRaddr=0;97._IRaddr=0;98.IRdata=0;99._IRdata=0;100.bits=1;101.IRstate=IR_getaddr;102.}103.else if ((time > msec_9)&&(time < msec_12p5))// les s than 12.5Msec and greater than 9 msec =Repeat code 104.{105.IR_repeat=2;106.IRstate=IR_idle;107.}108.else109.{ // to short, bad data just go to idle110.IRstate=IR_idle;111.}112.break;113.case IR_getaddr: // P2_4=!P2_4;114.TR1=0;115.time=TH1;116.time =(time <<8)+TL1;;117.TL1=0;118.TH1=0;119.TR1=1;120.if ((time>msec_2p5)||(time<msec_0p9))// if > 2.5mse c or shorter than .9Msec bad data , go to idle121.{122.IRstate=IR_idle;123.break;124.}125.if (time>msec_1p68)// greater than 1.68Msec is a 1126.{127.IRaddr|= bits;128.}129.bits=bits<<1;130.if (!bits)131.{132.IRstate=IR_getaddrinv;133.bits=1;134.}135.break;136.case IR_getaddrinv: //P2_4=!P2_4;137.TR1=0;138.time=TH1;139.time =(time <<8)+TL1;;140.TL1=0;141.TH1=0;142.TR1=1;143.if ((time>msec_2p5)||(time<msec_0p9))// if > 2.5mse c or shorter than .9Msec bad data , go to idle144.{145.IRstate=IR_idle;146.break;147.}148.if (time>msec_1p68)// greater than 1.68Msec is a 1 149.{150._IRaddr|= bits;151.}152.bits=bits<<1;153.if (!bits)154.{155.IRstate=IR_getdata;;156.bits=1;157.}158.break;159.case IR_getdata:160.TR1=0;161.time=TH1;162.time =(time <<8)+TL1;;163.TL1=0;164.TH1=0;165.TR1=1;166.if ((time>msec_2p5)||(time<msec_0p9))// if > 2.5mse c or shorter than .9Msec bad data , go to idle167.{168.IRstate=IR_idle;169.break;170.}171.if (time>msec_1p68)// greater than 1.68Msec is a 1172.{173.IRdata|= bits;174.}175.bits=bits<<1;176.if (!bits)177.{178.IRstate=IR_getdatainv;179.bits=1;180.}181.break;182.case IR_getdatainv:183.TR1=0;184.time=TH1;185.time =(time <<8)+TL1;;186.TL1=0;187.TH1=0;188.TR1=1;189.if ((time>msec_2p5)||(time<msec_0p9)) // if > 2.5mse c or shorter than .9Msec bad data , go to idle190.{191.IRstate=IR_idle;192.break;193.}194.if (time>msec_1p68)// greater than 1.68Msec is a 1 195.{196._IRdata|= bits;197.}198.bits=bits<<1;199.if (!bits) // we have it all , now we make sure it i s a NEC code from the CHS IR transmitter200.{ // make sure address,~address are correc t , data ,~data are correct and address is 0.201.IR_ready=((IRaddr^_IRaddr)==0xff)&&((IRdata^_IRda ta)==0xff)&&(IRaddr==0);202.if(IR_ready)203.{204.IRstate=IR_idle;205.}206.}207.break;208.default:209.IRstate=IR_idle;210.break;211.}212.}213.214.void main(void) 215.{216.cpu_init();217.while(1)218.{219.if(IR_ready)220.{221.IR_ready=0;222.switch(IRdata) 223.{224.case 0x45: //1 225.//your code226.break;227.case 0x44: //3 228.//your code229.break;230.case 0x43: //4 231.//your code232.break;233.case 0x08: //prev 234.//your code235.break;236.case 0x5a: //next 237.//your code238.break;239.default:240.break;241.&n bsp; } 242.}243.}。
#include <reg51.h>#define c(x) (x*120000/120000)sbit Ir_Pin=P3^3;//接红外sbit beep=P3^6;unsigned char code Led_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共阳极数码显示码0-F.unsigned char code Led_Sel[]={0x00,0x01,0x02,0x03};unsigned char Led_Buf[4]; //显示缓冲区char Led_Index;//位选unsigned char Ir_Buf[4]; //用于保存解码结果void delay_50ms(unsigned int t){unsigned int j;for(;t>0;t--)for(j=6245;j>0;j--){;}}//==============================================================//数码管扫描timer0() interrupt 1 using 1{TL0=65536-1000;TH0=(65536-1000)/256; //定时器0设定约1000us中断一次,用于数码管扫描P0=0xff;P2=Led_Sel[Led_Index]; //位选P0=Led_Tab[Led_Buf[Led_Index]]; //段选if(++Led_Index>3) Led_Index=0; //四个扫描完了,到第一个数码管}//============================================================== unsigned int Ir_Get_Low(){TL1=0;TH1=0;TR1=1;while(!Ir_Pin && (TH1&0x80)==0);TR1=0;return TH1*256+TL1;}//============================================================= unsigned int Ir_Get_High(){TL1=0;TH1=0;TR1=1;while(Ir_Pin && (TH1&0x80)==0);TR1=0;return TH1*256+TL1;}//============================================================== main(){unsigned int temp;char i,j;Led_Index=1;TMOD=0x11;TL0=65536-1000;TH0=(65536-1000)/256; //定时器0设定约1000us中断一次,用于数码管扫描EA=1;ET0=1;TR0=1;Led_Buf[0]=0;Led_Buf[1]=0;Led_Buf[2]=0;Led_Buf[3]=0; //显示区设成0do{ restart:while(Ir_Pin);temp=Ir_Get_Low();if(temp<c(8500) || temp>c(9500)) continue;//引导脉冲低电平9000temp=Ir_Get_High();if(temp<c(4000) || temp>c(5000)) continue;//引导脉冲高电平4500for(i=0;i<4;i++) //4个字节for(j=0;j<8;j++) //每个字节8位{temp=Ir_Get_Low();if(temp<c(200) || temp>c(800)) goto restart;temp=Ir_Get_High();if(temp<c(200) || temp>c(2000)) goto restart;Ir_Buf[i]>>=1;if(temp>c(1120)) Ir_Buf[i]|=0x80;}Led_Buf[0]=Ir_Buf[2]&0xf;Led_Buf[1]=(Ir_Buf[2]/16)&0xf;Led_Buf[2]=Ir_Buf[3]&0xf;Led_Buf[3]=(Ir_Buf[3]/16)&0xf; //显示结果P1=Ir_Buf[2];beep=0;delay_50ms(2);beep=1;}while(1);}。
51单片机红外接收解码程序(C51)接收以S52单片机作为接收系统。
以S52的P3.3口作为接收端口,该端口是外部中断1。
这个接受程序是以XC866作为红外发送控制系统,接收程序如下:#include; //头文件#include;#define uchar unsigned char //宏定义#define uint unsigned intsbit HWRx=P3^3; //位声明code uchar Table[]= //共阴数码管 0-9 a-f - 表{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6 f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};uchar Table_Data[8]={0,0,0,0,0,0,0,0};//用于显示的数组uchar Table_Rx[67];//用于存储判断接收是1或0的参数void Delay();//延时子函数void Display(uchar *lp,uchar lc)//显示{uchar i; //定义变量P2=0; //端口2为输出,关闭P1=P1&0xF8; //将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管for(i=0;i;0x7f)P2+=0x80;Delay(); //延时P2=0; //清0端口,准备显示下位if(i==7) //检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据break;P1++; //点亮下一位数码管}}void main() //主函数{EA=1; //首先开启总中断EX1=1; //开启外部中断 1IT1=1; //设置成下降沿触发方式while(1) //一直显示,其它由中断处理{Display(Table_Data,8);}}void Delay() //延时时间大约为31us,晶振12M {uchar i=13;while(i)i--;}void Delay_ms(uint z) //延时时间约为 1ms*X 晶振为12M{uint x=0,y=0;for(x=z;x>;0;x--)for(y=54;y>;0;y--);}void hongwai() interrupt 2 //外部中断 1 ,INT1(P3^3)连接红外线接收IC数据脚{uchar i,j,tmp;EX1=0; //关闭中断j=33; //传送一组数包括引导码1位,4个八位数据,总共33位i=0; //从第一维数组开始Delay_ms(10);if(HWRx){ //然后再检测红线接收脚是有数据招收,有继续,没有则退出EX1=1;return;}while(j--){ //循环接收33位数据,为何我们用到66位数组,我们可以不接收高电平时间常数,只接低电平常数就//可以判断1或0了,在这里我们都接收,还有一点要知道,接收波形是反向,在没有接收时端口为高电平tmp=0;Table_Rx[i]=1; //时间量从1开始while(!HWRx) //检测高低电平的变化,这里检测的是高电平{Table_Rx[i]++; //没变继续加1Delay(); //家一个延时防止,计数值一下子就加满了tmp++; //加1if(tmp==250)break;}i++;tmp=0;Table_Rx[i]=1; //时间量从1开始while(HWRx) //检测高低电平的变化,这里检测的是低电平{Table_Rx[i]++; //没变继续加1Delay(); //同上tmp++; //加1,用于判断是1还是0的,低电平来了if(tmp==250)break;}i++;}P1=0xf8;i=200; //加入循环延时,抗干扰while(i) //在有接收数据的时候显示一个H{tmp=255;while(tmp){tmp--;P2=0x76;}i--;}tmp=0;for(i=3;i;>;=1; //右移一位,接收低位在前if(Table_Rx[i]>;30) //检测低电平时间超过30就确认为1tmp+=0x80;}Table_Data[0]=tmp/16; //分开2位以16进制显示,用显示发送的数据Table_Data[1]=tmp%16;tmp=0;for(i=19;i;>;=1;if(Table_Rx[i]>;30)tmp+=0x80;}Table_Data[2]=tmp/16;Table_Data[3]=tmp%16;tmp=0;for(i=35;i;>;=1;if(Table_Rx[i]>;30)tmp+=0x80;}Table_Data[4]=tmp/16;Table_Data[5]=tmp%16;tmp=0;for(i=51;i;>;=1;if(Table_Rx[i]>;30)tmp+=0x80;}Table_Data[6]=tmp/16;Table_Data[7]=tmp%16;EX1=1; //刚进中断时关闭了分控,现在要打开}。
单片机实现红外接收解码摘要:接收到红外遥控器的脉冲波形,并通过解析其波形得到红外遥控器的相应解码,实习对相应设备的控制。
本文详细接受红外遥控技术原理并如何通过C51单片机实现红外遥控。
关键字:单片机,红外遥控,解码1.引言遥控器相信大家不会陌生,日常生活中会使用到各种各样的遥控器,比如电视机、DVD 机、空调、机顶盒甚至音响、热水器等都用到遥控器,其实红外技术已经走进与人们的生活并且与人们的生活息息相关了。
红外遥控器作为设备的输入控制具有操作简便、价格便宜等诸多好处。
您可以根据您公司产品需要和遥控器提供商协商定制遥控器,包括遥控器键盘布局、每个按键的键码等。
遥控器键盘上每个按键的键码是一个小于256的一个数值,按键后通过遥控器红外管产生脉冲发送出去,红外接收器接收到脉冲后,对脉冲流进行分析,提取键码值,并按照键码值实现其遥控目的。
2.红外接收原理红外遥控信号接收:红外接收电路可以使用集成接收器,接收器包括红外接收管及信号处理IC,接收器对外只有三个引脚,一个接电源的Vcc脚、一个接地的GND脚、一个脉冲信号输出脚,当然脉冲信号输出脚直接接单片机的某个可以使用的IO脚就可以了。
3.脉冲波形分析:每次按键,红外接收器这边会收到一串脉冲宽度不等的脉冲波形流,其脉冲流由35个脉冲波形构成:前导码:第1个脉冲波形用户码1:第2到第9个脉冲波形用户码2:第10到第17个脉冲波形键码:第18到第25个脉冲波形键码反码:第26到第33个脉冲波形连续按键脉冲:第34和第35个脉冲为结束脉冲(也即连续按键脉冲),在每次按键结束后会有两个结束脉冲,如果一直按键不放的话,会一直发送连续按键脉冲,并可以认为在收到10个连续按键脉冲后是下一个按键。
注意:不同的遥控器产生的用户码值可能不一样,笔者碰到两种不同的用户码:0x00,0xFF及0x04,0x7F。
脉冲流中有四种不同的脉冲波形宽度:其中前导码脉宽为:40(4ms) < 脉冲宽度< 50(5ms)连续按键脉宽为: 21(2.1ms) < 脉冲宽度 < 25(2.5ms)bit "0" 脉宽为: 3(0.3ms) < 脉冲宽度 < 7(0.7ms)bit "1" 脉宽为: 14(1.4ms) < 脉冲宽度 < 19(1.9ms)在收到一串脉冲流后,就要对其进行分析,先要检测第一个脉冲波形是不是前导码,如果不是,则继续检测前导码,如果是则检测如下32个脉冲波形:用户码1为1字节,由8个脉冲波形组成(其中一个脉冲波形表示字节中1 bit );用户码2为1字节; 键值为1字节;键值反码为1字节,键值反码为键值取反值。
第1章红外解码系统分析第1节设计要求整个控制系统的设计要求:被控设备的控制实时反应,从接收信号到信号处理及对设备控制反映时间应小于1s;整个系统的抗干扰能力强,防止误动作;整个系统的安装、操作简单,维护方便;成本低。
红外载波、编码电路设计要求:单片机定时器精确产生38KHz红外载波;根据控制系统要求能对红外控制指令信号精确编码并迅速发送。
红外解码电路设计要求:精确接收红外信号,并对所接收信号进行解码、放大、整形、解调等处理,最后输出TTL电平信号;对非红外光及边缘红外光抗干扰能力强。
设备扩展模块设计要求:直流控制交流;抗干扰能力强;反应迅速不产生误动作;能承受大电流冲击。
第2节总体设计方案2.1 方案论证驱动与开关方案一:采用晶闸管直接驱动。
其优点是体积小,电路简单,外围元件少。
但控制电流小,大电流晶闸管成本高,并且隔离性能差。
方案二:采用三极管驱动继电器。
其体积大,外围元件多。
优点是控制电流大,隔离性能好。
根据实际情况,拟采用方案二。
2.2 总体设计框图经过上述方案的分析选择,得出系统硬件由以下几部分组成:电视红外遥控器,51单片机最小系统,接收放大于一体集成红外接收头,1602液晶显示驱动电路。
整体设计思路为:根据扫描到不同的按键值转至相对应的ROM表读取数据。
确认设备及菜单选择键后AT89S2将从ROM读取出来的值,按照数据处理要求从P2.5输出控制脉冲与T0产生的38KHz的载波(周期是26.3μs)进行调制,经NPN三极管对信号放大驱动红外发光管将控制信号发送出去。
红外数据接收则是采用HS0038一体化红外接收头,内部集成红外接收、数据采集、解码的功能,只要在接收端INT0检测头信号低电平的到来,就可完成对整个串行的信号进行分析得出当前控制指令的功能。
然后根据所得的指令去操作相应的用电器件工作,如图1-1所示。
图1-1 电路设计整体框图第2章红外解码硬件电路设计第1节单片机及其硬件电路设计1.1 单片机的介绍AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash 存储器。
最简51单片机红外遥控解码程序(转载)2009-09-07 23:03/* 51单片机红外遥控解码程序 *//* 适用uPD6121系列 *//* 周正华 2008.4.11编 *//* /52_diy */#include <reg52.h>#define DIGPORT P2#define WORDPORT P0unsigned char code LED_num[]={0x3f,0x18,0x76,0x7c,0x59,0x6d,0x6f,0x38,0x7f,0x7d};#define Imax 14000 //此处为晶振为11.0592时的取值,#define Imin 8000 //如用其它频率的晶振时,#define Inum 1450 //要改变相应的取值。
unsigned char Im[]={0x00,0x00,0x00,0x00};unsigned long m,Tc;unsigned char i,IrOK;void DelayMy(unsigned int t){while(--t);}void Display_LED(unsigned long num){unsigned int ii;unsigned int jj=0;unsigned long aa,bb;unsigned int xx[8]={0,0,0,0,0,0,0,0};do{bb=num/10;aa=num-bb*10;xx[jj]=aa;num=bb;jj++;}while(num>0);DIGPORT=0x80;for(ii=0;ii<8;ii++){WORDPORT=LED_num[xx[ii]];DelayMy(60);DIGPORT=DIGPORT>>1;};WORDPORT=0;}//外部中断解码程序void intersvr1(void) interrupt 2 using 1{Tc=TH0*256+TL0; //提取中断时间间隔时长TH0=0; TL0=0; //定时中断重新置零if((Tc>Imin)&&(Tc<Imax)) m=0; //找到启始码if(Tc>Inum) Im[m/8]=Im[m/8]>>1|0x80; else Im[m/8]=Im[m/8]>>1; //取码if(m==32) if((Im[2]|0x01)==~Im[3]) IrOK=1; else IrOK=0; //取码完成后判断读码是否正确m++; //准备读下一码}/*演示主程序*/void main(void){m=0;EA=1;IT1=1;EX1=1;TMOD=0x11;TH0=0;TL0=0;TR0=1;ET0=1;for(;;){DelayMy(100);if(IrOK==1) for(i=0;i<400;i++) Display_LED(Im[2]);IrOK=0;}}。