红外解码与数据保存程序
红外接收解码原理和源程序

上述“0”和“1”构成旳32位二进制码经38kHz旳载频进行二次调制以提升发射效率,到达降低电源功耗旳目旳。然后再经过红外发射二极管产生红外线向空间发射,如图。
UPD6121G产生旳遥控编码是连续旳32位二进制码组,其中前16位为顾客辨认码,能区别不同旳电器设备,预防不同机种遥控码相互干扰。芯片厂商把顾客辨认码固定为十六进制旳一组数;后16位为8位操作码(功能码)及其反码。UPD6121G最多额128种不同组合旳编码。遥控器在按键按下后,周期性地发出同一种32位二进制码,周期约为108ms。一组码本身旳连续时间随它包括旳二进制“0”和“1”旳个数不同而不同,大约在45~63ms之间,图4为发射波形图。当一种键按下超出36ms,振荡器使芯片激活,将发射一组108ms旳编码脉冲,这108ms发射代码由一种起始码(9ms),一种成果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据旳反码(9ms~18ms)构成。假如键按下超出108ms仍未松开,接下来发射旳代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)构成。
注:P3.2接旳是外部中断
红外接受头将38K载波信号过虑,得到与发射代码反向接受代码
发射端旳“0”和“1”
红外解码旳关键就是辨认 0和1
Hale Waihona Puke 1. 解码旳关键是怎样辨认“0”和“1”,从位旳定义我们能够发觉“0”、“1”均以0.56ms旳低电平开始,不同旳是高电平旳宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平旳宽度区别“0”和“1”。假如从0.56ms低电平过后,开始延时,0.56ms后来,若读到旳电平为低,阐明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超出1.12ms,不然假如该位为“0”,读到旳已是下一位旳高电平,所以取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可。
最简单详细的红外解码程序

#include<reg52.h> //包含头文件名sbit IRIN=P3^2; //定义红外接收头的外部接口,即外部中断0sbit BEEP=P1^5; //定义蜂鸣器接口,我的在P1^5unsigned char IRCOM[7]; //定义数组,用来存储红外接收到的数据void delay(unsigned char x){ //延时子程序unsigned char i; //延时约x*0.14mswhile(x--) //不同遥控器应设置不同的参数{for(i=0;i<13;i++){}} //参数的选择咱们先不管,先看这个}void beep(){unsigned char i; //蜂鸣器发声子程序for(i=0;i<100;i++){delay(4); //这个得看你的蜂鸣器内部是否有振荡源BEEP=~BEEP;} //如果没有振荡源就应该输入脉冲信号BEEP=1;}void IR_IN() interrupt 0 using 0 //外部中断0程序{unsigned char j,k,n=0; //先定义变量,记住n=0EX0=0; //禁止中断,以免再次进入中断delay(15); //延时0.14ms*15=2.1msif(IRIN==1) //如果在这期间有高电平说明{ //信号不是来自遥控的,返回主程序EX0=1;return;}while(!IRIN){delay(1);} //死循环,等待9ms前导低电平信号的结束for(j=0;j<4;j++) //一共有4组数据{for(k=0;k<8;k++) //每组数据有8位{while(IRIN){delay(1);} //死循环,等待4.5ms前导高电平的结束while(!IRIN){delay(1);} //等待0.56ms低电平的结束,准备采集数据,while(IRIN) //开始采集数据{delay(1); //延时0.14ms,每过0.14ms时n就加1n++; //用n记录一共有多少个0.14msif(n>=30) //如果超过0.14ms*30=4.2ms{ //说明是乱码,放弃不要EX0=1;return;}}IRCOM[j]=IRCOM[j]>>1; //右移1位,xxxx xxxx变成0xxx xxx//我们先认为这一位数据是0,现在已经送入一位数据了/*你肯定知道_cror_(x,1)和x>>1的区别吧*/if(n>=8){IRCOM[j]=IRCOM[j]|0x80;}//但是如果不是0呢,//0xxx xxxx和0x80相或后变成了1xxx xxxx//这样这一们数据就被记录为1了/*想一下这里为什么是8呢,0.14ms*8=1.12ms,知道了吧*//*这样反复执行8次,8位数据就存在IRCOM[j]中了*//*外层再循环4次,4*8=32位数据码全都在IRCOM[0],IRCOM[1],IRCOM[2],IRCO M[3]中了*/n=0; //n计数后一定要记得清0,否则下一次就不能准确计数了}}if(IRCOM[2]!=~IRCOM[3]) //这里我们判断数据码和数据反码是不是相反{ //因为相反才是正确的,否则就放弃EX0=1;return;}beep();EX0=1; //记得开中断,你可以去掉这句话试一试}void main(){IE=0x81;TCON=0X01;BEEP=1;IRIN=1;while(1);}怎么样,你看懂了吗?作者:任杰。
(完整word版)红外编码解码程序(word文档良心出品)

