51单片机学习--红外遥控(外部中断)

在这里插入图片描述


需要利用下面这个红外接收头,OUT口会发出红外信号对应的高低电平,由于发送的速度很快,所以需要把OUT引脚接在外部中断引脚上,当OUT一旦产生下降沿,马上进中断,这样响应会更及时。
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
外部中断引脚位于P3_2和P3_3,我的开发板把OUT接在了P3_2,利用的是下降沿触发。
外部中断比定时器中断和串口中断要简洁一些,这里使用外部中断0(Int0),当IT0=1就是下降沿触发,IT0=0就是低电平触发。
IE0为中断标志位,EX0为此中断的使能,EA为所有中断的使能,PX0设置优先级。
外部中断1(Int1)也是同理。
图中红框框出的才是控制外部中断的。

在这里插入图片描述
首先来配置外部中断:

void Int0_Init(void)
{//配置外部中断IT0 = 1;      //选择下降沿触发IE0 = 0;      //中断标志位EX0 = 1;      //外部中断0使能EA = 1;       //中断使能PX0 = 1;      //优先级
}/* @brief 外部中断函数
void Int0_Routine(void) interrupt 0
{}
*/


在这里插入图片描述


高低电平的组合、持续时长构成了NEC编码:下面的波形就是OUT口会输出的波形。
Data中的反码可以进行数据验证。
在遥控器上按下一个按键之后,先发送一个start波形,然后发送Data,如果按住按键一直不放手,每过110ms就会发送一次repeat,相当于连续按键功能。

在这里插入图片描述
这里遥控器按键的命令码如下:
在这里插入图片描述


接下来编写红外解码的程序,主要的思路是:
建立一个IR.c红外解码模块,这个模块中利用Int0.c和Timer0.c来进行解码。
具体的解码方式:
首先定义一个变量表示当前的状态,用0来表示空闲状态,当收到下降沿时,转为1状态(1状态定义为:分辨是start还是repeat)并将定时器打开,当1状态又收到一个下降沿时,读出定时器的时长判断是start还是repeat。
如果判断为start,转为2状态(2状态定义为:开始解码32bit的Data)2状态会执行32次,数据读完之后回到0状态
如果判断为repeat,则把重发标志位的变量置1并转回0状态



所以首先要对之前写的Timer0模块进行一些改写。这次的目的不是让定时器计数进中断了,而是让它单纯的计时,下面就是改写后的Timer0.c,可以设定计时器的初始值,返回计时器的实时值,以及控制计时器的开关,计时器的返回值每多1就代表多走过了1us

#include <REGX52.H>void Timer0_Init(void)		//1毫秒@11.0592MHz
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0x66;		//设置定时初值TH0 = 0xFC;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 0;		//定时器0不计时
}//把16位值放入计数器
void Timer0_SetCounter(unsigned int Value)
{TH0 = Value/256;TL0 = Value%256;
}//返回计数器的值
unsigned int Timer0_GetCounter(void)
{return (TH0<<8) | TL0;
}//选择计时器是否启动,Flag为1则启动
void Timer0_Run(unsigned char Flag)
{TR0 = Flag;
}


