一、内容提要
上讲介绍并应用了单片机动态扫描驱动数码管,并给出了实例。这一讲将重点介绍单片机如何通过捕获来实现对红外遥控器解码。通过该讲,读者可以掌握红外遥控器的编码原理以及如何通过单片机对遥控器进行解码。
二、原理简介
随着家用电器、视听产品的普及,红外线遥控器已被广泛使用在各种类型的家电产品上(如遥控开关、智能开关等)。其具有体积小、抗干扰能力强、功耗低、功能强、成本低等特点,在工业设备中也得到广泛应用。
一般而言,一个通用的红外遥控系统由发射和接收两大部分组成,如图1 所示:
图1 红外遥控系统框图
其中发射部分主要包括键盘矩阵、编码调制、红外发射管;接收部分包括光、电信号的转换以及放大、解调、解码电路。举例来说,通常我们家电遥控器信号的发射,就是将相应按键所对应的控制指令和系统码( 由0 和1 组成的序列),调制在32~56kHz 范围内的载波上,然后经放大、驱动红外发射管将信号发射出去。此外,现在流行的控制方法是应用编/ 解码专用集成电路芯片来实现(如下文提到的SAA3010红外编码芯片和HS0038红外接收头)。
不同公司的遥控芯片,采用的遥控码格式也不一样。在此介绍目前广泛使用较普遍的两种,一种是NEC Protocol 的PWM( 脉冲宽度调制) 标准,一种是PhilipsRC-5Protocol 的PPM( 脉冲位置调制) 标准。
NEC 标准:遥控载波的频率为38kHz( 占空比为1:3) ;当某个按键按下时,系统首先发射一个完整的全码,然后经延时再发射一系列简码,直到按键松开即停止发射。简码重复为延时108ms,即两个引导脉冲上升沿之间的间隔都是108ms。一个完整的全码如图2所示。
图2 NEC标准下的全码表示
其中,引导码高电平4.5ms,低电平4.5ms ;用户码8 位,数据码8 位,共32 位;数据0 可用“高电平0.56ms +低电平0.56ms”表示,数据1 可用“高电平0.56ms +低电平1.68ms”表示,如图3 所示。一个简码可等同于引导码、系统码位0 的反码和结束位(0.56ms) 高电平时间总和。
图3 NEC标准下的数据0和1的表示
PHILIPS 标准:载波频率为38kHz ;没有简码,点按键时,控制码在1 和0 之间切换,若持续按键,则控制码不变。一个全码可等同于起始码、控制码、系统码、数据码的时间总和,如图4 所示。
图4 PHILIPS标准下的全码表示
数据0 用“低电平0. 889ms +高电平0. 889ms”
表示;数据1 用“ 高电平0. 889ms + 低电平0.
889ms”表示(图5)。连续码重复延时114ms。
图5 PHILIPS标准下的数据0和1的表示
在本讲中采用的是SAA3010 这款红外遥控器(见图6(a)),其符合常见的PHILIPS 标准中的RC-5 编码格式,其一帧码序列是由2 位控制码,1 位翻转码,5 为地址码,6 位数据码,结束码组成。其数据位时间长度是1.688ms。连续码重复延时为108ms,即在每按键一直被按下时延时为108ms 再输出同样的一帧数据。
图6 (a) SAA3010遥控器外观图 (b) SAA3010的数据位 (c) SAA3010的数据重复周期
从图6 中可以看出,SAA3010 的位传送方式是采用双相位,位1 和位0 的相位正好相反。在解码时可以用定时采样的方式进行解码,一个位采样二次,分别在位波形的四分之一和四分之三处进行采样,如位1 用这种方法采样的值就是0 和1。当然也可以只采样一次,例如在波形的四分之一处进行采样,然后定时一个波形的周期再采样,这样位1 采样的值就是0(本讲的实例即是采用这种方法)。
三、电路详解
如图7 (a) 中所示,红外接收头解码电路非常简单,采用的是一体化红外线接收头,一体化的红外接收头将遥控信号的接收、放大、检波、整形集于一身,并且输出可以让单片机识别的TTL 信号,这样大大简化了接收电路的复杂程度和电路的设计工作,方便使用。在本讲中采用的是红外一体化接收头HS0038,其外观图如7(b) 所示。其为黑色环氧树脂封装,不受日光、荧光灯等光源干扰,内附磁屏蔽,功耗低,灵敏度高。在用小功率发射管发射信号情况下,接收距离可达30m。它能与TTL、COMS 电路兼容。HS0038 为直立侧面收光型。它接收红外信号频率为38 kHz, 周期约26μs,同时能对信号进行放大、检波、整形,得到TTL 电平的编码信号。
图7 (a) 红外接收头解码电路 (b) HS0038外观图
其三个管脚分别是地、电源正、解调信号输出端。
为了响应速度,红外接收头的解码信号输出接入到单片机P3.3(外部中断1)端口上,这样一旦有红外解码信号输出就可触发进去中断。此外,电容C7 用于电源去耦滤波,保证红外接收头稳定工作。
四、程序设计
本讲设计的核心程序如下:
void time0() interrupt 1 ( 1)
bit in = ~IR_Input; ( 2)
TH0 = 0XFF; ( 3)
TL0 = 0X83; ( 4)
IR_Data[IR_sign] = IR_Data[IR_sign] | in; ( 5)
IR_count++; ( 6)
if(IR_count == 1 || IR_count == 2) ( 7)
{
if(in == 0) ( 8)
{
TR0 = 0; ( 9)
EX1 = 1; ( 10)
return; ( 11)
}
}
if(IR_count == 3) ( 12)
{
IR_sign = 1; ( 13)
}
else if(IR_count == 8) ( 14)
{
if(IR_Data[1] != 0) ( 15)
{
TR0 = 0; ( 16)
EX1 = 1;
return;
}
IR_sign = 2; ( 17)
}
else if(IR_count == 14) ( 18)
{
IR_sign = 3; ( 19)
}
else if(IR_sign == 3) ( 20)
{
TR0 = 0; ( 21)
IR_Success(); ( 22)
return; ( 23)
}
else
IR_Data[IR_sign] = IR_Data[IR_sign] 《 1; ( 24)
程序详细说明:
(1)定时器中断0 服务函数,红外接收头解码数据触发外部中断1 后,引发定时器中断,从而进行捕获解码。
(2)解码时, 将载频部分变为低电平, 即低电平实际为1, 高电平实际为0。
(3)设置定时器0 高八位初值,因为要定时间长度为一个数据位周期。
(4) 设置定时器0 低八位初值。经过实测,SAA3010 的位时间在1.655ms 左右。
(5)将红外数据放入最低位。
(6)红外计数没进一次定时器中断就加1。
(7)如果当前是第1 次和第2 次进入定时器中断。
(8)如果此时in 的值为0,即如果发现起始两位不全是1 的情况。
(9)关闭定时器0。
(10)重新打开外部中断进行接收。即起始两位必须都为1。
(11)退出返回。
(12)如果接收完起始位(2 位)和控制位(1 位)。
(13)IR_sign 置1,即将接收到的红外系统码放到IR_Data[1] 中。
(14)如果当前计数达到第8 次,即接收完5 位系统码。
(15)如果接收到的系统码不为0,即要求系统码全为0 才正确。
(16)则关闭定时器和重开外部中断并返回。
(17)IR_sign 置2,将接收到的红外数据位放到IR_Data[2] 中。
(18)如果当前计数达到第14 次,即接收完6 位数据码。
(19)IR_sign 置3,表示数据码接收成功。
(20)如果IR_sign 等于3,即表示如果接收完成。
(21)接收完成,关闭定时器0,不再捕获。
(22)接收完成后跳转到执行IR_Success() 函数,进行显示以及重新初始化等。
(23)返回。
(24)将数据左移一位, 以便将一下位数据并于最低位。
五、调试要点与实验现象
接好硬件,通过冷启动方式将程序所生成的。hex 文件下载到单片机运行后,打开串口调试助手软件,设置好波特率9600,复位单片机,然后按下SAA3010 遥控器上的相应按键,可以观察到在接收窗口有接收到的数据显示见图8,此外电路板上的串行通信指示灯也会闪烁,P0 口也会将所接到的数据显示在LED 灯上。
值得注意的是,不同红外遥控器的编码格式不同,即便是同一型号的红外遥控器,其发射出来的码值也可能稍有微小的区别,例如笔者手里所用的SAA3010 红外遥控器,其位时间实测在1.655ms 左右,而不是在标称的1.688ms,因此,有条件的读者可以用示波器或者逻辑分析仪之类的仪表对遥控器发射出来的码值进行测量,从而相应的修改所捕获的时间,确保无误。此外,红外的穿透能力较弱,例如我们用手遮挡住遥控器的发射头或者接收头时,此时难以收到数据或者引入干扰。
六、总结
本讲介绍了51 单片机如何利用外部中断触发和内部定时器捕获的方式进行红外遥控器解码,现简单总结如下:
要对红外遥控器解码,首先应当知道遥控器的编码标准,无论是本文中所介绍的NEC 标准和PHILIPS 标准,还是其他编码格式,因为不了解编码格式,难以对编码进行判断,从而造成解错码。其次,由于晶振(如遥控器内部和单片机晶振)本身的不稳定性等,为保证解码的准确性,应对每位码长时间经行测量,如利用仪表或者使用单片机本身,从而得到准备结果。下讲将讲述单片机驱动字符型液晶1602 模块的原理与实例,敬请期待。