【51单片机】程序实验17.红外遥控

发布于:2025-03-15 ⋅ 阅读:(19) ⋅ 点赞:(0)

主要参考学习资料: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);
	}
}