本文是基于单片机红外通讯的代码,代码分为发射板代码和接收板代码。
指令码是用户发给接收系统的指令,用以控制设备完成相应的操作。
指令码是一串数据流,其构成如图3-2。
一个完整的指令码由10ms高平引导码、3ms低平开始码、1ms脉宽正脉冲、3ms低平结束码、下一个10ms高平引导码组成。
其中引导码、开始码和结束码都是为了系统能够正确接受信号而设置的,能够判断信号是否有效、信号起始和结束。
信号中的脉冲个数才是我们指令码的指令所在,不同的脉冲个数对应不同的指令。
图3-2 指令码的组成3.3 红外遥控发射系统的设计红外遥控发射部分系统框图见图3-3。
发送端采用单片机的定时中断功能,由定时器T1产生周期为26us 的矩形脉冲,即每隔13us定时器T1产生中断输出一个相反的信号使单片机输出端产生周期为38KHz的脉冲信号。
系统通过连着单片机的按键获取用户遥控指令码,经按键扫描确认,然后交由单片机编码生成信息码,再由红外发射二极管将信息码发射出去。
在次设计中用到了T1和T0两个定时器,定时器T0控制T1开启和关闭,T0定时长度由指令码中高低电平维持时间长度决定。
具体发射过程如下:(1)定时器T1打开10ms,发射10ms引导码。
(2)定时器T1关闭3ms,发射3ms低平开始码。
(3)定时器T1打开1ms,发射1ms脉宽高电平脉冲。
(4)定时器T1关闭1ms,发射1ms脉宽低电平。
(5)重复(3)和(4)发射一定数目的脉冲。
(6)最后T1打开2ms和最后一个脉冲的1ms低电平一起构成3ms结束码,最终发射的信号如图3-2。
3.4 红外遥控接收系统的设计红外遥控接收电路框图见图3-4。
红外接收端普遍采用价格便宜,性能可靠的一体化红外接收头(MS0038 , 它接收红外信号频率为38KHz ,周期约26μs)。
它能同时对信号进行放大、检波、整形,得到TTL 电平的编码信号。
当接收头接收到26us周期的脉冲,输出低电平,否则输出高电平。
接收到的信号与发射信号成反码。
如图3-5中的A和图3-6中的E。
红外接收头收到信号后单片机立即产生中断,进入中断程序,同时关闭中断,开始接收红外信号。
先检测开始的低电平是否为10ms,若不是则退出中断程序,打开中断重新接收信号。
若是则检测下个电平是否为3ms高电平,如果不是,则退出中断程序,打开中断重新接收信号。
若是则表明接收信号有效,检测下个电平是否为低电平,若是低电平则脉冲计数器加一,表示检测到了第一个脉冲。
同时等待电平变为高电平,接着延时1ms跳过无用高电平,之后若再检测到低电平,则脉冲计数器继续加一。
再等待电平变为高电平,之后延时1ms 跳过无用高电平,之后若检测到低电平,则脉冲计数器继续加一。
如此重复上面的步奏。
如果1ms延时跳过无用高电平后,检测到仍为高电平,则继续延时1ms,之后再检测,若检测到低电平,也就是最后检测到了2ms高电平,则说明没有接收到3ms结束码,则此次接收的信号无效,退出中断程序,打开中断重新接收信号。
如果2ms高电平后,检测到了高电平,则继续延时1ms,如果检测到高电平,则说明最后接收到了大于3ms的高电平,因此结束码无效,此次接收无效,如果接收到低电平,则此次接收成功,计数器值有效。
同时将有效的计数值传给程序,进行指令分析,根据脉冲的不同个数执行相应操作。
图3-4 红外接收电路框图3.5 红外编解码原理通用红外编码采用不同的脉宽宽度来实现二进制信号的编码,编码由发送单片机来完成。
以间隔0.56ms、脉宽为0.565ms、周期为1.125ms的组合表示二进制的“1”;以间隔1.685ms、脉宽为0.565ms、周期为2.25ms的组合表示二进制的“0”。
本课题采用脉冲个数来进行编码,1ms高电平和1ms低电平组成一个脉冲周期,通过计算接收的不同脉冲个数执行部不同的操作。
3.5.1 指令码的调制指令码信号的调制仍由发送单片机来完成,如图3-5所示,A是指令码信号的编码波形,B 是频率为38KHz (周期为26μs) 的连续脉冲,C 是经调制后的间断脉冲串也就是信息码(相当于C =A ×B) ,也是用于红外发射二极管发送的波形。
图中脉冲个数仅为示意非真实情况。
3.5.2 信息码的解调信息码的解调由一体化红外接收头MS0038来完成,它把接收到的红外信号(图3-6中波形D ,也是图3-5中波形C) 经内部处理并解调复原,在输出脚输出图3-6中波形E (正好是对图3-5中波形A 的取反) ,MS0038的解调可理解为:在有红外脉冲输入时,输出端输出低电平,否则输出高电平,其输出的信号与TTL电平信号兼容,可直接与单片机T1的外部口及外部中断相联,以实现随时接收遥控信号并产生中断,然后由单片机对编码还原。
图3-5指令码信号的调制图3-6 信息码的解调#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit k1=P1^0;sbit k2=P2^4;sbit k3=P2^3;sbit k4=P2^2;sbit k5=P2^1;sbit k6=P2^0;uint flag=0;sbit LED_signer=P3^4;sbit LED=P3^0;void delay_10ms() //延时10ms;{ TH0 =0xd8 ;TL0 =0xf0 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void delay_3ms() //延时3ms; { TH0 =0xf4 ;TL0 =0x48 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void delay_1ms() //延时1ms;{ TH0 =0xfc ;TL0 =0x18 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void Time_Init(){EA=1;//总中断TMOD=0x21;TR1=0;ET0=0;///// 定时器0关闭;TR0=0;ET1=1;TH1=0xf3;TL1=0xf3;///// 定时器1关闭;} /////////////////////////中断初始化;void Time1_Init() interrupt 3{LED_signer=~LED_signer;} //////////////////////定时器1中断函数;void k1_count() ////////////发射2个脉冲;{ flag=1;LED=0;LED_signer=0;TR1=1;delay_10ms();TR1=0;/////////////////////////////// //10ms引导码高电平;while(flag){ uint i=0;LED_signer=0;delay_3ms(); //3ms低电平开始码;////////////////////////////////for(i=0;i<2;i++){TR1=1; ///1ms高电平脉冲delay_1ms(); ///脉冲个数就是循环次数;TR1=0;LED_signer=0;delay_1ms();}///////////////////////////////delay_1ms();delay_1ms(); //2ms结束码;if(k1==0) //如果结束码发射完毕时,若k1还被按住,{ //则发射下一帧的引导码10ms//TR1=1;delay_10ms();TR1=0;}else //若此时k1不为0了,则发射该码的结束引导码10ms;{flag=0;TR1=1;delay_10ms();TR1=0;LED_signer=0;}///////////////////////////////////// 结束码10ms高电平;}LED=1;}void k2_count() ///////////////////发射4个脉冲;{flag=1;LED=0;LED_signer=0;TR1=1;delay_10ms();TR1=0;/////////////////////////////// //10ms引导码高电平;while(flag){ uint i=0;LED_signer=0;delay_3ms(); //3ms低电平开始码;////////////////////////////////for(i=0;i<3;i++){TR1=1; ///1ms高电平脉冲delay_1ms(); ///脉冲个数就是循环次数;TR1=0;LED_signer=0;delay_1ms();}///////////////////////////////delay_1ms();delay_1ms(); //2ms结束码;if(k2==0) //如果结束码发射完毕时,若k还被按住,{ //则发射下一帧的引导码10ms//TR1=1;delay_10ms();TR1=0;}else //若此时k不为0了,则发射该码的结束引导码10ms;{flag=0;TR1=1;delay_10ms();TR1=0;LED_signer=0;}///////////////////////////////////// 结束码10ms高电平;}LED=1;}void k3_count() ////////////////////发射6个脉冲;{flag=1;LED=0;LED_signer=0;TR1=1;delay_10ms();TR1=0;/////////////////////////////// //10ms引导码高电平;while(flag){ uint i=0;LED_signer=0;delay_3ms(); //3ms低电平开始码;////////////////////////////////for(i=0;i<4;i++){TR1=1; ///1ms高电平脉冲delay_1ms(); ///脉冲个数就是循环次数;TR1=0;LED_signer=0;delay_1ms();}///////////////////////////////delay_1ms();delay_1ms(); //2ms结束码;if(k3==0) //如果结束码发射完毕时,若k还被按住,{ //则发射下一帧的引导码10ms//TR1=1;delay_10ms();TR1=0;}else //若此时k不为0了,则发射该码的结束引导码10ms;{flag=0;TR1=1;delay_10ms();TR1=0;}///////////////////////////////////// 结束码10ms高电平;}LED=1;}void k4_count() //////////////发射8个脉冲{flag=1;LED=0;LED_signer=0;TR1=1;delay_10ms();TR1=0;/////////////////////////////// //10ms引导码高电平;while(flag){ uint i=0;LED_signer=0;delay_3ms(); //3ms低电平开始码;////////////////////////////////for(i=0;i<5;i++){TR1=1; ///1ms高电平脉冲delay_1ms(); ///脉冲个数就是循环次数;TR1=0;LED_signer=0;delay_1ms();}///////////////////////////////delay_1ms();delay_1ms(); //2ms结束码;if(k4==0) //如果结束码发射完毕时,若k还被按住,{ //则发射下一帧的引导码10ms//delay_10ms();TR1=0;}else //若此时k不为0了,则发射该码的结束引导码10ms;{flag=0;TR1=1;delay_10ms();TR1=0;LED_signer=0;}///////////////////////////////////// 结束码10ms高电平;}LED=1;}void k5_count() //////////////发射10个脉冲码;{flag=1;LED=0;LED_signer=0;TR1=1;delay_10ms();TR1=0;/////////////////////////////// //10ms引导码高电平;while(flag){ uint i=0;LED_signer=0;delay_3ms(); //3ms低电平开始码;////////////////////////////////for(i=0;i<6;i++){TR1=1; ///1ms高电平脉冲delay_1ms(); ///脉冲个数就是循环次数;TR1=0;LED_signer=0;delay_1ms();}///////////////////////////////delay_1ms();delay_1ms(); //2ms结束码;if(k5==0) //如果结束码发射完毕时,若k还被按住,{ //则发射下一帧的引导码10ms//TR1=1;delay_10ms();TR1=0;}else //若此时k不为0了,则发射该码的结束引导码10ms;{flag=0;TR1=1;delay_10ms();TR1=0;LED_signer=0;}///////////////////////////////////// 结束码10ms高电平;}LED=1;}void k6_count() ////////////////发射12个脉冲码;{flag=1;LED=0;LED_signer=0;TR1=1;delay_10ms();TR1=0;/////////////////////////////// //10ms引导码高电平;while(flag){ uint i=0;LED_signer=0;delay_3ms(); //3ms低电平开始码;////////////////////////////////for(i=0;i<7;i++){TR1=1; ///1ms高电平脉冲delay_1ms(); ///脉冲个数就是循环次数;TR1=0;LED_signer=0;delay_1ms();}///////////////////////////////delay_1ms();delay_1ms(); //2ms结束码;if(k6==0) //如果结束码发射完毕时,若k还被按住,{ //则发射下一帧的引导码10ms//TR1=1;delay_10ms();TR1=0;}else //若此时k不为0了,则发射该码的结束引导码10ms;{flag=0;TR1=1;delay_10ms();TR1=0;LED_signer=0;}///////////////////////////////////// 结束码10ms高电平;}LED=1;}void main(){ P2=0xff;P1=0xff;Time_Init();LED_signer=0;LED=1;while(1){if(k1==0){delay_10ms();if(k1==0)k1_count();}else if(k2==0){delay_10ms();if(k2==0)k2_count();}else if(k3==0){delay_10ms();if(k3==0)k3_count();}else if(k4==0){delay_10ms();if(k4==0)k4_count();}else if(k5==0){delay_10ms();if(k5==0)k5_count();}else if(k6==0){delay_10ms();if(k6==0)k6_count();}else ;}}2.以下是红外遥控接收板的代码#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit LED=P1^0; ///////////接受成功指示灯;uint count=0; ///////////计数脉冲个数;sbit IR=P3^2; ///////////红外接受头引脚;uint endcount=0;void delay_10ms(void) ///////////延迟10ms;{TH0 =0xd8 ;TL0 =0xf0 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void delay_3ms() ////////////延迟3.2ms;{TH0 =0xf3 ;TL0 =0x80 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void delay_1ms() ///////////延迟1.2ms;{TH0 =0xfb ;TL0 =0x50 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void delay_2ms() //////////延迟2ms;{TH0 =0xf8 ;TL0 =0x30 ;TR0 = 1;while(!TF0);TF0 = 0;TR0 = 0;}void Time_Init() /////////中断初始化;{EA=1;EX0=1;IT0=0;/////////// 外部中断0打开;TMOD=0x01;TR0=0;ET0=0; /// 计时器关闭;}void Time_Init0() interrupt 0{ EX0=0; /////外部中断响应时,关闭中断,进入中断函数;count=0;delay_10ms(); /////检测是否为信号10ms低引导码;if(IR==0) /////若不是,则跳出中断函数,继续执行中断;{ EX0=1;return;}delay_3ms(); /////若是引导码,则检验是否为3ms高电平开始码;if(IR==1) //////若不是开始码,则跳出中断函数,继续执行中断函数;{ EX0=1;return;}while(1){count++; //////若是开始码,且检测到IR==0则count加1;while(IR==0);///跳过低电平,delay_1ms(); ///延时1ms后,检测IR是否为低电平;if(IR==1) ///若不是,则结束接受程序,计数器清零;执行中断;{delay_2ms();if(IR==0){ endcount=count;EX0=1;return;}else{ EX0=1;return;}}////若是低电平,则跳回开头,计数器加1;}}void main(){Time_Init();LED=1;while(1){if(endcount==2){LED=1;}else if(endcount==3){LED=1;}else if(endcount==4){LED=1;}else if(endcount==5){LED=1;}else if(endcount==6){LED=1;}else if(endcount==7){LED=0;}else LED=1;}}。