红外编码解码程序,我写的是:发送模块通过按键,发送出相应键值的编码,接收模块接收到信号后解码该键值,并点亮相应的状态灯(新手,高手勿喷)//************************* 单片机红外发射******************************* #include<reg52.h> sbit ir=P 1人3;sbit k1= P2A5;sbit k2=P2M;sbit k3=P2A3;sbit k4=P2A2;sbit k5=Pil;unsigned int count, set_count; bit irflag,keyflag; unsigned char irsys[]={0x00,0xff}; unsigned char irdata,ircode;void delay(unsigned int a){unsigned char i;while(--a!=0) for(i=300;i>0;i--);}void keyscan(){/*if(k1==0){delay(10);if(k1==0){keyflag=1;while(!k1);irdata=0x01;}*/ if(k2==0) {delay(10); if(k2==0) {keyflag=1;while(!k2); irdata=0x02;}{delay(10); if(k3==0) {keyflag=1;while(!k3); irdata=0x03;} if(k4==0){delay(10); if(k4==0) {keyflag=1;while(!k4); irdata=0x04;} if(k5==0){delay(10); if(k5==0) {keyflag=1;while(!k5); irdata=0x05;void ir_sendbyte() // 红外发送一个字节数据{ unsigned char i; for(i=0;i<8;i++) //发送8 位数据{set_count=43; //发送编码中的0.56ms 高电平irflag=1;count=0;TR0=1; while(count<set_count);TR0=0;if(ircode&0x01) set_count=130; // 判断红外编码最低位,若为 1 则 1.69ms 的低电平else set_count=43; // 为0 则0.565ms 的低电平irflag=0;count=0;TR0=1; while(count<set_count);TR0=0; ircode=ircode>>1;}}void ir_send(){set_count=346; //发送编码中的引导码(4.5ms高电平+4.5ms低电平)irflag=1;count=0;TR0=1;while(count<set_count);set_cou nt=346; //发送编码中的 4.5ms低电平irflag=0;count=0;TR0=1;while(count<set_count);TR0=0; ircode=irsys[0];ir_sendbyte();ircode=irsys[1];ir_sendbyte();ircode=irdata; //发送8 位数据码ir_sendbyte();ircode=~irdata; // 发送8 位数据反码ir_sendbyte();set_count=43; //发送编码中的0.56ms高电平irflag=1;count=0;TR0=1;while(count<set_count);TR0=0;irflag=0;/*delay(23); //延时23ms (编码中的23ms低电平)set_count=346; //发送编码中的引导码(4.5ms高电平+4.5ms低电平) irflag=1;count=0;TR0=1; while(count<set_count);TR0=0; set_count=346; irflag=0;count=0;TR0=1;while(count<set_count);TR0=0;*/ set_count=43;irflag=1;count=0;TR0=1;while(count<set_count);TR0=0;irflag=0;delay(23);}void timer0_init(){EA=1;TMOD=0x02;//定时0 8 位自动重装模式ET0=1;TH0=0xe6; //定时13us,38K 红外矩形波,晶振24M TL0=0xe6; }void main(){timer0_init();count=0;ir=0;irflag=0;while(1){keyscan(); if(keyflag) {delay(10); ir_send(); delay(500); keyflag=0;delay(100);}}}void timer0() interrupt 1 {count++;if(irflag==1)ir=~ir; // 有发射标志,则发射38khz 的矩形波elseir=0;红外接收**************************** //*************************#include<reg52.h>#define uchar unsigned char #define uint unsigned intsbit led仁P2A1;sbit led2=卩2人2;sbit led3=卩2人3;uchar irtime;uchar startflag;uchar irdata[33];uchar bitnum;uchar irreceok;uchar ircode[4]; uchar irprosok;void display();void timer0init(){TMOD=0x02;TH0=0x00;TL0=0x00;ET0=1;EA=1;TR0=1;void int0init(){IT0=1;EX0=1; EA=1;}}void irpros(){uchar k,i,j;uchar value;k=1;for(j=0;j<4;j++){for(i=0;i<8;i++){ value=value>>1; if(irdata[k]>6){value=value | 0x80;}k++;if(k>33)k=1;}ircode[j]=value;}irprosok=1;}void main(){ timer0init(); int0init(); while(1) { if(irreceok) { irpros(); irreceok=0;} display();}void display()switch(ircode[2]){case 0x05:led1=1; led2=1; led3=1; break;case 0x02:led1=0;led2=1; led3=1; break;case 0x03:led2=0; led1=1; led3=1; break;case 0x04:led3=0;led1=1;led2=1; break;//case 0x01: 备用}void timer0 () interrupt 1 { irtime++;}void int0 () interrupt 0 {if(startflag){if(irtime>32) // 检测引导码{bitnum=0;}irdata[bitnum]=irtime;irtime=0;bitnum++;if(bitnum==33){bitnum=0;irreceok=1;startflag=0;}else{startflag=1; irtime=0;}}。
红外解码程序