接下来就可以编写IR.c了,要注意IR.c中包含了Int0的外部中断函数:
参考之前说的具体的解码方式:
首先定义一个变量表示当前的状态,用0来表示空闲状态,当收到下降沿时,转为1状态(1状态定义为:分辨是start还是repeat)并将定时器打开,当1状态又收到一个下降沿时,读出定时器的时长判断是start还是repeat。
如果判断为start,转为2状态(2状态定义为:开始解码32bit的Data)2状态会执行32次,数据读完之后回到0状态
如果判断为repeat,则把重发标志位的变量置1并转回0状态

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"unsigned int IR_Time;  //计时时长
unsigned char IR_State; //状态unsigned char IR_Data[4]; //分别表示Data的四个字节
unsigned char IR_pData;   //代表每个个字节的对应位 0~31unsigned char IR_DataFlag; //数据接收完成标志位
unsigned char IR_RepeatFlag; //重发标志位
unsigned char IR_Address;
unsigned char IR_Command;void IR_Init(void)
{Timer0_Init();Int0_Init();
}unsigned char IR_GetDataFlag(void)
{if(IR_DataFlag){IR_DataFlag = 0;return 1;}else return 0;
}unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag = 0;return 1;}else return 0;
}unsigned char IR_GetAddress(void)
{return IR_Address;
}unsigned char IR_GetCommand(void)
{return IR_Command;
}void Int0_Routine(void) interrupt 0
{if(IR_State == 0) //空闲{Timer0_SetCounter(0);Timer0_Run(1);IR_State = 1;}else if(IR_State == 1) //判断是start/repeat{IR_Time = Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time > 13500-500 && IR_Time < 13500+500){//startIR_State = 2;}else if(IR_Time > 11250-500 && IR_Time < 11250+500){//repeatIR_RepeatFlag = 1;Timer0_Run(0);IR_State = 0;}}else if(IR_State == 2) //读取Data{IR_Time = Timer0_GetCounter();Timer0_SetCounter(0);if(IR_Time > 1120-500 && IR_Time < 1120+500){//对应位为0IR_Data[(IR_pData/8)] &= ~(0x01<<(IR_pData%8));IR_pData ++;}else if(IR_Time > 2250-500 && IR_Time < 2250+500){//对应位为1IR_Data[IR_pData/8] |= (0x01<<(IR_pData%8));IR_pData ++;}else{//接收到错误信号则重新接收IR_pData = 0;IR_State = 1;}if(IR_pData >= 32){//Data已收完IR_pData = 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;}Timer0_Run(0);IR_State = 0;}}}

Command和Address要想在main中调用,就得封装成相应的Get函数,然后对应红外遥控器按键的键码可以用宏定义,IR.h如下:

#ifndef __IR_H__
#define __IR_H__#define IR_POWER        0x45
#define IR_MODE         0x46
#define IR_MUTE         0x47
#define IR_START_STOP   0x44
#define IR_PREVIOUS     0x40
#define IR_NEXT         0x43
#define IR_EQ           0x07
#define IR_VOL_MINUS    0x15
#define IR_VOL_ADD      0x09
#define IR_0            0x16
#define IR_RPT          0x19
#define IR_USD          0x0D
#define IR_1            0x0C
#define IR_2            0x18
#define IR_3            0x5E
#define IR_4            0x08
#define IR_5            0x1C
#define IR_6            0x5A
#define IR_7            0x42
#define IR_8            0x52
#define IR_9            0x4Avoid IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);#endif


最后在main.c中调用这些函数即可,

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"unsigned char Num;
unsigned char Address, 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) Num --;if(Command == IR_VOL_ADD) Num ++;LCD_ShowNum(2, 12, Num, 3);}}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/34475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全球八分之一的河流受到缺氧影响

一项全球研究发现&#xff0c;世界各地河流中的溶解氧含量低得危险。缺氧的真实发生率可能更高。 小型、低梯度的城市河流&#xff0c;例如图中北卡罗来纳州的那条河流&#xff0c;是最容易缺氧的河流之一。图片来源&#xff1a;乔安娜布拉扎克 2023 年 3 月&#xff0c;《卫报…

学生管理系统(Python版本)

