红外遥控器是怎么工作的?(实现代码)
2022-08-01

红外遥控是我们现实生活中必不可少的一员。遥控,顾名思义即在遥远的地方进行控制,其实也就是说远程通信。红外遥控就是以红外线为传输介质的遥控。

红外遥控器是怎么工作的?其实它内部就是有一个单片机,单片机的I/O口控制一个红外LED灯(当然一般会加外部放大电路以增大传输距离),在内部编码后发送出去,然后电视或者空调之类的可以用红外遥控控制的电器在接收到红外信号后就会进行解码,并根据制定好的协议执行特定动作,比如电视可能换台、调节音量等。现在有的手机就带有红外遥控功能,其实也是用单片机的功能实现的。

红外遥控解码

有的时候,我们希望模拟一些遥控器的功能,这时候就要对这些遥控器的数据进行解码。

在进行解码前,我们先来了解一下红外编码。红外编码有很多种,最常用的编码是NEC编码。NEC格式的编码如下:

NEC格式的红外编码是连续的32位二进制码组。32位二进制码组之前的引导码,用于区分每次的传输;在起始码之后的才是32位二进制码组,其中8位用户识别码和8位反码(反码主要用于)校验,用户识别码的作用主要是区分不同品牌的遥控器;接着就是8位操作码和反码,用于表示哪个按键被按下。

NEC格式的编码除引导码和起始码外,用于交互数据的信息采用脉宽调制的串行码,在38kHz的载波下,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如下所示:

了解了红外编码,就可以进行红外解码了。

实现方法

一般,进行红外解码我们需要先将接受到的有效信号与外界环境的干扰信号分离开,这就是载波的作用。现在市面上有很多一体化红外接收头,内部是红外接收二极管 +放大电路 +解调器。当接收到红外信号后,先将其放大,然后把38kHz的信号保留下来。需要注意的是一般一体化红外接收头接收到信号时输出是低电平,没有接收信号时是高电平。

上面是常用红外接收头的引脚,“OUT”脚接单片机的I/O口,“-”脚接电源负极,“+”脚接电源正极。

接好电路,就要进行解码工作了.其实解码工作主要是识别引导码,还有数据“0”“1”。我们看波形图,只要识别红外接收头“OUT”引脚高低电平持续的时间就可以了。这个可以用定时器中断完成,也可以用延时来判断。由于只完成解码工作,我们就用延时的方法更方便。

首先,红外接收头没有接到信号时是高电平,等待其变低。之后,每隔900us测量一次,若在10次内电平变高,说明这不是引导码,退出重新开始;若10次内并没有变高,说明这就是引导码,继续下一步。接着可以不判断起始码,就是直接等待引脚电平变高再变低,就可以接收数据了。

接收数据,就是进行判断“0”和“1”。从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。

每一位“0”或者“1”在接收头接收信号即低电平的时间都是一样的,直接等待低电平过去,在高电平时延时600us,如果600us时还是高电平,说明是“1”;如果是低电平即高电平过去了,说明是“0”。将这些数据结合到一起,就是接收到的编码了。

将单片机的串口与电脑接好,就可以在串口显示我们读到的红外遥控数据了。

实现代码:

#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();

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~928us

if ( 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.086ms

DELAY_Us(200);          // 0.086ms

DELAY_Us(200);          // 0.086ms

// 共计2.272ms

if( 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~928us

if ( IR_Out == 1)

DELAY_Ms(1);        // 测试实际延时约为1.007ms

return 1;

else

return 0;

// --- 串口初始化 --------------------------------------------

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 reload

TH1 = 0xFD;             // TH1: reload value for 9600 baud @

// 11.0592MHz

TR1 = 1;                // TR1: timer 1 run

EA = 0;                 // 关闭总中断

ES = 0;                 // 关闭串口中断

1、红外遥控的编码不只NEC,还有很多也有广泛应用如RC-5,RC-6等。

2、上面的代码所用指令是STC 89C52单片机,如需用其它芯片请另行更改。

以上所有信息仅作为学习交流使用,不作为任何学习和商业标准。若您对文中任何信息有异议,欢迎随时提出,谢谢!

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
  • 嵌入式系统的运算处理架构

    硬件三人行,专注于工程师在线教育。以模拟电路课程和PCB实战课程为主,以基于stm32的算法课程和产品结构课程为辅。满足5年以下工作经验的硬件工程师技术提升需求

    昨天
  • Linux Kernel是如何工作的

    ( 作者:杨东杰)  本文发表于LinuxFormatmagazine杂志,作者从技术深度上解释了LinuxKernel是如何工作的。相信对Linux

    08-11
  • Linux在PMP消费类电子产品上的应用

      Linux是一种适合于嵌入式系统的开源操作系统,可以高效地处理各种复杂的任务。从基于TIDM320的PMP解决方案入手,以TIDM320平台为例,提出一种在

    08-11
  • C51中的关键字和ANSIC标准关键字

    1、C51中的关键字2、ANSIC标准关键字作者:武力戡乱来源:武力戡乱的博客

    08-11
  • Watchdog的原理和配置

    一、Watchdog介绍单片机的watchdog一般都有两个,一个是独立看门狗IWDG,一个是窗口看门狗WWDG。以STM32为例,STM32的独立看门狗是一个

    08-11
  • BSP在嵌入式开发中的位置和作用

    BSP是板级支持包,是介于主板硬件和操作系统之间的一层,应该说是属于操作系统的一部分,主要目的是为了支持操作系统,使之能够更好的运行于硬件主板。BSP是相对于操

    08-11
  • 6步移植Lua代码

    Lua代码符合ANSIC标准,只要有C编译器的开发环境就能跑Lua。虽说只要有C编译器就能跑Lua,但是单片机的环境太简单,有些C标准的内容仍旧无法支持。Lua

    08-11
  • 为什么单片机管脚设计成低电平才有效?

    它是由常用的电路结构所决定的,低电平时电路往往有较高电平时更低的环路阻抗,而低阻抗则意味着抗干扰能力更强。结合实际讲一个有用的例子来加深印象:有的同学可能已经学

    08-11
  • 单片机硬件设计去耦和供电

    1、建议在印制电路板中,VDD和GND分别由电源层和地层实现。连接到AVDD和AGND引脚的模拟电源应直接布线到电源层和地层,它们不能和任何一个数字电源共享线路

    08-11
  • 设计单片机线路板时有指示灯的好处

    在设计单片机线路板的硬件的时候,一般都有指示灯,有时还不止一个,这样做是为什么呢?下面我来简要说一下自己设计电路板和软硬件调试的时候,指示灯所起到的不可忽视的作

    08-11
  • ARM Contex三个系列的区别

    从cortex开始,分为三个系列,a系列,r系列,m系列。m系列与arm7相似,不能跑操作系统(只能跑ucos2),偏向于控制方面,说白了就是一个高级的单片机。

    08-11
  • 51单片机程序的几个特点

    本篇我们将分析上一篇所写的程序代码。未来学习单片机的大部分精力,我们也将放在程序代码的编写上。但是不用担心,我会非常详细的介绍每个程序的编写思路和各种注意事项等

    08-11
下载排行榜
更多
广告