注:主函数由读者自己编写,本程序只用于解码,最终得出的按键码存于变量Key_Temp中。
本人习惯写某个器件的程序的时候,习惯创建.c和.h文件,因为这样方便移植,在新建的程序中只需添加.C文件和include .h文件就行了,很方便。
本人用芯片是15W4K32S4。
自己用这块芯片做有开发板,平时写程序都用它。
也可用一般的51单片机,但要注意定时器的时间和外部中断的端口头文件(.h文件)#ifndef __IR_H__#define __IR_H__sfr INT_CLKO = 0x8f;sbit IR = P3^6; //外部中断2的端口在P3.6口extern Byte Long_Press;extern Byte Key_Temp;void Init_IR();#endif以下是(.C文件)#include <15W4K32S4.h> //也可以用reg52.h ,一般的编译器没有<15W4K32S4.h>这个头文件,因为这是我个人添加进编译器里面的#include "IR.h"/******************************************************************* 时间计算:时间由定时器计的定时值来决定,本程序设定工作频率是24MHz,但定时器是12T模式。
故一个定时脉冲时间为0.5us。
实际定时所得时间应为((TH0<<8)|TL0)*0.5 ,单位us。
本程序由:河池学院-物电学院-XXX编写,*******************************************************************/bit IR_Error = 0; //超时错误标志,解码过程中,每个高电平或低电平的时间都不会//超时,也就是定时器不会被记满,如若定时器记满,向CPU申请了中断,那便可认//为是解码失败也就无需再等待高电平结束或低电平结束Byte Long_Press; // 长按计数,若用到长按功能Byte Key_Temp;Word IR_table[4];void Init_IR() //初始化函数,初始化定时器和外部中断{INT_CLKO |= 0x10; //使能外部中断2(不固定,用哪个外部中断都行:下降沿触发)AUXR &= 0x7F; //定时器时钟12T模式,此句可以不写,//因为单片机的定时器上电默认是12T,写是为了方便日后了解TMOD = 0x01; //设置定时器0为不可重装模式,从零开始定时TR0 = 0; //定时器不定时,也可不写,上电默认不启动ET0 = 1; //允许定时器中断,解码超时时进入定时器中断,以方便结束解码EA = 1; //打开总中断}void IR_Rec() interrupt 10{Byte IR_cnt;Byte IR_cnt1;Word L_Time; //定义低电平时间Word H_Time; //定义高电平时间INT_CLKO &= 0xEF; //关闭外部中断2TH0 = 0; //清零定时器的值TL0 = 0;TR0 = 1; //开始定时while(!IR&&!IR_Error); //等待低电平结束if(IR_Error)//若计时超过正常红外时间{IR_Error = 0;TR0 = 0; //关闭定时器TH0 = 0;TL0 = 0;INT_CLKO |= 0x10; //使能外部中断2return; //返回:即结束整个中断服务,退出当前中断服务}TR0 = 0; //关闭定时器L_Time = (TH0<<8)|TL0; //获取定时器的值L_Time = L_Time*0.5; //计算出时间TH0 = 0;TL0 = 0;TR0 = 1;while(IR&&!IR_Error); //等待高电平结束if(IR_Error)//若计时超过正常红外时间{IR_Error = 0;TR0 = 0; //关闭定时器TH0 = 0;TL0 = 0;INT_CLKO |= 0x10; //使能外部中断2return;}TR0 = 0;H_Time = (TH0<<8)|TL0;H_Time = H_Time*0.5;if((L_Time>8000)&&(L_Time<10000)&&(H_Time>4000)&&(H_Time<5000))//判断是否为起始码{//若为起始码,则进行解码//一共接收到四个字节,第一个字节为用户码,第二个字节为用户码反码//第三个字节为按键码,第四个字节为按键码的反码//红外遥控是先发低电平,所以接收时候数据是右移,左移或右移,都是自动补零,//故只用判断高电平Long_Press = 0;//长按计数清零for(IR_cnt=0;IR_cnt<4;IR_cnt++){for(IR_cnt1=0;IR_cnt1<8;IR_cnt1++){Key_Temp >>= 1; //先右移一位TH0 = 0;TL0 = 0;TR0 = 1; //启动定时器while(!IR&&!IR_Error); //等待低电平结束if(IR_Error)//若计时超过正常红外时间{IR_Error = 0;TR0 = 0; //关闭定时器TH0 = 0;TL0 = 0;INT_CLKO |= 0x10; //使能外部中断2return;}TR0 = 0; //关闭定时器L_Time = (TH0<<8)|TL0; //获取低电平时间L_Time = L_Time*0.5; //计算时间(us)TH0 = 0; //定时器清零TL0 = 0;TR0 = 1; //启动定时器while(IR&&!IR_Error); //等待高电平结束if(IR_Error)//若计时超过正常红外时间{IR_Error = 0;TR0 = 0; //关闭定时器TH0 = 0;TL0 = 0;INT_CLKO |= 0x10; //使能外部中断2return;}TR0 = 0;H_Time = (TH0<<8)|TL0;H_Time = H_Time*0.5;if((L_Time<220)||(L_Time>700)) //若低电平时间异常{INT_CLKO |= 0x10; //使能外部中断2return; //停止解码}if((H_Time>1400)&&(H_Time<1800)) //若高电平时间在“1”的范围{Key_Temp |= 0x80;}else if((H_Time<200)&&(H_Time>2000)) //若高电平时间异常{INT_CLKO |= 0x10; //使能外部中断2return; //停止解码}}IR_table[IR_cnt] = Key_Temp;}if(((IR_table[0]+IR_table[1])==0xFF)&&((IR_table[2]+IR_table[3])==0xFF))//验证接收到的数据是否正确,原码加反码等于全1,也就是FF{Key_Temp = IR_table[2]; //将存储的按键值赋给Key_Temp,}else Key_Temp = 0; //若验证的数据有误,则赋0}elseif((L_Time>8000)&&(L_Time<10000)&&(H_Time>1950)&&(H_Time<2350)) //长按{Long_Press++; //长按计数}INT_CLKO |= 0x10; //处理完毕,打开外部中断}void Time0() interrupt 1{IR_Error = 1;}。
红外解码程序详解

