完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在此主要学习如何将红外通讯用代码来转化实现
首先我们需要了解红外通讯的基本组成或者是是基本过程,一般来说,红外操作系统由接收装置和发送装置两大部分组成。 那么从图中可以得到,红外通讯的基本过程,首先需要提前对键盘进行相应的编码调制,(此处我们用的是单片机送的红外遥控器),当你按下按键时,从发射管发出信号,当红外接收装置接收到信号后,对其进行信号放大与解调,然后解码输出这个信号。 信号调制和解调在此处不进行讨论,了解有这个过程即可。 不同的遥控产品可能使用不同的信号转化协议,我们采用的遥控器是单片机赠送的遥控器,采用的是NEC协议,其读取信号的方式如下图。 我们的任务是读取单片机的接收端,对其进行解码,那么接收端的方波图与图中正好相反,也就是说图中的高电平在接收中是低电平,此处我们需要注意数据传输的特点是从低位开始。 读0和读1 那么我们是如何来进行读0和读1的呢,首先,可以看到位0时,其周期为1.125ms左右,而位1时,其周期为2.25ms,我们就可以通过盘对其周期的读取来进行读0和读1。 确定周期 那我们怎么来进行一个周期的时间读取呢,我们注意到,不论是读0,读1还是上图的引导码和其他四个码,都是产生一个上升沿开始,直到下一个上升沿产生,结束一个周期。 而在接收端,就代表着一个周期就是产生一个下降沿到下一个下降沿产生的时间。 在我们了解完可以用时间来确定每一位的读取时,我们的问题已经解决的差不多了,接下来就是一些对NEC协议的了解和解读了。 NEC协议 首先NEC一共有33位数据,由一个一位构成的引导码和4个8位的用户码、用户码、数据码、数据反码。引导码象征信号的开始。 接下来就是实现解码的程序了,了解了过程后,理解程序其实是很简单的。 #include typedef unsigned char INT8U; typedef unsigned char uchar; typedef unsigned int INT16U; typedef unsigned int uint; uchar IRtime; //储存检测红外高低电平持续时间 uchar IRcord[4]; //储存解码后的4个字节数据 uchar IRdata[33]; //包含起始码在内的33位数据 bit IRpro_ok; //解码后4个字节数据接收完成标志位 bit IRok; //33位数据接收完成标志 //初始化定时器0,外部中断0,串口 void init() { TMOD |= 0x02;//设置定时器0工作模式2,8位自动重装 TL0 = TH0 = 0;//初始化定时器0寄存器,定时器0溢出一次时间为256个机器周期 EA = 1;//开总中断 ET0 = 1;//开定时器0中断 TR0 = 1;//启动定时器0 IT0 = 1;//设置外部中断0跳变沿触发方式 EX0 = 1;//开外部中断0中断 TMOD |= 0x20;//设置定时器1工作模式2 ,8位自动重装 TL1 = TH1 = 0xfd;//比特率9600 SM1 = 1;//设置串口工作模式1,10位异步收发 TR1= 1; //启动定时器1 } //定时器0中断,每中断一次需要256*1.085us = 277.76us void time0() interrupt 1 { IRtime++;//277.76us } //外部中断0 存入33次脉宽 void int0() interrupt 0 { static uchar i;//静态变量用于存入33次数据计数 static bit startflag;//开始储存脉宽标志位 if(startflag) { /*判断引导码,如果是引导码则从起始码开始存*/ if((IRtime < 53) && (IRtime >= 32)) i = 0; IRdata = IRtime;//以TO溢出的次数来计算脉宽把这个时间存放在数组中 IRtime = 0;//计数清零 i++;//计数脉宽存入次数自加 if(i == 33) //i等于33那么就表示已经存入了33次脉宽 { IRok = 1; //脉宽检查完成 i = 0; //把脉宽计数清零准备下次存入 } } else { IRtime = 0; //定时器0计数清零 startflag = 1;//开始处理标志位置1 } } //把提取的33次脉宽进行解码 NEC协议 void IRcordpro() { uchar i;//i是用于计数处理4个字节 uchar j;//j用于计数处理1个字节的8位数据 uchar k;//k用于计数处理33次脉宽 k = 1;//从第一位脉宽开始处理,丢掉起始码 for(i = 0; i < 4; i++) { for(j = 0; j < 8; j++) { //如果脉宽大于数据0标准的1125us那么就判定为数据1 if(IRdata[k] > 5) IRcord |= 0x80;//写1 //只能右移7次,如果右移8次则会把第一位数据移出去 if(j < 7) IRcord >>= 1; k++; //处理下一次脉宽 } } IRpro_ok = 1;//解码完成 } void main() { uchar i; //计数串口发送字节数 init();//初始化 while(1) { if(IRok)//判断33次脉宽是否提取完成 { IRcordpro();//根据脉宽解码出4个字节的数据 IRok = 0;//清零脉宽检查完成标志位等待下一次脉宽检查 if(IRpro_ok)//判断解码是否完成 { for(i = 0; i < 4; i++) //串口发送4个字节数据 { SBUF = IRcord; //发送数据 while(!TI); //等待发送完成标志 TI = 0; //清零发送完成标志位 } IRpro_ok = 0;//清零解码标志位 } } } } |
|
|
|
只有小组成员才能发言,加入小组>>
2553 浏览 0 评论
1152浏览 2评论
750浏览 1评论
503浏览 0评论
269浏览 0评论
433浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 10:05 , Processed in 1.483016 second(s), Total 79, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号