51单片机(十七)红外遥控(外部中断)

news/2024/12/23 6:28:56/

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。

⭐️ 专栏主要内容: 主要学习51单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v

本学习过程参考:https://space.bilibili.com/383400717

单片机安装软件、各种资料以及源码的路径:
https://pan.baidu.com/s/1vDTN2o8ffvczzNQGfyjHng
提取码:gdzf

本节主要介绍学习红外遥控(外部中断)的相关知识,包括红外遥控(外部中断)介绍、本节目标等;并利用两个小实验来写程序进行练习,分别是红外遥控以及 红外遥控电机调速,最后附上相关代码。

文章目录

  • 一、红外遥控和本节目标
    • 1.1 红外遥控基础知识
    • 1.2 51单片机的外部中断
    • 1.3 本节目标
  • 二、红外遥控
  • 二、红外遥控电机调速

一、红外遥控和本节目标

1.1 红外遥控基础知识

红外遥控简介

在这里插入图片描述

硬件电路
在这里插入图片描述

基本接收与发送

在这里插入图片描述

NEC编码

在这里插入图片描述
遥控器并不会直接发送0还是1;而是根据时间的长短来进行判断是0还是1;如上图中,560us+560us这个周期表示0;560us+1690us这个周期表示1;

下图是示波器输出的遥控器各个键码的按下时的波形,可以看出来跟上面我们分析的时序图(NEC编码)是一致的;
在这里插入图片描述
遥控器键码

在这里插入图片描述

1.2 51单片机的外部中断

在这里插入图片描述

在这里插入图片描述

1.3 本节目标

目标1:红外遥控

LCD1602上显示遥控器地址码、遥控器控制码,以及自定义数字;
在这里插入图片描述
例如,当按下遥控器的开关键,如下图:
在这里插入图片描述

则LCD1602上的控制码会显示45,因为该键的控制码就是45:

在这里插入图片描述

另外,使用遥控器上的VOL+和VOL-控制我们自定义数字的加和减:
在这里插入图片描述
当按下VOL+时,自定义数字往上增加,按下VOL-时,自定义数字减少,例如当按下VOL+时:
在这里插入图片描述

目标2:红外遥控电机调速
用遥控器的0 、 1、 2、 3等按键对电机进行调速;
按0,电机停:
在这里插入图片描述
按1和2和3,则分别按照1速度、2速度、3速度转:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、红外遥控

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\17-1 红外遥控(11.0592MHz晶振)

具体代码:

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"ADDR  CMD  NUM");LCD_ShowString(2,1,"00    00   000");IR_Init();while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag())	//如果收到数据帧或者收到连发帧{Address=IR_GetAddress();		//获取遥控器地址码Command=IR_GetCommand();		//获取遥控器命令码LCD_ShowHexNum(2,1,Address,2);	//显示遥控器地址码LCD_ShowHexNum(2,7,Command,2);	//显示遥控器命令码if(Command==IR_VOL_MINUS)		//如果遥控器VOL-按键按下{Num--;						//Num自减}if(Command==IR_VOL_ADD)			//如果遥控器VOL+按键按下{Num++;						//Num自增}LCD_ShowNum(2,12,Num,3);		//显示Num}}
}

Int0.c

#include <REGX52.H>/*** @brief  外部中断0初始化* @param  无* @retval 无*/
void Int0_Init(void)
{IT0=1;IE0=0;EX0=1;EA=1;PX0=1;
}/*外部中断0中断函数模板
void Int0_Routine(void) interrupt 0
{}
*/