//此程序为网上下载后修改,要弄懂的话,可以去看看HT6221的时序图。
当然也欢迎在这里留言。
///C51的红外解码程序,可以根据需要自己修改://11.0592Mhz#include<reg51.h>//根据自己的接线来改sbit IRIN = P3^2; //红外接收器数据线sbit led = P3^7; //指示灯//////////////////////////////////////////////定义数组IRCOM,分别装解码后得到的数据//IRCOM[0] 低8位地址码//IRCOM[1] 高8位地址码//IRCOM[2] 8位数据码//IRCOM[3] 8位数据码的反码/////////////////////////////////////////////#define uchar unsigned char#define uint unsigned intuchar IRCOM[4]=0;bit flag=0;/********************/void delay014ms(unsigned char x); //x*0.14MSvoid IR_init(void);void delay014ms(unsigned char x) //x*0.14MS STC10F04延时约0.15MS {unsigned char i;while(x--){for (i = 0; i<125; i++) //13{;}}}/////////////////初始化////////////void IR_init(void){EA=1;EX0=1; //允许总中断中断,使能 INT0 外部中断IT0=1; //触发方式为脉冲负边沿触发IRIN=1; //I/O口初始化}////////////解码过程//////////////void IR_CODE(void) interrupt 0 //在外部中断子程序中解码{unsigned char j,k,N=0;EX0 = 0;delay014ms(15);if (IRIN==1){ EX0 =1;return;} //确认IR信号出现while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
红外解码程序详解