class Student:def __init__(self, id, name, age):self.id idself.name nameself.age ageclass StudentManagementSystem:def __init__(self):self.students []def add_student(self, student):self.students.append(student)print("学生信息添加成功&#xff01;&qu…

大脑营行|“福安市华龙教育基金”支持家乡教育事业发展

8月8日&#xff0c;福安市松罗中学举行“福安市华龙教育基金”中考奖学金颁发仪式。福安市松罗乡党委书记钟文、乡长郑仁寿、福安市人民政府教育督导室副科级督导员&#xff08;片区领导&#xff09;陈秦、校长张明亮、各村支部书记、家长代表、受奖学生&#xff0c;校领导班子…

UG NX二次开发(C#)-采用PK函数与NXOpen的效率对比

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、创建一个测试项目2.1 创建工程2.2 添加引用2.3 添加PK函数代码2.4 添加NXOpen.net的代码2.5 在mn函数中调用这两个方法2.6 生成dll3、测试代码3.1 在UG NX11.0中创建一个part3.2 调用tes…

vue中$bus全局事件总线

1.介绍 说明&#xff1a;Vue中&#xff0c;$bus 指的通常是一个全局事件总线&#xff0c;它是一种用于在不同组件之间进行通信的模式。它允许你在一个组件中发出事件&#xff0c;而其他组件可以监听并响应这些事件。 2.main.js 说明&#xff1a;为什么在beforeCreate钩子函数…

@RequestHeader使用

RequestHeader 请求头参数的设置 GetMapping("paramTest/requestHeader")public String requestHeaderTest(RequestHeader("name") String name){return name;} 在Postman的Headers中添加请求头参数&#xff0c;不过貌似不能加中文

实现两个列表对应数值相乘、相除、相加等

实现两个列表对应数值相乘、相除、相加等 利用循环实现两个列表相乘使用zip()方法在Python中实现两个列表相乘使用numpy.multiply()方法在Python中实现两个列表相乘使用map()函数在Python中实现两个列表相乘1、利用循环实现两个列表相乘 for循环遍历两个列表元素&#xff0c;…

基于FPGA的PID算法理论详解(1)

基于FPGA的PID算法理论详解(1) 1 概述 比例-积分-微分(PID)控制是业内最常见的控制算法,在工业控制领域有很高的接受度。PID控制器的广泛应用得益于其在多种操作条件下稳定的性能,以及易操作的特性。工程师可以用简单直观的方式实现PID控制。PID控制有三个基本要件:比…

百川智能发布首个530亿参数闭源大模型,今年追上GPT-3.5

4月官宣创业&#xff0c;6月15日发布第一款7B开源模型&#xff0c;7月11日发布第二款13B、130亿参数开源模型。 平均保持2个月一个版本发布速度&#xff0c;8月8日&#xff0c;百川智能发布了创业以来的首个530亿参数闭源大模型——Baichuan-53B&#xff08;以下简称“53B”&a…

LeetCode 热题 100 JavaScript -- 74. 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非递减顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 …

无涯教程-Perl - glob函数

描述 此函数返回与EXPR匹配的文件的列表,这些文件将由标准Bourne shell进行扩展。如果EXPR未指定路径,请使用当前目录。如果省略EXPR,则使用$_的值。 从Perl 5.6开始,扩展是在内部完成的,而不是使用外部脚本。扩展遵循csh(以及任何派生形式,包括tcsh和bash)的扩展方式,其翻译…

从后往前读取列表的方法

从后往前读取列表的方法 方法1&#xff1a;使用for循环遍历列表时&#xff0c;可以使用reverse()函数将列表反转&#xff0c;然后再遍历。 # 列表 num [0, 1, 2, 3]# 反向遍历 for i in reversed(num):print(i)输出结果&#xff1a; 3 2 1 0方法2&#xff1a;先计算列表长度…

【STM32】小电流FOC驱控一体板(开源)

FOC驱控一体板http://链接: https://pan.baidu.com/s/12HoV9yDlMC5QVGNCJ5tK0w 提取码: 1111 主控芯片stm32f103c8t6 驱动芯片drv8313 三相电流采样 根据B站一个UP主的改的&#xff08;【【自制】年轻人的第一块FOC驱动器】&#xff09;&#xff0c;大多数元器件是0805&…

(第二篇)ansible-kubeadm在线安装单master集群

ansible可以安装的KS8版本如下&#xff1a; 请按照此博客中的内容操作后&#xff0c;才可以通过下面的命令查询到版本。 [rootk8s-master01 ~]# yum list kubectl --showduplicates | sort -r kubectl.x86_64 1.20.0-0 kubern…

Java SpringBoot 加载 yml 配置文件中字典项

实际项目中&#xff0c;如果将该类信息放配置文件中的话&#xff0c;一般会结合Nocas一起使用 将字典数据&#xff0c;配置在 yml 文件中&#xff0c;通过加载yml将数据加载到 Map中 Spring Boot 中 yml 配置、引用其它 yml 中的配置。# 在配置文件目录&#xff08;如&#xff…

第一百一十一回 如何实现屏幕适配

文章目录 概念介绍实现方法示例代码 我们在上一章回中介绍了动画相关的内容&#xff0c;本章回中将介绍 如何适配屏幕.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们平常使用的手机屏幕大小不同&#xff0c;App运行在这些大小不同的屏幕上时效果却相同&…

ArcGIS Pro实践技术应用——暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用全流程科研能力提升

查看原文>>>ArcGIS Pro实践技术应用——暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合能力 本文将利用ArcGIS Pro 将您的 GIS 工作组织到工程中&#xff0c;您可以使用 ArcGIS Pro 映射 2D 和 3D 数据。借助 ArcGIS Pro&#xff…

阿里云FRP内网穿透挂载多台服务器

1. FRP介绍 FRP (Fast Reverse Proxy) 是比较流行的一款。FRP 是一个免费开源的用于内网穿透的反向代理应用&#xff0c;它支持 TCP、UDP 协议&#xff0c; 也为 http 和 https 协议提供了额外的支持。你可以粗略理解它是一个中转站&#xff0c; 帮你实现 公网 ←→ FRP(服务器…

全国各地区数字经济工具变量-文本词频统计(2002-2023年)

数据简介&#xff1a;本数据使用全国各省工作报告&#xff0c;对其中数字经济相关的词汇进行词频统计&#xff0c;从而构建数字经济相关的工具变量。凭借数字经济政策供给与数字经济发展水平的相关系数的显著性作为二者匹配程度的划分依据&#xff0c;一定程度上规避了数字经济…

leetcode做题笔记74搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非递减顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 思…