主要参考学习资料:B站【普中官方】51单片机手把手教学视频
开发资料下载链接:http://www.prechin.cn/gongsixinwen/208.html
单片机套装:普中STC51单片机开发板A4标准版套餐7
红外遥控介绍
红外线简介
可见光按波长从长到短排列依次为红橙黄绿青蓝紫,其中红光波长为620~760nm。比红光波长还要长的光为红外线,红外遥控利用波长760~1500nm的红外线来传输控制信号。
红外遥控原理
红外发射装置
红外发射装置是由键盘电路、红外编码电路、电源电路和红外发射电路组成。红外发射电路的主要元件是红外发光二极管。通常红外遥控为了提高抗干扰性能和降低电源消耗,常用38KHz的载波传输二进制编码,该频率来源于发射端晶振频率455KHz的十二分频。
上图左侧为发射端,右侧为接收端。脉冲到达时,发射端二极管发出红外线,接收端通过取反将其解码。
二进制编码形式有很多种,常见的是以NEC为代表的PWM脉冲宽度调制码和Philip的PPM脉冲位置调制码,本实验配套遥控器使用NEC的协议。
NEC码的位定义(发射端):一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(569us脉冲+560ms低电平)。
NEC遥控指令的数据格式(接收端):引导码由9ms的低电平和4.5ms的高电平组成,地址码、地址反码、控制码、控制反码均为八位数据格式,按照从低位到高位的顺序传输,反码增加了传输的可靠性,用于检验传输的信号是否正确。地址码和地址反码对于同一个遥控器来说是相同的,不同按键对应的控制码是不一样的。发射端需要对上述信号取反。
NEC还规定了连发码,由9ms低电平+2.5ms高电平+0.56ms低电平+97.94ms高电平组成。如果在一帧数据数据发送完成后,红外遥控器按键仍然没有放开,会紧接着发送连发码。通过统计连发码的次数可以标记按键按下的长短或者次数。
红外接收装置
红外接收设备由红外接收电路、红外解码、电源和应用电路组成,将红外线转化为电信号,再经过放大、限幅、检波和整型形成遥控指令脉冲输出到微控制器来对信号进行接收。
一体化红外接收头对上述电路进行了集成封装,包括三个管脚,从左到右依次为Vout、GND、Vcc。
红外接收头在无脉冲时为高电平,接收到脉冲时为低电平,可通过下降沿触发外部中断,从中断中读取数据。
硬件设计
本实验Vout管脚与单片机外部中断管脚P3.2相连。
实验17 红外遥控
实现功能:数码管显示红外遥控器键值。
数码管驱动沿用自实验14
红外接收头驱动
ired.h
#ifnedf _ired_H
#define _ired_H
#include "public.h"
//定义外部中断管脚
sbit IRED = P3^2;
//声明存储一帧数据的数组
extern u8 gired_data[4];
void ired_init(void);
#endif
ired.c
程序框图(未注明分支均强制退出中断):
#include "ired.h"
u8 gired_data[4];
//启用相应外部中断
void ired_init(void)
{
IT0 = 1;
EX0 = 1;
EA = 1;
IRED = 1;
}
//外部中断响应函数
void ired() interrupt 0
{
//倒计时变量
u16 time_cnt = 0;
//存储循环控制变量
u8 i = 0, j = 0;
//高电平计时变量
u8 ired_high_time = 0;
//参考程序框图
if(!IRED)
{
time_cnt = 1000;
while(!IRED)
{
delay_10us(1);
time_cnt--;
if(!time_cnt)return;
}
if(IRED)
{
time_cnt = 500;
while(IRED)
{
delay_10us(1);
time_cnt--;
if(!time_cnt)return;
}
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
time_cnt = 600;
while(!IRED)
{
delay_10us(1);
time_cnt--;
if(!time_cnt)return;
}
while(IRED)
{
delay_10us(10);
ired_high_time++;
if(ired_high_time>=20)return;
}
gired_data[i] >>= 1;
if(ired_high_time>=8)gired_data[i] |= 0x80;
ired_high_time = 0;
}
}
}
if(gired_data[2] != ~gired_data[3])
{
for(i=0;i<4;i++)
gired_data[i] = 0;
return;
}
}
}
主函数
#include "public.h"
#include "smg.h"
#include "ired.h"
void main()
{
//存储三位十六进制键值段码值数组
u8 ired_buf[3];
//启用外部中断函数
ired_init();
while(1)
{
//以十六进制显示键值,第三位固定为H
ired_buf[0] = gseg_code[gired_data[2]/16];
ired_buf[1] = gseg_code[gired_data[2]%16];
ired_buf[2] = 0x76;
seg_display(ired_buf, 6);
}
}