红外遥控解码程序设计——————基于uPD6121红外编码制式红外传感系统是目前应用最为广泛的遥控系统,一个红外遥控系统可分为发射和接收两部分组成,发射端称之为红外遥控器,一般由矩阵键盘,红外编码调制芯片和红外发射管组成;接收端用一体化红外接收头即可,这个东东内置光电放大器和解调部分,信号接收之后一般很微弱须放大后才可解码,为有效发射出去得先托付在载波上所以需经历调制、解调的过程,其实对于发射部分主要工作在于编码,而对于编码方式只有几种主流方式,而目前国内大部分均为uPD6121编码方式(日本NEC公司搞出来的。
),所以我们只须弄清楚这种编码的时序,即可写出万能的红外解码程序,只要是基于这种编码方式的遥控器(家里的电视、空调、电扇遥控器)都可以用该程序来解码(这点也充分证明了C语言的高移植性啊。
)这种编码的格式其实很简单,开头是一个引导码,人家芯片在编码时将其设计成9ms的高电平和4.5ms的低电平,也就是说你必须跳过这段引导码之后才会接收到数据,第一个问题来了:为什么要加这段引导码?因为红外传感是非常容易受到干扰的,如果直接传送数据很可能并非发送端的信号,很可能来自其他辐射,后面设计程序时会遇到这个问题。
所以我们在写程序时在引导码时可以加入检测代码,如果是引导码则继续接收,否则跳出。
第二个问题就是:接收数据时我们用外部中断接收,这是考虑到CPU 的执行效率,如果你在主函数里接收数据,就好比CPU一直在问:你接收到数据没?你接收到没?..很明显不靠谱,和串口通信一样,接收数据用中断这是经验,有利于单片机的执行效率。
第三个要注意的就是红外接收端和编码发送的数据是反向的!这点很重要,我看很多资料没有写明这点,让很多童鞋疑惑不解,也就是说引导码编码时确实是9ms高电平和4.5ms 的低电平,但是到了接收端是9ms的低电平和4.5ms的高电平,所以我们在解码时就得注意引导码高电平出现的顺序。
对于编码格式,引导码后接了4个字节的数据,前两个字节为用户码和用户反码,简单点说就是器件地址;后两字节为操作码和操作反码,就是我们真正需要的数据。
红外遥控解码程序

