红外原理
来源:互联网 发布:豪世华邦网络办公平台 编辑:程序博客网 时间:2024/04/29 00:29
首先,必须要了解一些基本原理。其实按下遥控器的某一个键,遥控器会发出一连串经过调制后的信号,这个信号经过红外一体化模块接收后,输出解调后的数字脉冲,每个按键对应不同的脉冲,故识别出不同的脉冲就能识别出不同的按键。
上图就是很常见的车载MP3遥控器,比较小巧,很好用。下面是红外发射和接受原理:
到此读者可能会有疑惑,那么不同的调制解调方法那么出来的脉冲规则是不一样的?是的,的确如此。
遥控发射器专用芯片很多,根据编码格式可以分成两大类,这里我们以运用比较广泛,解码比较容易的一类来加以说明,现以日本NEC的uPD6121G组成发射电路为例说明编码原理(一般家庭用的DVD、VCD、音响都使用这种编码方式)。当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:
- 8 位地址码, 8 位命令码
- 完整发射两次地址码和命令码,以提高可靠性
- 脉冲时间长短调制方式
- 38KHz 载波频率
- 位时间 1.12ms 或 2.25ms
下图为一个引导码的调制波形:
下图为逻辑0和逻辑1的调制波形:
下图为重复码的调制波形:
请看下图,来自网络:
当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个引导码(9ms),一个结果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,接下来发射的代码(连发码)将仅由起始码(9ms)和结束码(2.25ms)组成。(实际上人手的动作是很慢的,即使你快速的按下按键,可能对于芯片来说还是超过108ms,所以如何处理连发码是很关键的)
遥控器在按键按下后,周期性地发出同一种32位二进制码,周期约为108ms。一组码本身的持续时间随它包含的二进制“0”和“1”的个数不同而不同,大约在45~63ms之间,图为发射波形图。
下面是我写的代码,按键编码通过串口发送到电脑端:
由于时间关系,代码注释不多。
其中START_Judge()函数是判断9ms低电平,既是判断有无遥控信号。
BOOT_REPEATING_CODE_Judge()是判断是引导码还是连发码,引导码则进入接受数据环节,连发码表明数据已经接受结束。
H_L_LEVEL_Judge()是接受数据时判断高低电平。
/*------------------------------------------------------------*- 红外收发.C ------------------------------------------------------------ 遥控器测试-*------------------------------------------------------------*/#include <reg52.h>// --- 红外接收一体化输出口 ----------------------------------sbit IR_Out = P3^2;bit START_Flag = 0;bit BOOT_REPEATING_CODE_Flag = 0;unsigned char DATA[4] = {0};bdata unsigned char TEMP_BIT;sbit B0 = TEMP_BIT^0;sbit B1 = TEMP_BIT^1;sbit B2 = TEMP_BIT^2;sbit B3 = TEMP_BIT^3;sbit B4 = TEMP_BIT^4;sbit B5 = TEMP_BIT^5;sbit B6 = TEMP_BIT^6;sbit B7 = TEMP_BIT^7;// --- 有无遥控信号判断函数 ----------------------------------bit START_Judge();// --- 连发码判断函数 ----------------------------------------bit BOOT_REPEATING_CODE_Judge();// --- "0"和"1"识别 ------------------------------------------bit H_L_LEVEL_Judge();// --- 串口初始化 --------------------------------------------void UART_Initial();void DELAY_Us(unsigned int Us){unsigned int x;for(x = 0; x <= (Us/200-1); x++);}void DELAY_Ms(unsigned int Ms){unsigned int x,y;for(x = 0; x <= (Ms-1); x++){for(y = 0; y <= 120; y++);}}void main(){unsigned char i;UART_Initial();IR_Out = 1;while(1){START_Flag = START_Judge();BOOT_REPEATING_CODE_Flag = BOOT_REPEATING_CODE_Judge();if ( START_Flag && !BOOT_REPEATING_CODE_Flag ){for(i =0;i <4; i++){B0 = H_L_LEVEL_Judge();B1 = H_L_LEVEL_Judge();B2 = H_L_LEVEL_Judge();B3 = H_L_LEVEL_Judge();B4 = H_L_LEVEL_Judge();B5 = H_L_LEVEL_Judge();B6 = H_L_LEVEL_Judge();B7 = H_L_LEVEL_Judge();DATA[i] = TEMP_BIT;}for(i =0;i <4; i++){SBUF = DATA[i];while( TI == 0 );TI = 0;}}}}void UART_Initial(){SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit reloadTH1 = 0xFD; // TH1: reload value for 9600 baud @// 11.0592MHz TR1 = 1; // TR1: timer 1 runEA = 0; // 关闭总中断ES = 0; // 关闭串口中断}bit START_Judge(){bit TEMP_Flag = 1;unsigned char i = 0; //在正常无遥控信号时,一体化红外接收头输出是高电平,程序一直在循环。 while ( IR_Out == 1);//重复10次,目的是检测在6876~8352微秒内如果出现高电平就退出解码程序for(i =0;i <9; i++){DELAY_Us(800);// 测试实际延时约为764~928usif ( IR_Out == 1 ){TEMP_Flag = 0;break;}}return TEMP_Flag;}bit BOOT_REPEATING_CODE_Judge(){bit TEMP_Flag = 1;while( IR_Out == 0 ) ;// 等待高电平避开9毫秒低电平引导脉冲DELAY_Ms(1);// 测试实际延时约为1.007ms DELAY_Ms(1);// 测试实际延时约为1.007ms DELAY_Us(200);// 0.086msDELAY_Us(200);// 0.086msDELAY_Us(200);// 0.086ms// 共计2.272msif( IR_Out == 0 ){TEMP_Flag = 1;// 是连发码}else{TEMP_Flag = 0;// 不是连发码,而是引导码}return TEMP_Flag;}bit H_L_LEVEL_Judge(){while( IR_Out == 0 );// 等待地址码第一位的高电平信号DELAY_Us(800);// 测试实际延时约为764~928usif ( IR_Out == 1){DELAY_Ms(1);// 测试实际延时约为1.007ms return 1;}else{return 0;}}
编辑如下:
01 FE 8B 74 --- 01 FE 8D 72 --- 01 FE 8F 70
01 FE 89 76 --- 01 FE 81 7E --- 01 FE 87 78
01 FE 0F F0 --- 01 FE 2B D4 --- 01 FE 13 EC
01 FE 2D D2 --- 01 FE 33 CC --- 01 FE 1B E4
01 FE 19 E6 --- 01 FE 31 CE --- 01 FE BD 42
01 FE 11 EE --- 01 FE 39 C6 --- 01 FE B5 4A
以上为对应按键的编码。
过程中存在问题:
一是如何有效的识别引导码和连发码,因为这个能直接影响到长时间按键,单片机的响应与否。这个问题,貌似我以解决,就是长时间按键后,单片机识别一次按键后,如果还是同一按键,就不与理睬。
还有一个问题就是,如果连续按下两次按键,该程序能够识别出,但是如果间隔很短,第二下按键的编码容易出错,容易变成这样:
03 FE 8B 74.。。。就是第一个字节出现误差,这个问题现在还未来得及解决。
还有就是本程序对于延时函数的精度要求很高,因为本身处理的脉冲就是MS级别的。所以需要严格的测试延时函数的实际延时时间:
以上的代码,可以看出许多问题,软件延时不准确,大量的“while( IR_Out == 0 ) ;”代码,抗干扰能力弱,容易进入死循环。
下面介绍的这种解码方法,利用外部中断触发程序,定时器定时(但没有设置定时中断程序,即判断TF的值确定定时结束),在代码过程中,开头的一个7.93ms延时,足以滤掉不合法的红外信号。应该说效率质量更高的。
代码注释很详细,在此不在细述:
/*------------------------------------------------------------*- IR_Decoder.C (v1.00) ------------------------------------------------------------ 名称:遥控器红外解码,PO口接LED,显示功能码以供查看 编写:mhjerry 日期:20011.7 内容:按遥控器上的按键,会在PO口LED上显示-*------------------------------------------------------------*/#include "reg52.h"// 此口为红外信号输入MCU口sbit IR_Out = P3^2;// 主程序运行标志位,运行主程序时LED灭,运行中断程序时LED亮sbit IR_Flag = P3^1;// LED显示口#define LED_Port P1// 用于存放按键码值,初始化为0000 0000这样接受数据时可以只考虑1了unsigned char dat[4] = {0,0,0,0};/*............................................................*/void main(){IR_Out = 1;// 此口为MCU输入口,故需要置1IR_Flag = 1;// 灭LED灯TMOD = 0x01;// 定时器0,方式1IT0 = 1;// 外部中断0,下降沿触发EX0 = 1;// 准许外部中断EA = 1;// CPU准许中断while(1){IR_Flag = 1;// 执行主程序时,LED灯灭}}/*------------------------------------------------------------*- 函数名称:Int0() 函数输入:无(容许中断时,外部触发) 函数输出:无 函数说明:外部中断0中断处理-*------------------------------------------------------------*/void Int0() interrupt 0{unsigned char i,j;EX0 = 0;// 关闭外部中断0IR_Flag = 0;// 执行中断程序时,LED灯亮i = 10;// 0.793ms延时,运行10次while( --i ){// 定时0.793ms,延时0.793ms*10=7.93msTH0 = 0xfc;TL0 = 0xe7;TR0 = 1;while( !TF0 );TF0 = 0;TR0 = 0;// 这7.93ms期间只要IR_Out变高电平,就非合法的红外信号,跳出if( IR_Out ){EX0 = 1;// 准许中断return ;}}// 程序进行到这里,表明是合法的红外信号(利用9ms判断)while( !IR_Out );// 等待9ms低电平过去// 程序进行到这里,表明经过9ms低电平TH0 = 0xf6; TL0 = 0xff;TR0 = 1;while( !TF0 );TF0 = 0;TR0 = 0; // 延时2.305ms// IR_Out 为低表明是连发码,不予理睬,跳出if( !IR_Out ){EX0=1;return;}// 程序进行到这里,表明是引导码,等待4.5ms高电平的过去while( IR_Out );// 开始接收用户码for(i=0; i<4; i++) {for(j=0; j<8; j++){while( !IR_Out );// 等待低电平过去 dat[i] >>= 1;// 把上次的数据位右移一位TH0 = 0xfc; TL0 = 0xe7;TR0 = 1; while( !TF0 ); TR0=0; TF0=0; //延时0.793ms// 若为数据"1",则延时后IR_Out为高电平 if( IR_Out ) { dat[i] |= 0x80;// 所有数据位1放最高位 while( IR_Out );// 等待高电平过去 }} }LED_Port = dat[2]; EX0=1;// 开中断 return;}/*------------------------------------------------------------*- ---- END OF FILE --------------------------------------------*------------------------------------------------------------*/
- 红外原理
- 红外遥控原理
- 红外遥控器工作原理
- 红外遥控通信原理
- 红外遥控器解码原理
- 红外遥控原理
- 红外接收原理
- 红外 IR 协议原理分析
- 红外发射与接收原理
- 红外 IR 协议原理分析
- 红外 IR 协议原理分析
- 16.2 红外遥控通信原理
- 红外
- 红外
- 红外
- 红外
- 红外
- 红外
- 浅谈Javaweb经典三层架构和MVC框架模式
- DNA Pairing
- HEVC函数入门(9)——tile相关
- Html5 补充笔记 单行标签结束,css display input title
- CodeM美团点评编程大赛初赛B轮
- 红外原理
- 浏览器工作原理
- Oracle创建表空间、用户的完整过程
- 跨域问题解决完整方案
- 锁的升级与对比
- 将腾讯视频缓存文件保存成MP4
- nginx利用第三方模块nginx_upstream_check_module来检查后端服务器的健康情况
- [进军硅谷]将二叉搜索树转化为一个有序的循环链表
- lock和lockfree 之内核如何使用队列的