IR.c:

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"unsigned int IR_Time;
unsigned char IR_State;unsigned char IR_Data[4];
unsigned char IR_pData;unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;/*** @brief  红外遥控初始化* @param  无* @retval 无*/
void IR_Init(void)
{Timer0_Init();Int0_Init();
}/*** @brief  红外遥控获取收到数据帧标志位* @param  无* @retval 是否收到数据帧,1为收到,0为未收到*/
unsigned char IR_GetDataFlag(void)
{if(IR_DataFlag){IR_DataFlag=0;return 1;}return 0;
}/*** @brief  红外遥控获取收到连发帧标志位* @param  无* @retval 是否收到连发帧,1为收到,0为未收到*/
unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag=0;return 1;}return 0;
}/*** @brief  红外遥控获取收到的地址数据* @param  无* @retval 收到的地址数据*/
unsigned char IR_GetAddress(void)
{return IR_Address;
}/*** @brief  红外遥控获取收到的命令数据* @param  无* @retval 收到的命令数据*/
unsigned char IR_GetCommand(void)
{return IR_Command;
}//外部中断0中断函数,下降沿触发执行
void Int0_Routine(void) interrupt 0
{if(IR_State==0)				//状态0,空闲状态{Timer0_SetCounter(0);	//定时计数器清0Timer0_Run(1);			//定时器启动IR_State=1;				//置状态为1}else if(IR_State==1)		//状态1,等待Start信号或Repeat信号{IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间Timer0_SetCounter(0);	//定时计数器清0//如果计时为13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)if(IR_Time>13500-500 && IR_Time<13500+500){IR_State=2;			//置状态为2}//如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)else if(IR_Time>11250-500 && IR_Time<11250+500){IR_RepeatFlag=1;	//置收到连发帧标志位为1Timer0_Run(0);		//定时器停止IR_State=0;			//置状态为0}else					//接收出错{IR_State=1;			//置状态为1}}else if(IR_State==2)		//状态2,接收数据{IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间Timer0_SetCounter(0);	//定时计数器清0//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)if(IR_Time>1120-500 && IR_Time<1120+500){IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));	//数据对应位清0IR_pData++;			//数据位置指针自增}//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)else if(IR_Time>2250-500 && IR_Time<2250+500){IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));	//数据对应位置1IR_pData++;			//数据位置指针自增}else					//接收出错{IR_pData=0;			//数据位置指针清0IR_State=1;			//置状态为1}if(IR_pData>=32)		//如果接收到了32位数据{IR_pData=0;			//数据位置指针清0if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))	//数据验证{IR_Address=IR_Data[0];	//转存数据IR_Command=IR_Data[2];IR_DataFlag=1;	//置收到连发帧标志位为1}Timer0_Run(0);		//定时器停止IR_State=0;			//置状态为0}}
}

二、红外遥控电机调速

代码路径:51单片机入门教程资料\课件及程序源码\程序源码\KeilProject\17-2 红外遥控电机调速