红外遥控解码程序红外接收头的型号有很多HS0038 VS838等功能⼤致相同,只是引脚封装不同。
红外接收有⼏种统⼀的编码⽅式,采样哪种编码⽅式取决于遥控器使⽤的芯⽚,接收头收到的都是⼀样的。
电视遥控器使⽤的是专⽤集成发射芯⽚来实现遥控码的发射,如东芝TC9012,飞利浦AA3010T等,通常彩电遥控信号的发射,就是将某个按键所对应的控制指令和系统码(由0和1组成的序列),调制在38KHz的载波上,然后经放⼤、驱动红外发射管将信号发射出去。
不同公司的遥控芯⽚,采样的遥控码格式也不⼀样,较普遍的有两种,⼀种NEC标准,⼀种是PHILIPS标准。
NEC标准:遥控载波的频率为38KHz(占空⽐1:3)当某个键按下时,系统⾸先发射⼀个完整的全码,如果按键超过108ms仍未松开,接下来发射的代码(连发代码)将由起始码(9ms)和结束码(2.5ms)组成。
⼀个完整的全码 = 引导码 +⽤户码 +⽤户码 + 数据码 + 数据码 + 数据反码。
其中,引导码⾼电平9ms,低电平4.5ms;系统码8位,数据码8位,共32位;其中前16位为⽤户识别码,能区别不同的红外遥控设备,以防⽌不同的机种遥控码互相⼲扰。
后16位为8位的操作码和8位的操作反码,⽤于核对数据是否接收准确。
收端根据数据码做出应该执⾏上⾯动作的判断。
连发代码是在持续按键时发送的码。
它告知接收端。
某键是在被连续的按着。
NEC标准下的发射码表⽰发射数据0时⽤”0.56ms⾼电平 + 0.565ms低电平 = 1.125ms”表⽰;数据1⽤”⾼电平0.56ms + 1.69ms = 2.25ms”表⽰。
遥控器发射信号:需要注意的是:当⼀体化接收头收到38kHz红外信号时,输出端输出低电平,否则为⾼电平。
所以⼀体化接收头输出的波形和发射波形是反向的PHILIPS标准:载波频率38KHz:没有筒,点按键时,控制码1和0之间切换,若持续按键,则控制码不变。
⼀个全码 = 起始码’11’ +控制码 + ⽤户码 + ⽤户码数据0⽤“低电平1.778ms + ⾼电平1.778ms”表⽰;数据1⽤“⾼电平1.778ms + 低电平1.778ms”表⽰。
红外解码程序

