单片机红外电视遥控器C51程序代码单片机程序
- 格式:doc
- 大小:43.50 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的前导低电平信号。
请勿转载!!!作品功能简介:当学习键按下后,红外接收头便可将接受到的信号存储到单片机中。
在接受到通用遥控器发出的信号后,如果按下发射键,单片机将调出刚刚储存的信息,通过红外发射头发射出和遥控器一样的信号来达到控制的作用。
#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit studylamp=P2^7;sbit lamp=P2^6;sbit studykey=P3^2;sbit remotein=P1^1;sbit remoteout=P1^0;sbit txkey=P2^0;uint i,j,m=255,n,k,s;uchar idata remotedata[206];uint head;uint remdata;//一毫秒延时程序delay1ms(uint t){for(i=0;i<t;i++)for(i=0;j<120;j++);}//初始化函数clearmen(){studylamp=1;lamp=1;remoteout=0;remotein=1;for(i=0;i<206;i++){remotedata[i]=0x00;}IE=0x00;IP=0x01;TMOD=0x22;PCON=0X00;TH1=0xf3;TL1=0xf3;IT0=1;EX0=1;EA=1;}//键功能函数void key_tx(){if(txkey==0){delay1ms(1);if(txkey==0){while(txkey==0);ET1=1;TR1=1;for(i=head;i>0;i--);remoteout=0;ET1=0;TR1=0;n=0;while(1){lamp=0;studylamp=1;if(remotedata[n]==0x00){delay1ms(10);break;}for(i=remotedata[n];i>0;i--){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}n++;ET1=1;TR1=1;for(i=remotedata[n];i>0;i--);remoteout=0;ET1=0;TR1=0;n++;}}}}//主函数void main(){clearmen(); //初始化while(1){key_tx(); //按键扫描}}//40KHz发生器void time_intt1(void) interrupt 3{remoteout=~remoteout;}//外中断0void intt0(void) interrupt 0{ET1=0;TR1=0;EX0=0;EA=0;head=0;while(studykey==0);studylamp=0;lamp=1;while(remotein==1);head=0;while(remotein==0){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();head++;}n=0;remdata=0x0000;while(1){while(remotein==1){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();remdata++;}if(remdata>m) //高电平>5毫秒退出 {remotedata[n]=0x00;EX0=1;EA=1;goto end;}remotedata[n]=remdata;n++;remdata=0x0000;while(remotein==0){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();remdata++;}remotedata[n]=remdata;n++;remdata=0x00;}end: lamp=0;studylamp=0;}电路:实物:2009-06-25 12:39。
学习型红外线遥控程序——C51学习型红外线遥控程序——C51/*************晶体为11.0592M,波特率9600bps***************学习型红外线遥控程序*******/#include <AT89X51.H>void Ewen(void);void Ewds(void);void Delay(void);void Irda(void);void Study(void);void Output(unsigned int h);void Comput(unsigned char outdata);void Erase(unsigned char Address);unsigned int Read(unsigned char Address);unsigned char Display(unsigned char inAddress);void Write(unsigned char Address,unsigned int InData);unsigned int Both(unsigned char data1,unsigned char data2);unsigned char data e1 _at_ 0x1A; //分别存放红外线译码后的数据unsigned char data w1 _at_ 0x1B;unsigned char data e2 _at_ 0x1C;unsigned char data w2 _at_ 0x1D;sbit IrInput=P3^2; //红外线输入引脚,可自定义sbit Study1=P3^6; //学习按键,可自定义sbit Led2=P2^5; //接收成功、学习成功指示sbit Led1=P2^6; //空闲指示sbit Dout=P2^3; //at93c16--DOsbit Din=P2^2; //at93c16--DIsbit sk=P2^1; //at93c16--SKsbit cs=P2^0; //at93c16--CS/*********************主程序***************************/ void main(void){unsigned int i;SCON = 0x50; //串口方式1,允许接收TMOD = 0x20; //定时器1定时方式2TH1 = 0xFD; //波特率9600TL1 = 0xFD;IT0 = 1; //INT0下降沿有效EX0 = 1; //开INT0中断;TR1 = 1; //启动定时器P2_7=0; //初始化引脚P1=0xff;EA = 1; //允许CPU中断while(1){for (i=0; i<20000; i++){ Led1=1;if(!Study1) Study();}for (i=0; i<20000; i++){ Led1=0;if(!Study1) Study();}}}/***********************串口输出**********************/ void Comput(unsigned char outdata){SBUF = outdata;while(!TI);TI = 0;}/*******************红外线查询子程序*******************/ void Irda(void){#pragma asmMOV R6,#10SB:MOV R4,#19 ;延时880微秒D1:MOV R5,#19DJNZ R5,$DJNZ R4,D1JB P3.2,EXIT ;延时882微秒后判断P3.2脚是为1DJNZ R6, SB ;在8820微秒内如P3.2为1就退出JNB P3.2, $ ;等待高电平避开9毫秒低电平引导脉冲MOV R4,#10 ;延时4740微秒D2: MOV R5,#218DJNZ R5,$DJNZ R4,D2;延时4.74毫秒避开4.5毫秒的结果码MOV R1,#1AH ;设定1AH为起始RAM区MOV R2,#4 ;接收从1AH到1DH,用于存放操作码和操作反码PP:MOV R3,#8 ;每组数据为8位SS:JNB P3.2,$ ;等待地址码第一位的高电平信号MOV R4,#19 ;延时880微秒D5:MOV R5,#19DJNZ R5,$DJNZ R4,D5;高电平开始后882微秒判断信号的高低电平MOV C,P3.2 ;将P3.2引脚此时的电平状态0或1存入C中JNC TT ;如果为0就跳转到TTMOV R4,#2 ;延时1000微秒D6:MOV R5,#248DJNZ R5,$DJNZ R4,D6;检测到高电平1的话延时1毫秒等待脉冲高电平结束TT:MOV A,@R1 ;将R1中地址的给ARRC A ;将C中的值0或1移入A中的最低位MOV @R1,A ;DJNZ R3,SS ;接收满8位换一个内存INC R1 ;对R1中的值加1,换下一个RAMDJNZ R2,PP ;接收完所有数据EXIT:#pragma endasm}。
//51单片机做的红外遥控实验(C语言)#include<reg51.h>#define u8 unsigned char#define u16 unsigned int#define ID 0x00 //本遥控器的ID号sbit ir=P3^3;code u8 seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0-9的段码code u8 s[]={1,0x40,0x48,0x04,0x02,0x05,0x54,0x0A,0x1E,0x0E}; u8 buf[4];bit ir_f=0;u8 nu;void delay(u16 x){while(x--);}void show(u16 x){u8 i=0,k=0;u8 s[4];kk:s[i]=x%10;if((x/10)>=1){x=x/10;i++;goto kk;}k=i+1;for(i=0;i<k;i++){P0=seg[s[i]];P2=~(8>>i);delay(300);P0=0XFF;P2=0XFF;}}void timer0_init(){TH0=0;TL0=0;TMOD|=0x01;TR0=0;}u16 low_test(){u16 t;TR0=1;while((ir==0)&&((TH0&0X80)!=0X80));TR0=0;t=TH0;t<<=8;t|=TL0;TH0=0;TL0=0; //t=(TH*256+TL0);//机器周期数return t;}u16 high_test(){u16 t;TR0=1;while((ir==1)&&((TH0&0X80)!=0X80));TR0=0;t=TH0;t<<=8;t|=TL0;TH0=0;TL0=0;return t;}/*u16 time_test(bit x){}*/u8 receive_8bit(){u8 d,i;u16 t;for(i=0;i<8;i++){t=low_test();t=high_test();d>>=1;if((t>=2750)&&(t<=3100)){d|=0x80;}}return d;}void ir_decode(){u16 t;u8 i;if(ir==0)//有遥控信号{t=low_test();//8295-9000us,倍频的是16590-18000if((t>=14500)&&(t<=18000))//检查引导码低电平时间{t=high_test();if((t>=8000)&&(t<=9000))//检查高电平{for(i=0;i<4;i++){buf[i]=receive_8bit();}if(buf[0]==(~buf[1]))//检查系统码是否正确{if(buf[0]==ID){if(buf[2]==(~buf[3])){//具体按键处理ir_f=1; //遥控有效}}}}}}}/*void key(){if(buf[2]==0x40){P1^=(1<<0);}if(buf[2]==0x48){P1^=(1<<1);}}*/void ir_execuse(){if(ir_f==1){switch(buf[2]){case 0x40:P1^=(1<<0);break;case 0x48:P1^=(1<<1);break;case 0x04:P1^=(1<<2);break;case 0x02:P1^=(1<<3);break;case 0x05:P1^=(1<<4);break;case 0x54:P1^=(1<<5);break;case 0x0A:P1^=(1<<6);break;case 0x1E:P1^=(1<<7);break;}ir_f=0;}}void show_d(){u8 j;for(j=0;j<10;j++){if(s[j]==buf[2]){nu=j;break;}}show(nu);}void isr_init(){EA=1;EX1=1;//外部中断,一直看3.3有没有下降沿。
本程序只适用于本图所显示的遥控器以及stc12c5a60s2的单片机并且晶振是11.0592M的:
使用方法:
软件上将下列.c和.h加入c51工程,在主程序运行前加入红外初始化ini_hw()函数,然后运行程序的时候,如果signal=1,代表接收到按下的按键,用完后注意清零。
读key就是红外按键的值(1,2,3······代表按键依次的按键值),读kr就是按键的键值。
硬件上,把接收头的put接单片机的外部中断的P3^2上。
下面是.h文件
#ifndef _hwcl_h_ //红外处理,用于处理红外键值
#define _hwcl_h_
#include<STC12C5A60S2.H>
#include<intrins.h>
#define I 10
sbit js=P3^2;
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
extern uint key,kr; //key和kr都是键值,但kr是红外码二进制转换过来的,而key 是处理过的键值变成如1,2,3
extern uint signal; //当按键检测到时,signal值是1
extern uchar pdata b[40];
extern void ini_hw();
#endif。
下面把这次红外编程的解码的经历简要的写一下,以便以后回顾总结:红外遥控过程是这样的:红外遥控器的矩阵键盘按键,接着专用芯片编码调制然后红外发射;红外接受头经过光电放大,解调,最后解码编程。
我的遥控专用芯片是UPD6122G-001.解码晶振是455kHz,调制载波频率是455kHz/12=38kHz。
此外调制信号是PWM进行调制的,0是脉冲波形位0.5625ms的高电平跟0.5625ms的低电平组成,1则是0.5625ms的高电平跟1.6785ms的低电平组成。
跟其他通用的波形一样,有键按下时,先是9ms的高电平的起始码,接着是一个4.5ms结果码,接下来就是数据了。
用户码的高8位,用户码的低8位,8位数据码,8位数据反码,最后还有一个停止位。
如果按键一直没松,则接下来就只是发送起始码(9ms高电平),接着是一个2.2ms的低电平,再接着是一个停止位。
我的红外接在单片机p3.7引脚上面,从网上收集了一些程序,基本上如同一则,汇编编写,跟外部中断还有关系。
于是便萌生了自己写一下的想法。
我的思路是用定时器进行计数,然后编程。
刚开始编写程序是,由于忘了对定时器的标志位进行置为,结果定时中断根本就没有执行,手头上又没有用仿真芯片,搞得我下载调试了十来次才发现了这个问题。
还有一个问题刚开始遥控能够解码的时候,可是一直按某个键,你按一次,她就变化一次,搞得我很是郁闷,差点儿没晕过去。
怎么找都不知道问题的所在,心里不断地打算放弃,不过最后还是坚持了下来,原来电路的实际解码电平跟资料上是相反的。
遥控器的实际电平由高变低,而电路板上却是由低变高。
这点确好相反。
总结:一要自信,二要坚持,才有可能完成你想做的事件。
#include"reg51.h"#include"2-16.h"#include"address.h"//需要显示的信息uchar code hello[] = "Hello,PengSen!";//变量uchar data psCount; //定时器计数器uchar data i;uchar data j;uchar data temp;uchar data dp[4]; //用来保存红外遥控的码值uchar data dp2[12];//用来显示红外遥控的码值sbit HW = P3^7;void delay(unsigned int y);void main(){//初始化initlcd();dp[0] = 0x0;dp[1] = 0x0;dp[2] = 0x0;dp[3] = 0x0;TMOD = 0x11; // 定时器0, 1工作模式1, 16位定时方式TH1 = 0xfe; //定时500uSTL1 = 0x33;TCON = 0x01;IE = 0x80;TR1 = 1;printf(hello,13);while(1){//报文头ET1 = 0;psCount = 0;while(HW == 1); //初始状态下,红外输出脚一直是高电平,等待遥控按键ET1 = 1;while(HW == 0);if( psCount > 17)//0.5* 17 = 8.5ms约为9.0ms{ET1 = 0;psCount = 0;ET1 = 1;while(HW == 1);if(psCount > 5)//超过0.5*5 = 2.5毫米,检查一下遥控命令是不是连发,不是则执行下面的程序{ET1 = 0;psCount = 0;dp[0] = 0x0;dp[1] = 0x0;dp[2] = 0x0;dp[3] = 0x0;//数据for(i = 0 ; i < 4; i++){for(j = 0; j < 8; j++){while(HW == 0);ET1 = 0;psCount = 0;ET1 = 1;while(HW == 1);if(psCount > 2)//根据波形长度判定码值为0或1temp = 0;elsetemp = 1;dp[i] |= (temp<<j);//保存键值}}}}//停止位while(HW == 1);//数据显示delay(20);dp2[0] = dp[0]/100 + 0x30;dp2[1] = dp[0]%100/10 + 0x30;dp2[2] = dp[0]%10 + 0x30;dp2[3] = dp[1]/100 + 0x30;dp2[4] = dp[1]%100/10 + 0x30;dp2[5] = dp[1]%10 + 0x30;dp2[6] = dp[2]/100 + 0x30;dp2[7] = dp[2]%100/10 + 0x30; dp2[8] = dp[2]%10 + 0x30;dp2[9] = dp[3]/100 + 0x30;dp2[10] = dp[3]%100/10 + 0x30; dp2[11] = dp[3]%10 + 0x30;printf(dp2,12);delay(20);}}//延时子程序void delay(unsigned int y){uchar x;for(;y!=0;y--)for(x=200;x!=0;x--); }//定时器1中断void timer1() interrupt 3{psCount++;TH1 = 0xfe; //定时500uSTL1 = 0x33;}。
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.}。
c51学习型红外遥控器程序#include; //装入AT89X51头文件#include;//装入红外解码程序#include;//装入24c02读写程序sbit key=P1^0;//定义按键IOsbit led=P0^0; //定义指示ledsbit rel=P0^1;//定义输出控制脚unsigned char kaver; //定义kaver为输出口状态缓存unsigned char iccdate,irdate; //定义24c02数据和解码数据//延时10ms函数,用于开关消抖等delay10ms(){unsigned char i,j;for(i=20;i>;0;i--)for(j=248;j>;0;j--);}//学习红外解码并写入24c02的函数study(){IR_IN();irdate=IRCOM[3];iccdate=ReadIIC(W_cmd,0x00,R_cmd);if(irdate!=iccdate) //只在解码结果与读取结果不同时写入24C02{if(irdate!=0)//防止没有接收到红外信号,IRCOM[3]置零时,误写入0{WP=0;WriIIC(W_cmd,0x00,irdate);delay10ms();WP=1;led=0;while(key==0);//学习成功等待按键释放,led停止闪动作为指示}}}//进入学习状态时的led闪动函数flash(){unsigned char i;while(key==0){led=~led;for(i=50;i>;0;i--)study();}}//按键模式识别函数keymod(){unsigned char m=0;while(key==0) //如果按键按下,开始对按键时间进行计数{delay10ms();//计数时间延时m++;delay10ms();//计数时间延时if(m>;=90)//如果计数次数大于90次,等于按键按下时间大于约5秒后,进入led闪动学习模式{m=0;flash();}}if(m。
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; //刚进中断时关闭了分控,现在要打开}。
红外遥控解解码程序#include <reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P1^0;sbit rs=P1^2;sbit ir=P3^2;sbit led=P1^3;sbit led2=P3^7;unsigned int LowTime,HighTime,x;unsigned char a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;unsigned char flag;//中断进入标志位uchar z[4];uchar code table[]={"husidonghahahah"};uchar code table1[]={"User Code:"};void delay(uint x){uint i,j;for(i=x;i>0;i--) //i=xms即延时约xms毫秒for(j=100;j>0;j--);}void write_com(uchar com){//写液晶命令函数rs=0;lcden=0;P2=com;delay(3);lcden=1;delay(3);lcden=0;}void write_date(uchar date){//写液晶数据函数rs=1;lcden=0;P2=date;delay(3);lcden=1;delay(3);lcden=0;}void init_anjian() //初始化按键{a=0;b=0;c=0;d=0;e=0;f=0;g=0;h=0;i=0;j=0;k=0;l=0;m=0;n=0;o=0;p=0;q=0;r=0;s=0;t=0;u=0;}void init_1602(){//初始化函数uchar num;lcden=0;rs=0;write_com(0x38);//1602液晶初始化write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<14;num++)//写入液晶固定部分显示{write_date(table[num]);delay(3);}write_com(0x80+0x40);for(num=0;num<9;num++){write_date(table1[num]);delay(3);}}void write_dianya(uchar add,char date){//1602液晶刷新时分秒函数4为时,7为分,10为秒char shi,ge;shi=date%100/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void dingshiqi() //定时器记高低电平时间{TH0=0; //定时器高八位置0TL0=0; //定时器低八位置0TR0=1; //开启定时器0while(ir==0); //如果是低电平就等待,给低电平计时TR0=0; //关闭定时器T0LowTime=TH0*256+TL0; //保存低电平时间TH0=0; //定时器高八位置0TL0=0; //定时器低八位置0TR0=1; //开启定时器0while(ir==1); //如果是高电平就等待,给引导码高电平计时TR0=0; //关闭定时器T0HighTime=TH0*256+TL0; //保存高电平长度}void main(){char i=0;TMOD=0x01; //定时器T0作为定时模式ET0=1; //开T0中断IT0=0; //外部中断,下降沿触发EX0=1; //开外部中断EA=1; //开总中断init_1602();while(1){}}void inter0() interrupt 0 //开始解码{EX0=0; //关闭外部中断0,不再接受红外信号,只解码当前的红外信号。
用AT89S51单片机制作红外电视遥控器一般红外电视遥控器的输出都是用编码后串行数据对38~40kHz的方波进行脉冲幅度调制而产生的。
当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。
这种遥控码具有以下特征:采用脉宽调制的串行码,以脉宽为、间隔、周期为的组合表示二进制的“0”;以脉宽为、间隔、周期为的组合表示二进制的“1”。
上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制,然后再通过红外发射二极管产生红外线向空间发射。
一般电视遥控器的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。
后16位为8位的操作码和8位的操作反码,用于核对数据是否接收准确。
根据红外编码的格式,发送数据前需要先发送9ms的起始码和的结果码。
遥控串行数据编码波形如下图所示:接收方一般使用TL0038一体化红外线接收器进行接收解码,当TL0038接收到38kHz红外信号时,输出端输出低电平,否则为高电平。
所以红外遥控器发送红外信号时,参考上面遥控串行数据编码波形图,在低电平处发送38kHz红外信号,高电平处则不发送红外信号。
单片机红外电视遥控器电路图如下:C51程序代码:#include <>static bit OP; //红外发射管的亮灭static unsigned int count; //延时计数器static unsigned int endcount; //终止延时计数static unsigned char flag; //红外发送标志char iraddr1; //十六位地址的第一个字节char iraddr2; //十六位地址的第二个字节void SendIRdata(char p_irdata);void delay();void main(void){count = 0;flag = 0;OP = 0;P3_4 = 0;EA = 1; //允许CPU中断TMOD = 0x11; //设定时器0和1为16位模式1 ET0 = 1; //定时器0中断允许TH0 = 0xFF;TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次TR0 = 1;//开始计数iraddr1=3;iraddr2=252;do{delay();SendIRdata(12);}while(1);}//定时器0中断处理void timeint(void) interrupt 1{TH0=0xFF;TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次count++;if (flag==1){OP=~OP;}else{OP = 0;}P3_4 = OP;}void SendIRdata(char p_irdata){int i;char irdata=p_irdata;//发送9ms的起始码endcount=223;flag=1;count=0;do{}while(count<endcount);//发送的结果码endcount=117flag=0;count=0;do{}while(count<endcount);//发送十六位地址的前八位irdata=iraddr1;{//先发送的38KHZ红外波(即编码中的低电平)endcount=10;flag=1;count=0;do{}while(count<endcount);//停止发送红外信号(即编码中的高电平)if(irdata-(irdata/2)*2) //判断二进制数个位为1还是0 {endcount=41; //1为宽的高电平}else{endcount=15; //0为窄的高电平}flag=0;count=0;do{}while(count<endcount);irdata=irdata>>1;}//发送十六位地址的后八位irdata=iraddr2;for(i=0;i<8;i++){endcount=10;flag=1;count=0;do{}while(count<endcount);if(irdata-(irdata/2)*2){endcount=41;}else{endcount=15;}flag=0;count=0;do{}while(count<endcount);irdata=irdata>>1;}//发送八位数据irdata=p_irdata;{endcount=10;flag=1;count=0;do{}while(count<endcount);if(irdata-(irdata/2)*2){endcount=41;}else{endcount=15;}flag=0;count=0;do{}while(count<endcount);irdata=irdata>>1;}//发送八位数据的反码irdata=~p_irdata;for(i=0;i<8;i++){endcount=10;flag=1;count=0;do{}while(count<endcount);if(irdata-(irdata/2)*2){endcount=41;}else{endcount=15;}flag=0;count=0;do{}while(count<endcount);irdata=irdata>>1;}endcount=10;flag=1;count=0;do{}while(count<endcount);flag=0;}void delay(){int i,j;for(i=0;i<400;i++){for(j=0;j<100;j++){}}}制作的实物如下图所示:步进电机#include<>#define uint unsigned int#define uchar unsigned char#define ms *77// f = 12 M#define LEDLen 4#define Dj_star() {IE=0x81; pri_dj=0; }#define Dj_stop() {IE=0x00; pri_dj=1; P1=0xff; shache="0"; delay(800ms); delay(800ms);delay(400ms); shache = 1; }#define Chilun_Num 8/* 齿轮数8 个*/#define set_display_num() { LEDBuf[0] = tmp / 1000; LEDBuf[1] = tmp / 100 % 10; \LEDBuf[2] = tmp / 10 % 10; LEDBuf[3] = tmp % 10; } uchar LEDBuf[LEDLen] = {0,0,0,0};void read_num (); /* 读播码盘到set_round_num * 8 */void display ();void delay(uint delay_time) { uint i; for (i=0; i < delay_time ; i++) ; }void run ();void fx_run();uint round_num = 0; /* 记录已转的齿轮数, 中断1次加1*/uint set_round_num = 0; /* 播码盘设置圈数*/uint set_pwm_width = 0; /* 播码盘设置步进电机正向速度*/bit one_round_flg = 0;sbit led_1000 = P0^7; //use for displaysbit led_100 = P0^6; //use for displaysbit led_10 = P0^5; //use for displaysbit led_1 = P0^4; //use for displaysbit key_start = P3^0;sbit key_puse = P3^0;sbit key_clear = P3^1;/* P3^2 接齿轮传感器中断*/sbit bujin_zx_stop = P3^3; /* 接步进电机,正向到位传感器,为0 停机*/sbit bujin_fx_stop = P3^4; /* 接步进电机,反向到位传感器,为0 停机*/sbit shache = P3^5; /* 接刹车控制继电器0 电位有效*/sbit pri_dj = P3^6; /* 接主电机控制继电器0 电位有效*/void main(){TCON = 0x01;display();while(1) {IE="0x00";round_num = 0;display();if ( bujin_fx_stop ) fx_run();while ( key_start );delay ( 8ms );if(!key_start){read_num();//set_round_num = 8;while ( !key_start );run ();fx_run();}}}void run () {#define Delay_time 180/* 转一圈50 次循环,每循环4 步,50 * 4 = 200 ,200 * 1。
单片机红外电视遥控器C51程序代码单片机程序
//**************************************************************
//名称:单片机红外电视遥控器C51程序代码()
/*--------------------------------------------------------------
描述:
一般红外电视遥控器的输出都是用编码后串行数据对38~40kHz的方波进行
脉冲幅度调制而产生的.当发射器按键按下后,即有遥控码发出,所按的键
不同遥控编码也不同。
这种遥控码具有以下特征:
采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms
的组合表示二进制的“1”。
上述“0”和“1”组成的32位二进制码经38kHz
的载频进行二次调制,然后再通过红外发射二极管产生红外线向空间发射。
一般电视遥控器的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。
后16位
为8位的操作码和8位的操作反码,用于核对数据是否接收准确。
根据红外编码的格式,发送数据前需要先发送9ms的起始码和4.5ms的结果码。
接收方一般使用TL0038一体化红外线接收器进行接收解码,当TL0038接收到38kHz红外信号时,输出端输出低电平,否则为高电平。
所以红外遥控器发送红外信号时,参考上面遥控串行数据编码波形图,在低
电平处发送38kHz红外信号,高电平处则不发送红外信号。
----------------------------------------------------------------*/
//编辑:
//日期:
//****************************************************************
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
#include <reg51.h> //包括一个51标准内核的头文件
static bit OP; //红外发射管的亮灭
static unsigned int count; //延时计数器
static unsigned int endcount; //终止延时计数
static unsigned char flag; //红外发送标志
char iraddr1; //十六位地址的第一个字节
char iraddr2; //十六位地址的第二个字节
void SendIRdata(char p_irdata);
void delay();
//**************************************************************
void main(void)
{
count=0;
flag=0;
OP=0;
P3_4=0;
EA = 1; //允许CPU中断
TMOD = 0x11; //设定时器0和1为16位模式1
ET0 = 1; //定时器0中断允许
TH0 = 0xFF;
TL0 = 0xE6; //设定时值0为38K 也就是每隔26us中断一次
TR0 = 1; //开始计数
iraddr1=3;
iraddr2=252;
do{
delay();
SendIRdata(12);
}
while(1);
}
//**************************************************************
//定时器0中断处理
void timeint(void) interrupt 1
{
TH0=0xFF;
TL0=0xE6; //设定时值为38K 也就是每隔26us中断一次count++;
if (flag==1)
{OP=~OP;}
else
{OP = 0;}
P3_4 = OP;
}
//**************************************************************
void SendIRdata(char p_irdata)
{
int i;
char irdata=p_irdata;
//发送9ms的起始码
endcount=223;
flag=1;
count=0;
do{}while(count)
//发送4.5ms的结果码
endcount=117;
flag=0;
count=0;
do{}while(count)
//----------------------发送十六位地址的前八位-------------------
irdata=iraddr1;
for(i=0;i<8;i++)
{
//先发送0.56ms的38KHZ红外波endcount=10; //(即编码中0.56ms的低电平)
flag=1;
count=0;
do{}while(count)
//停止发送红外信号(即编码中的高电平)if(irdata-(irdata/2)*2) //判断二进制数个位为1还是0
{ endcount=41; //1为宽的高电平
}
else
{ endcount=15; //0为窄的高电平
}
flag=0;
count=0;
do{}while(count)
irdata=irdata>>1;
}
//-----------------------发送十六位地址的后八位-------------------
irdata=iraddr2;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count)
if(irdata-(irdata/2)*2)
{endcount=41;}
else
{endcount=15;}
flag=0;
count=0;
do{}while(count)
irdata=irdata>>1;
}
//-----------------------发送八位数据------------------------------
irdata=p_irdata;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count)
if(irdata-(irdata/2)*2)
{endcount=41;}
else
{ endcount=15;}
flag=0;
count=0;
do{}while(count)
irdata=irdata>>1;
}
//-------------------------发送八位数据的反码----------------------
irdata=~p_irdata;
for(i=0;i<8;i++)
{
endcount=10;
flag=1;
count=0;
do{}while(count)
if(irdata-(irdata/2)*2)
{endcount=41;}
else
{endcount=15;}
flag=0;
count=0;
do{}while(count)
irdata=irdata>>1;
}
endcount=10;
flag=1;
count=0;
do{}while(count) flag=0;
}
//**************************************************************
void delay()
{
int i,j;
for(i=0;i<400;i++)
{
for(j=0;j<100;j++) { };
}
}。