江科大51单片机学习笔记之红外遥控

本文围绕51单片机红外遥控展开,介绍了红外遥控的原理、硬件电路、NEC编码等知识,还阐述了51单片机的外部中断。通过两个实验,分别实现了LCD显示遥控器信息和用遥控器控制电机转速,详细说明了实验步骤,包括创建文件、初始化、测试等内容。

(加三个链接,其余完成)

一、红外遥控简介

•红外遥控是利用红外光进行通信的设备,由红外LED将调制后的信号发出,由专用的红外接收头进行解调输出

•通信方式:单工,异步

•红外LED波长:940nm(人眼看不见)

•通信协议标准:NEC标准

二、硬件电路
红外发送部分
image-20230731195439810

上左图,两个输入端,一个接38KHZ的方波,另一个直接接输入信号,两个NPN型的三极管,低电平导通。IN高电平,LED不亮,IN低电平时,LED是以38KHZ的频率闪着亮,目的是为了抗干扰

上右图,简化版,通过程序控制在IN口输入左下角的波形

红外接收部分
image-20230731200715509

这是一体化的红外接收头的电路,其OUT口可以直接输出高低电平,在其内部会将38KHZ的波形给滤掉。在实际使用中,将OUT连接到外部中断,因为红外接收处理波形对实时性要求比较高(高低电平的宽度较短,只有几百微妙)。上右图是开发板上的红外接收部分的原理图

三、基本发送与接收

•空闲状态:红外LED不亮,接收头输出高电平(接收头没有接收到任何信号)

•发送低电平:红外LED以38KHz频率闪烁发光,接收头输出低电平(将38KHZ的波形过滤掉)

•发送高电平:红外LED不亮,接收头输出高电平

image-20230731201543918
四、NEC编码

NEC编码解决的问题就是怎么去表示数据

image-20230727162354103

注:该波形是接收端OUT端口的波形

按键按下时,输出Start信号,该信号是由9ms的低电平和4.5ms的高电平组成

之后是数据区,共32位,格式如上图(反码的目的是进行数据的校验)

这里的数据表示方式和传统的低电平表示0高电平表示1不同,根据上图,低电平560us高电平560us时表示0,低电平560us高电平1690us时表示1

Repeat是支持按键长按的功能,每隔110ms就会发送这样的波形(如果一直按着按键不松手的话)

实际波形图如下:

image-20230727165237810

以按下KEY2为例,首先是Start波形,之后是8位的地址码0000 0000,接着是地址码的反码1111 1111,之后是指令码0110 0010,最后是指令码的反码1001 1101。指令码0110 0010为0x46,与KEY2键码对应。

遥控器键码如下:

image-20230727165654124
五、51单片机的外部中断

具体可见中断章节:江科大51单片机学习笔记之定时器与中断系统_rebened小橙的博客-优快云博客

•STC89C52有4个外部中断

•STC89C52的外部中断有两种触发方式: 下降沿触发和低电平触发(不支持上升沿触发和高电平触发)

封装图

image-20230727164804086

本单片机只使用了两个外部中断,本开发板使用了外部中断0(连接到了P32引脚)

外部中断寄存器:

image-20230731202942087

以INT0为例,触发方式有IT0决定(IT0为1时是下降沿触发,IT0为0时是低电平触发),IE0是中断标志位,当其为1时表示触发了该中断,EX0是中断使能,EA也是中断使能(所有中断),PX0是配置中断优先级的,配置完后便课触发中断。

六、实验1

现象:LCD屏幕显示遥控器的地址吗、按键的命令码以及自定义的变量Num。按下遥控器上的按键,LCD上显示的值也会随之发生改变。按VOL+键Num值会加,按VOL-键Num值会减,且支持长按。

1、创建文件

思路:创建文件IR.cInt0.c及其头文件。IR.c用于存放红外解码相关程序,Int0.c用于存放外部中断0的相关程序

波形时间宽度的计算:使用定时器0来计算波形高电平或低电平的宽度。本来定时器0中的计数器达到设定值时会触发中断,现在定时器0只当做计数器,不触发中断,通过计数器来计算电平宽度。例如,在下降沿时开启计数器,在上升沿时记录计数器的值,二者的差值除以频率就是这段低电平的时间长度。通过计算高低电平的宽度来判断这个信号是Start信号、0信号、1信号还是Repeat信号

(先将相关文件先添加至项目中)

2、外部中断初始化

编写Int0.c文件以及头文件

/**
  * @brief  外部中断0初始化
  * @param  无
  * @retval 无
  */
void Int0_Init(void)
{
   
   
	IT0 = 1;//下降沿触发
	IE0 = 0;//中断标志位清零,也可以不设置
	//中断打开
	EX0 = 1;
	EA = 1;
	PX0 = 1;//高优先级
}
3、修改定时器函数

参考之前的中断章节

修改Timer.hTimer.c

不需要定时器0来触发中断,故将中断部分直接注释掉,并且TR0先置为0,之后再手动开启计数

#include <REGX52.H>

/**
  * @brief  定时器0初始化
  * @param  无
  * @retval 无
  */
void Timer0Init(void)		
{
   
   
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0不计时,先不启动
	/*
	//中断
	ET0 = 1;//使能T0中断
	EA = 1;
	PT0 = 0;//设置中断优先级,为低优先级
	*/
}

/**
  * @brief  定时器0设置计数器值
  * @param  Value,要设置的计数器值,范围:0~65535
  * @retval 无
  */
void Timer0_SetCounter(unsigned int Value)
{
   
   
	TH0=Value/256;//取高8位
	TL0=Value%256;//取低8位
}

/**
  * @brief  定时器0获取计数器值
  * @param  无
  * @retval 计数器值,范围:0~65535
  */
unsigned int Timer0_GetCounter(void)
{
   
   
	return (TH0<<8)|TL0;//将两个寄存器的值赋值到一个16位的变量上
}

/**
  * @brief  定时器0启动停止控制
  * @param  Flag 启动停止标志,1为启动,0为停止
  * @retval 无
  */
void Timer0_Run(unsigned char Flag)
{
   
   
	TR0=Flag;
}

/*
//定时器0的中断处理函数
void Timer0_Routine() interrupt 1
{
	static unsigned int count = 0;
	//重新赋值计数器,因为计数器溢出后会变为0,要1ms产生一次中断,需要重新给计数器赋值为64535
	TL0 = 0x9C;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	//1ms产生一次中断,每次中断count+1,1000次后再进行处理,此时处理的时间间隔就为1s
	count++;
	if(count >= 1000)
	{
		count = 0;
		P2_0 = ~P2_0;
	}
	
}
*/
4、测试

测试定时器0的计数功能是否正常

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer.h"

unsigned int Time;

void main()
{
   
   
	LCD_Init();
	Timer0Init();
	Timer0_SetCounter(0);
	Timer0_Run(1);
	Delayms(10);
	Time=Timer0_GetCounter();
	LCD_ShowNum(
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值