红外解码程序本篇介绍红外解码的原理和程序的写法。
下面来看一下,红外线是如何编码的。
下面来具体说一下,解码的原理,每按一下遥控器的一个按键,遥控器就会发出32个“0”“1”代码(当然是通过高低电平的占空比来判断是0还是1的),具体是0,1是如何编码的上面图片中有介绍,和一个引导码,引导码的作用是告诉处理器,接下来将要开始发送代码,我们在编写程序时,当检测到引导码时,就应该准备接受数据了。
32位代码中的前16位是用户识别码,不同的遥控器不相同,防止互相干扰的,后16是8为数据码,和8位数据反码。
接下来开始介绍如何解码程序的编写。
程序中用到了两个中断,一个是定时器中断,一个是外部中断。
定时器中断用来准确计时,判断接受的代码是0还是1,外部中断用来准确确定定电平到来的时刻,然后开始计时。
/*********************************************************函数功能:红外解码,用八位数码管显示红外线的按键码,便于红外控制测试环境:hot 51学习板编译环境:keil4整理人:张家越QQ:435835181整理时间:2011-04-03************************************************************/#include<reg51.h>#define uchar unsigned char#define uint unsigned intuchar code seg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0 x6f,0x77,0x7c,0x39,0x5E,0x79,0x71 };//0-f的段选码unsigned char code seg_we[]={0,1,2,3,4,5,6,7};uchar irtime,startflag,bitnum,irreceok;uchar irdata[33];uchar irprosok;uchar display[8];uchar ircode[8] ;sbit led1=P0^1;sbit led2=P0^2;/******************************************************************** ****函数功能:延时函数,在数码管显示时使用,不需要很精确********************************************************************* ****/void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}/******************************************************************** ******函数的功能:定时器0的初始化********************************************************************* *****/void timer0init(){TMOD=0x02; //设置定时器工作在方式2TH0=0x00; //TL0=0x00; //设置定时器的初值ET0=1; //开定时器中断TR0=1; // 打开定时器EA=1; //开总中断}/******************************************************************** ****外部中断1的初始化********************************************************************* **/void int1init(){IT1=1; //设置触发方式为上升沿EX1=1; //开外部中断1EA=1; //开总中断}/******************************************************************** **定时器0的功能函数,每中断一次irtime++,用于计时********************************************************************* **/void timer0() interrupt 1{irtime++; //定时器中断一次irtime++,用于计时}/******************************************************************** ***外部中断0的处理函数,每当有低电平数据过来时,中断一次,(使用次中断的前提是,信号线必需接在外部中断0上面,也就是P3^2口),函数功能是,把信号从高低电平变成时间的代码放入irdata【】中********************************************************************* ***/void int1() interrupt 2{if(startflag){if(irtime>32) //一组代码检测完毕{bitnum=0;}irdata[bitnum]=irtime; //把检测到的时间送到数组irdata【】中去irtime=0;bitnum++;if(bitnum==33) //如果检测到bitnum=33,说明32位用户码已经检测完毕{bitnum=0; //将bitnum清零以便重新计数irreceok=1; //接收完毕标志位置一}}else //(此函数先进入else语句,跳过引导码的检测){startflag=1; //将开始标志位置一irtime=0; //设置时间初值为零irreceok=1; //接收完毕标志位置一}}/******************************************************************** *****函数功能:把irdata【】中的时间代码转换成二进制代码存放在ircode【】中********************************************************************* *****/void irpros(){uchar k=1,value,j,i;for(j=0;j<4;j++){for(i=0;i<8;i++){value=value>>1; //右移7次(第一次是00,相当于没有移位)if(irdata[k]>6) //循环8次{value=value|0x80;}k++;}ircode[j]=value;}irprosok=1;}/******************************************************************** ********函数的功能是:将ircode【】中的二进制代码转换成为16进制代码便于在数码管上显示******************************************************************* ********/void irwork(){display[0]=ircode[0]/16;display[1]=ircode[0]%16;display[2]=ircode[1]/16;display[3]=ircode[1]%16;display[4]=ircode[2]/16;display[5]=ircode[2]%16;display[6]=ircode[3]/16;display[7]=ircode[3]%16;}/******************************************************************** ****函数功能:用数码管显示解码结果********************************************************************* ***/void display1(){uchar i;for(i=0;i<8;i++){P2=seg_we[i];P0=seg_du[display[i]];delay_50us(40);}}void main(){timer0init(); //定时器初始化int1init(); //外部中断初始化while(1){if(irreceok) //判断数据接收完毕(数组中存储的是高低电平的时间){irpros(); //执行处理函数,将高低电平时间转化成16进制的0,1代码,存放在数组中irreceok=0; //标志清零}if(irprosok) //处理函数执行完毕,{irwork(); //将存储的16进制代码分离,便于数码管显示irprosok=0; //标志清零}display1();}}//在最后我再分析一下程序的编写思路,便于大家理解,一旦有按键按下,接受管接收到引导码,进入外部中断,并将高低电平的时间放入irdata【】数组中,接受完毕标志位置一,判断接受标志位,为1,进行处理函数,将高低电平转换成16进制数,处理标志位置一,判断处理标志位,为1,执行分离函数,将16进制数分离,便于数码管显示,分离完毕后显示。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/***********************************************************************/
/***********************************************************************/
/************************ ************************/
/************************ 红外遥控C语言程序************************/
/************************ ************************/
/***********************************************************************/
/***********************************************************************/
/***********************************************************************/
//数码管后2位显示机器码,前2位显示键值。
晶振最好用11.0592M,当键值为0xb9的,继电器动作。
/***********************************************************************/
#include <reg51.h>
#include <intrins.h>
void beep();
void SystemInit(void);
void Delay_840us(void);
void Delay_2400us(void);
void LedDisp();
unsigned char GetCode(void);//获得码
void delay(unsigned char loop);
sbit IRIN = P3^2;
sbit BEEP = P1^6;
sbit swch = P1^7;
unsigned char KeyValue;//机器码
unsigned char MaValue;//键值码;
//unsigned char disbuf[4];//数码管显示缓冲
unsigned int kcode;
//unsigned char scan[4]={0x04,0x08,0x10,0x20};//p2位选择
unsigned char code table[16] =//共陰碼
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7C,0x39,0x5E,0x79,0x71};
void beep()//蜂鸣器
{
unsigned char i;
for (i=0;i<100;i++)
delay(5);
BEEP=~BEEP;
}
BEEP=0;
}
void delay(unsigned char loop) //us延时
{ unsigned char i;
for(i=0;i<loop;i++);
}
void Delay_840us(void)
{ TL1=-774;
TH1=((-774)>>8);
TR1=1;
while(!TF1);
TF1=0;
TR1=0;
}
void Delay_2400us(void)
{ TL1=-2212;
TH1=((-2212)>>8);
TR1=1;
while(!TF1);
TF1=0;
TR1=0;
}
void SystemInit(void)
{//P1=0xff;
IRIN=1;
BEEP=1;
IE=0x81; //使能INT0 EX0=1;
IT0=1; //INT0负跳变触发
TMOD=0x10; //定时器1工作在方式1 EA=1;
EX0=1;
}
unsigned char GetCode()//读码:
{ unsigned char n;
static temp=0;
for(n=0;n<8;n++)
{ while(!IRIN);
Delay_840us();
if(IRIN) //0
{ temp=(0x80|(temp>>1));
while(IRIN);
}
else temp=(0x00|(temp>>1));//1
}
return temp;
}
void LedDisp()
{
P0=table[kcode];
P2=0x80;
delay(50);
P0=0x00;
}
void main(void)
{
SystemInit();
BEEP =0;
while(1)
{ //以下是查表显示
//disbuf[0]=(((KeyValue&0xf0)>>4)&0x0f);
//disbuf[1]=KeyValue&0x0f;
//disbuf[2]=(((MaV alue&0xf0)>>4)&0x0f);
//disbuf[3]=MaValue&0x0f;
//KeyValue=KeyValue&0xff;
switch(KeyValue)
{
case 0xe8:kcode=1;break;
case 0xe9:kcode=2;break;
case 0xf9:kcode=3;break;
case 0xf5:kcode=4;break;
case 0xfc:kcode=5;break;
case 0xf8:kcode=6;break;
case 0xed:kcode=7;break;
case 0xa8:kcode=8;break;
case 0xfd:kcode=9;break;
case 0xba:kcode=10;break;
case 0xec:kcode=11;break;
case 0xab:kcode=12;break;
}
LedDisp();
}
}
void int0_irq(void) interrupt 0
{
unsigned char n;
unsigned char Count=0;
unsigned char addrl,addrh,num1,num2;
EA=0;
for(n=10;n>0;n--) //检测9ms开始码{ Delay_840us();
if(IRIN)
{ Count++;
break;
}
}
if(Count)
{ //KeyValue=Count;
EA=1;
return;
}
while(!IRIN);
Delay_2400us(); //4.5ms结果码if(!IRIN)
{EA=1;return;}
Delay_2400us();
addrl=GetCode();
addrh=GetCode();
num1=GetCode();
num2=GetCode();
if(num1!=~num2)//错码;
{ KeyValue=14;
EA=1;
return;
}
KeyValue=num2;
MaV alue=addrh;
beep();
EA=1;
}。