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

您所在的位置:网站首页 无人机遥控设置与调试教程 51单片机(十七)红外遥控(外部中断)

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

2023-05-22 05:16| 来源: 网络整理| 查看: 265

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括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 #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 /** * @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 #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); //定时计数器清0 Timer0_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 IR_RepeatFlag=1; //置收到连发帧标志位为1 Timer0_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 IR_Data[IR_pData/8]|=(0x01 IR_pData=0; //数据位置指针清0 if((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 #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 #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~99 if(Counter Motor=0; //输出0 } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3