具体代码:

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Motor.h"
#include "IR.h"unsigned char Command,Speed;void main()
{Motor_Init();IR_Init();while(1){if(IR_GetDataFlag())	//如果收到数据帧{Command=IR_GetCommand();		//获取遥控器命令码if(Command==IR_0){Speed=0;}		//根据遥控器命令码设置速度if(Command==IR_1){Speed=1;}if(Command==IR_2){Speed=2;}if(Command==IR_3){Speed=3;}if(Speed==0){Motor_SetSpeed(0);}	//速度输出if(Speed==1){Motor_SetSpeed(50);}if(Speed==2){Motor_SetSpeed(75);}if(Speed==3){Motor_SetSpeed(100);}}Nixie(1,Speed);						//数码管显示速度}
}

Motor.c:

#include <REGX52.H>
#include "Timer1.h"//引脚定义
sbit Motor=P1^0;unsigned char Counter,Compare;/*** @brief  电机初始化* @param  无* @retval 无*/
void Motor_Init(void)
{Timer1_Init();
}/*** @brief  电机设置速度* @param  Speed 要设置的速度,范围0~100* @retval 无*/
void Motor_SetSpeed(unsigned char Speed)
{Compare=Speed;
}//定时器1中断函数
void Timer1_Routine() interrupt 3
{TL1 = 0x9C;		//设置定时初值TH1 = 0xFF;		//设置定时初值Counter++;Counter%=100;	//计数值变化范围限制在0~99if(Counter<Compare)	//计数值小于比较值{Motor=1;		//输出1}else				//计数值大于比较值{Motor=0;		//输出0}
}

http://www.ppmy.cn/news/70849.html

相关文章

javaIO之字符流

目录 一、简介二、字符流入流1.1FileReader构造方法1.2FileReader读取字符数据 三、字符流出流3.1 FileWriter 构造方法3.2FileWriter写入数据3.3关闭close和刷新flush3.4FileWriter的续写和换行3.5文本文件复制 四、IO异常处理五、小结 一、简介 字符流 Reader 和 Writer 的故…

数据库管理-第七十五期 手把手教你搭19c RAC(20230516)

数据库管理 2023-05-16 第七十五期 手把手教你搭19c RAC1 基础环境2 操作系统配置2.1 /etc/hosts2.2 配置系统挂载2.3 配置本地yum源2.4 操作系统配置2.5 安装预安装RPM包并配置&#xff1a;2.6 创建对应目录2.7 配置时间同步 3 存储挂载3.1 存储环境3.2 存储识别3.3 多路径聚合…

【AI绘图 丨 Midjourney 系列教程二】— 初识超火的AI绘画神器Midjourney

今天起&#xff0c;由 Midjourney 打头阵&#xff0c;让我们开始共同探索一系列的 AI 领域革命性作品&#xff0c;包括 Midjourney、Stable Diffusion、ChatGPT 等等&#xff0c;学习这些新时代的魔法和它的咒语。 写在前面 官方文档是最好的入门课程。相较于市面上琳琅满目的…

Matlab入门教程|002球的体积问题

写给Matlab小白的教程。如果你已经安装了Matlab&#xff0c;手头有一堆Matlab教程&#xff0c;面对书中一堆术语和命令不知所措&#xff0c;那么&#xff0c;请看本教程&#xff0c;从零开始&#xff0c;快速上手。 1 本文要点 初等代数计算&#xff1a;求函数值&#xff0c;求…

本科毕业生10大高薪专业出炉,IT行业赢麻了

据环球网报道&#xff0c;现在大学毕业生转行率高达80%&#xff01; 非常后悔&#xff01;有不少粉丝向播妞倾诉&#xff0c;曾经以为读了大学就能找到体面的工作&#xff0c;实际上是掉入了天坑专业&#xff0c;成了现实版孔乙己。 大学生找不到对口好工作&#xff0c;似乎已成…

能源硕士为何受热捧?社科院与杜兰大学能源管理硕士项目为你解惑

能源行业可谓是全球最具发展前景的行业之一&#xff0c;能源管理硕士更是近几年被争相推荐的“大热门”。广泛的就业选择、较高且稳定的收入&#xff0c;是该专业的特点之一&#xff0c;毕业后可选择在政府相关机构、能源监管部门、全国节能减排领域的各类研究机构工作&#xf…

大模型时代入场级技能:提示词工程!中文教程来啦

写出优质的提示词&#xff0c;让 AI 生成惊艳的图文作品。——这就是如今年薪百万仍一人难求的提示词工程师们在解决的问题。大语言模型时代下&#xff0c;不断涌现出众多让人瞳孔地震的绘画、拍案叫绝的文案&#xff0c;它们的创作者并非传统定义的画家、作家&#xff0c;而是…

腾讯云轻量应用服务器卡死怎么连接?

腾讯云轻量云服务器卡死怎么解决&#xff1f;使用腾讯云自带的VNC登录连接轻量服务器&#xff0c;或使用腾讯云OrcaTerm一键免密登录轻量实例。如果是确定数据没问题&#xff0c;也可以使用控制台自带的重启实例。 腾讯云轻量应用服务器参考&#xff1a;https://curl.qcloud.co…