历史上的今天
今天是:2025年07月26日(星期六)
2021年07月26日 | 51单片机学习笔记【九】——红外通信实验
2021-07-26 来源:eefocus
一.红外通信基础
1.红外线原理
红外线是波长在760nm~1mm之间的非可见光。红外通信装置由红外发射管和红外接受管组成,红外发射管是能发射出红外线的发光二极管,发射强度随着电流的增大而增大;红外接受管是一个具有红外光敏感特征的PN节的光敏二极管,只对红外线有反应,产生光电流。
2.信号调制原理
基带信号:从信号源发出没有经过调制的原始信号,特点是频率较低,信号频率从0开始,频谱较宽。
调制:就是用待传送信号去控制某个高频信号的幅度、相位、频率等参量变化的过程,即用一个信号去装载另一个信号。
红外遥控器使用38KB的载波对原始信号进行解调,原理如下

调制后产生一定频段的高低电平,但红外接收头接受到的信号和调制后的信号电平相反。
3.NEC协议
红外遥控由多种协议控制,这里介绍最主要,应用最广的NEC协议。NEC数据格式:引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,最后一个停止位。
引导码:9ms的载波+4.5ms的空闲。
比特值“0”:560us的载波+560us的空闲。
比特值“1”:560us的载波+1.68ms的空闲。

协议规定低位首先发送。一串信息首先发送9ms的AGC(自动增益控制)的高脉冲,接着发送4.5ms的起始低电平,接下来是发送四个字节的地址码和命令码。如果你一直按那个按键,一串信息也只能发送一次,一直按着,发送的则是以110ms为周期的重复码。
二.实验例程
1.实验原理
产生下降沿,进入外部中断0的中断函数,延时一下之后检IO口是否还是低电平,是就等待9ms的低电平过去。等待完9ms低电平过去,再去等待4.5ms的高电平过去。接着开始接收传送的4组数据先等待560us的低电平过去检测高电平的持续时间,如果超过1.12ms那么是高电平(高电平的的持续时间为1.69ms,低电平的持续时间为565us。)检测接收到的数据和数据的反码进行比较,是否等到的数据是一样的。
2.实验说明
本实验通过单片机控制红外接受设备接受红外发送设备发送的信号,并通过数码管的显示判断是否接受到信号。实验接线为JP10接J12,J6的A,B,C分别接P2.2,P2.3,P2.4。
3.源代码
/**************************************
> File Name: 红外通信原理
> Author: pengshp
> Mail: pengshp3@outlook.com
> Date: 2015年 7 月 27 日
***************************************/
#include #define GPIO_DIG P0 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; sbit IRIN = P3^2; //红外接收器位声明 unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned char DisplayData[8]; //用来存放要显示的8位数的值 unsigned char IrValue[6]; //用来存放读取到的红外值 unsigned char Time; void DigDisplay(); //动态显示函数 void IrInit(); void DelayMs(unsigned int); void main() { IrInit(); while(1) { IrValue[4]=IrValue[2]>>4; //高位 IrValue[5]=IrValue[2]&0x0f; //低位 DisplayData[0] = 0x00; DisplayData[1] = DIG_CODE[IrValue[4]]; DisplayData[2] = DIG_CODE[IrValue[5]]; DisplayData[3] = 0x76; DisplayData[4] = 0x00; DisplayData[5] = DIG_CODE[IrValue[4]]; DisplayData[6] = DIG_CODE[IrValue[5]]; DisplayData[7] = 0x76; DigDisplay(); } } void DelayMs(unsigned int x) //0.14ms误差 0us { unsigned char i; while(x--) { for (i = 0; i<13; i++); } } void IrInit() { IT0=1; //下降沿触发 EX0=1; //打开中断0允许 EA=1; //打开总中断 IRIN=1; //初始化端口 } void ReadIr() interrupt 0 { unsigned char j,k; unsigned int err; Time=0; DelayMs(70); if(IRIN==0) //确认是否真的接收到正确的信号 { err=1000; //1000*10us=10ms,超过说明接收到错误的信号 while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去 { DelayMs(1); err--; } if(IRIN==1) //如果正确等到9ms低电平 { err=500; while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去 { DelayMs(1); err--; } for(k=0;k<4;k++) //共有4组数据 { for(j=0;j<8;j++) //接收一组数据 { err=60; while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去 { DelayMs(1); err--; } err=500; while((IRIN==1)&&(err>0))//计算高电平的时间长度。 { DelayMs(1); //0.14ms Time++; err--; if(Time>30) { EX0=1; return; } } IrValue[k]>>=1; //k表示第几组数据 if(Time>=8) //如果高电平出现大于565us,那么是1 { IrValue[k]|=0x80; } Time=0; //用完时间要重新赋值 } } } if(IrValue[2]!=~IrValue[3]) //反码取反后与原码相同则说明信号接受正确 { return; } } } void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { switch(i) //位选,选择点亮的数码管 { case(0): LSA=0;LSB=0;LSC=0; break; //显示第0位 case(1): LSA=1;LSB=0;LSC=0; break; //显示第1位 case(2): LSA=0;LSB=1;LSC=0; break; //显示第2位 case(3): LSA=1;LSB=1;LSC=0; break; //显示第3位 case(4): LSA=0;LSB=0;LSC=1; break; //显示第4位 case(5): LSA=1;LSB=0;LSC=1; break; //显示第5位 case(6): LSA=0;LSB=1;LSC=1; break; //显示第6位 case(7): LSA=1;LSB=1;LSC=1; break; //显示第7位 } GPIO_DIG=DisplayData[i]; //发送段码
史海拾趣
|
使用两条线测量电阻非常方便,但会产生测量误差。通过使用4条线及源端子和测量端子分开的万用表,几乎可以消除这种误差。遗憾的是,增加额外的引线和连接提高了测量的复杂程度。您需要连接增加的引线,在从电压变成电阻时,可能不得不更换夹子和探 ...… 查看全部问答> |
|
Found pins functioning as undefined clocks and/or memory enables原因:是你作为时钟的PIN没有约束信息。可以对相应的PIN做一下设定就行了。主要是指你的某些管脚在电路当中起到了时钟管脚的作用,比如flip-flop的clk管脚,而此管脚没有时钟约束 ...… 查看全部问答> |
|
散分!大家好,学习了两周的BIOS原代码分析,现写了一篇总结,希望大家多意见! 本科毕业设计,用了三周时间安装的wince开发环境,编写了第一个GPIO驱动 然后从上周一开始到今天(周日)共两周时间开始分析BIOS原代码的整个执行流程,(说是两周,期间有三天左右在看C++,有一天左右在看wince操作系统,有一天多在看USB,还有其 ...… 查看全部问答> |
|
我搞了一段helloworld的驱动,在linux下能加载成功,下面是测试驱动的代码 #include #include #include #include #include #include #include int main() {printf(\"Content-type:text/html\\n\\n\"); int fd,i,nwrite,nread; char *buf ...… 查看全部问答> |
|
玩pxa270的板子,接触到CPLD,不太清楚cpld与cpu之间的关系。cpld中关于Nandflash的控制逻辑: assign nNFRE = bnCS1 || bADDR25 || (!bADDR24) || bnOE; assign nNFWE = bnCS1 || bADDR25 || (!bADDR24) || bnWE; ...… 查看全部问答> |
|
if(k3==0) { while(!k3); timedata[0]--; if(timedata[0]<0) {timedata[0]=59;} 请问这句代码有问题吗?为什么我timedata[0]小于0时,得不到5 ...… 查看全部问答> |




