STM32外设系列—红外遥控

news2024/11/16 16:56:53

文章目录

  • 一、红外遥控简介
  • 二、红外遥控的原理
  • 三、二进制脉冲编码
    • 3.1 NEC码的位定义
    • 3.2 NEC遥控指令的数据格式
  • 四、红外遥控程序设计思路
  • 五、红外遥控程序设计
    • 5.1 红外遥控初始化程序
    • 5.2 记录高电平持续时间函数
    • 5.3 中断服务函数
    • 5.4 读取键值
    • 5.5 参数定义
  • 六、应用实例

一、红外遥控简介

红外遥控,顾名思义,就是利用红外线实现遥控。这里就不单独对红外线做介绍了,红外线的波长再可见光范围外,所以人眼是看不到的。红外遥控的原理就是利用红外线进行通讯,比如生活中常用的电视遥控器,空调遥控器等,大多都是红外通讯实现的遥控功能。

二、红外遥控的原理

红外遥控是一种非接触,无线控制技术。具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等特点。红外遥控系统一般有红外发射装置和红外接收设备两大部分组成。

  • 红外发射装置就是我们常见的遥控器,由键盘电路,红外编码电路,电源电路和红外发射电路组成。
  • 红外接收设备是由红外接收电路,红外解码,电源和应用电路组成。红外接收装置有三个引脚,VDD,GND和数据输出VOUT。通常正对接收头凸起处看,从左到右引脚顺序为VOUT,GND,VDD

红外遥控模块

通常红外遥控为了提高抗干扰性能和降低电源消耗,红外遥控器常用载波的方式传送二进制编码,常用的载波频率为38kHz,这是由发射端所使用的455kHz晶振来决定的。在发射端要对晶振进行整数分频,分频系数一般取12,所以为38kHz。也有一些遥控系统采用36kHz、40 kHz、56 kHz等,一般由发射端晶振的振荡频率来决定。所以,通常的红外遥控器是将遥控信号(二进制脉冲码) 调制在38KHz的载波上,经缓冲放大后送至红外发光二极管,转化为红外信号发射出去的。

三、二进制脉冲编码

二进制脉冲码的形式有多种,其中最为常用的是NEC Protocol 的PWM码(脉冲宽度调制)和 Philips RC-5 Protoco 的 PPM码(脉冲位置调制码,脉冲串之间的时间间隔来实现信号调制)。如果要开发红外接收设备,一定要知道红外遥控器的编码方式和载波频率,才可以选取一体化红外接收头和制定解码方案。这里针对NEC编码形式做一个详细介绍。NEC编码形式有以下特点

  • 8 位地址和 8 位指令长度
  • 地址和命令 2次传输(确保可靠性)
  • PWM 脉冲位置调制,以发射红外载波的占空比代表“ 0”和“1”
  • 载波频率为 38Khz
  • 位时间为 1.125ms 或 2.25ms

3.1 NEC码的位定义

一个脉冲对应 560us 的连续载波,一个逻辑1传输需要 2.25ms(560us脉冲+1680us 低电平) ,一个逻辑 0的传输需要 1.125ms (560us脉冲+560us 低电平)。而红外接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为: 逻辑 1应该是 560us 低+1680us 高,逻辑 0 应该是 560us 低+560us 高。所以可以通过计算高电平时间判断接收到的数据是0还是1。NEC码位定义时序图如下

逻辑0和逻辑1的时序图

3.2 NEC遥控指令的数据格式

NEC遥控指令的数据格式为:引导码、地址码、地址反码、控制码控制反码。引导码由一个 9ms 的低电平和一个 4.5ms 的高电平组成地址码、地址反码、控制码、控制反码均是8 位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性 (可用于校验)。数据格式如下

NEC遥控指令数据格式

NEC码还规定了连发码(由 9ms 低电平+2.5m 高电平+0.5ms 低电平+97.94ms 高电平组成),如果在一帧数据发送完毕之后,红外遥控器按键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数。

四、红外遥控程序设计思路

红外发射装置只需要按键按下即可产生红外信号,我们只需要针对红外接收设备编写程序即可。上面介绍了,红外接收设备在收到脉冲的时候为低电平,在没有脉冲的时候为高电平。根据“0”和“1”的时序图可知,我们只需要监测红外接收设备的数据输出引脚的高电平持续时间就可以判断接收到的是“0”还是“1”。

另外,没有按键按下时,也就是没有发红外信号,没有脉冲,红外接收设备的数据输出引脚一直为高电平。只有接收到脉冲时,说明有按键按下,此时红外接收设备的数据输出引脚为低电平。因此,可以利用外部中断的下降沿出发来判断是否有按键按下,在中断中测量高电平持续时间来判断接收到的是“0”还是“1”。

五、红外遥控程序设计

5.1 红外遥控初始化程序

需要初始化GPIO和外部中断,GPIO配置为上拉输入模式

/*
 *==============================================================================
 *函数名称:Drv_Hw_Init
 *函数功能:初始化红外遥控模块
 *输入参数:无
 *返回值:无
 *备  注:红外端口初始化函数,时钟端口及外部中断初始化
 *==============================================================================
 */
void Drv_Hw_Init (void)
{
	// 结构体定义
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);

	// 配置GPIO结构体
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;   // 红外接收
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;   // 上拉输入模式
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);   // 选择GPIO管脚用作外部中断线路
	EXTI_ClearITPendingBit(EXTI_Line11);
	
	// 配置外部中断
	EXTI_InitStructure.EXTI_Line=EXTI_Line11;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure); 

	// 配置NVIC结构体
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   // 抢占优先级为0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;   // 响应优先级为1
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   // 使能
	NVIC_Init(&NVIC_InitStructure);
}

5.2 记录高电平持续时间函数

利用记录延时次数的方法测量高电平持续时间

/*
 *==============================================================================
 *函数名称:Drv_Hw_RecordHightTime
 *函数功能:记录高电平持续时间并返回
 *输入参数:无
 *返回值:t:高电平持续时间
 *备  注:无
 *==============================================================================
 */
u8 Drv_Hw_RecordHightTime (void)
{
	u8 t = 0;
	while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 1)   // 高电平
	{
		t ++;
		delay_us(20);
		if(t >= 250)
		{
			return t;   // 超时溢出
		}
	}
	return t;
}

5.3 中断服务函数

中断服务函数中接收数据,接收完成后对应的接收完成标志位置1

/*
 *==============================================================================
 *函数名称:EXTI15_10_IRQHandler
 *函数功能:外部中断服务函数
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void EXTI15_10_IRQHandler(void)   // 红外遥控外部中断
{
	u8 Tim = 0,Ok = 0,Data,Num = 0;

   while(1)
   {
	   	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 1)
		{
			 Tim = Drv_Hw_RecordHightTime();   //获得此次高电平时间

			 if(Tim>=250)
			 {
				 break;   // 不是有用的信号
			 }

			 if(Tim >= 200 && Tim < 250)
			 {
			 	Ok = 1;   // 收到起始信号
			 }
			 else if(Tim >= 60 && Tim < 90)
			 {
			 	Data = 1;   // 收到数据 1
			 }
			 else if(Tim >= 10 && Tim < 50)
			 {
			 	Data = 0;   // 收到数据 0
			 }
			 
			 if(Ok == 1)
			 {
			 	hw_jsm <<= 1;
				hw_jsm += Data;

				 // 接收完成
				if(Num >= 32)
				{
					hw_jsbz = 1;
				  	break;
				}
			 }
			 Num ++;
		}
   }
	 
	 // 清除中断标志位
   EXTI_ClearITPendingBit(EXTI_Line11);	
}

5.4 读取键值

判断键盘上按下的是哪个按键。不同的遥控器,按键对应的红外编码可能不同,可以通过串口打印接收到的键值的方法来读出每一个按键的键值。

/*
 *==============================================================================
 *函数名称:Med_Hw_ReadKeyValue
 *函数功能:读取键值
 *输入参数:无
 *返回值:红外键值
 *备  注:每一个键值是测试出来的,不同遥控器键值可能不同
 *==============================================================================
 */
u8 Med_Hw_ReadKeyValue (void)
{
	if(hw_jsm == 0x00FF9867)
	{
		return 0;
	}
	else if(hw_jsm == 0x00FFA25D)
	{
		return 1;
	}
	else if(hw_jsm == 0x00FF629D)
	{
		return 2;
	}
	else if(hw_jsm == 0x00FFE21D)
	{
		return 3;
	}
	else if(hw_jsm == 0x00FF22DD)
	{
		return 4;
	}
	else if(hw_jsm == 0x00FF02FD)
	{
		return 5;
	}
	else if(hw_jsm == 0x00FFC23D)
	{
		return 6;
	}
	else if(hw_jsm == 0x00FFE01F)
	{
		return 7;
	}
	else if(hw_jsm == 0x00FFA857)
	{
		return 8;
	}
	else if(hw_jsm == 0x00FF906F)
	{
		return 9;
	}
	else if(hw_jsm == 0x00FF6897)   // 按键*按下
	{
		return 10;
	}
	else if(hw_jsm == 0x00FFB04F)   // 按键#按下
	{
		return 11;
	}
	else if(hw_jsm == 0x00FF38C7)   // 按键OK按下
	{
		return 12;
	}
	
	else if(hw_jsm == 0x00FF18E7)   // 按键"上"按下
	{
		return 13;
	}
	else if(hw_jsm == 0x00FF4AB5)   // 按键"下"按下
	{
		return 14;
	}
	else if(hw_jsm == 0x00FF10EF)   // 按键"左"按下
	{
		return 15;
	}
	else if(hw_jsm == 0x00FF5AA5)   // 按键"右"按下
	{
		return 16;
	}
	return 17;
}

5.5 参数定义

定义了以下两个参数

u32 hw_jsm;	  // 定义一个32位数据变量,保存接收码
u8 hw_jsbz;  // 定义一个8位数据的变量,用于指示接收标志

六、应用实例

利用红外遥控控制LED的亮灭,按下“1”点亮,按下“0”熄灭。每次执行完对应按键的内容后,需要清除接收完成标志位和接收码。main函数如下

u8 gHwKeyValue = 0;   // 红外键值

int main(void)
{
	Med_Mcu_Iint();   // 系统初始化
	
	while(1)
  {
		if (hw_jsbz == 1)
		{
			// 获取红外键值
			gHwKeyValue = Med_Hw_ReadKeyValue();
			
			// 按下按键“1”
			if (gHwKeyValue == 1)
			{
				// 点亮LED
				Med_Led_StateCtrl(LED1,LED_ON);
			}
			// 按下按键“0”
			if (gHwKeyValue == 0)
			{
				// 熄灭LED
				Med_Led_StateCtrl(LED1,LED_OFF);
			}
			
			hw_jsbz = 0;   // 清除接收完成标志位
			hw_jsm = 0;   // 清零接收码
		}
	}
}

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

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

相关文章

ADB原理,常用命令汇总及示例

一. ADB简介 ADB&#xff0c;即 Android Debug Bridge 是一种允许模拟器或已连接的 Android 设备进行通信的命令行工具&#xff0c;它可为各种设备操作提供便利&#xff0c;如安装和调试应用&#xff0c;并提供对 Unix shell&#xff08;可用来在模拟器或连接的设备上运行各种…

基于Java+SpringBoot+vue的食品安全管理系统设计与实现

博主介绍&#xff1a;✌擅长Java、微信小程序、Python、Android等&#xff0c;专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 Java项目精品实战案…

基于Java+Vue前后端分离网络教学平台设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

Ubuntu连不上网,在windows安装docker后

在windows上安装docker后&#xff0c;会依赖于virtualbox虚拟机&#xff0c;并且有虚拟网络&#xff0c;与ubuntu虚拟机网络产生冲突。 解决办法&#xff0c;打开网络适配器&#xff0c;禁用VirtualBox网络 这个时候就可以了。 ubuntu上使用docker pull镜像的时候&#xff0c…

线性代数克莱姆法则的几何含义

以二元一次方程组的求解为例&#xff1a; { a c a 1 b c b 1 c 1 a c a 2 b c b 2 c 2 \left\{\begin{array}{l} a_{c}a_{1} b_{c}b_{1} c_{1} \\ a_{c}a_{2} b_cb_{2} c_{2} \end{array}\right. {ac​a1​bc​b1​c1​ac​a2​bc​b2​c2​​ 其中 a c a_c ac​和 b c b_…

【Lua】ZeroBrane Studio免费专业IDE使用详解

▒ 目录 ▒ &#x1f6eb; 问题描述环境 1️⃣ IDE界面说明项目目录编辑器控制台窗口输出窗口选择解释器堆栈窗口监视窗口大纲窗口 2️⃣ 调试程序3️⃣ 自定义lua解释器编译自己的lua解释器增加interpreters配置文件重启IDE 4️⃣ 其它IDE比较Lua EditorVSCode &#x1f6ec; …

精密电阻的丝印识别方法

在PCB上经常会出现一些精密的电阻丝印和普通的电阻的丝印识别方式不太一样&#xff0c;比如图1所示。 图1 这种电阻的丝印主要是由两部分组成&#xff0c;第一部分是两个数字&#xff0c;第二部分是一个字母&#xff0c;电阻的阻值的计算就是根据这这个丝印编码。例如图2中的丝…

css中鼠标悬停和点击触发样式变换(:hover和:active)

效果 代码 /*hover--光标&#xff08;鼠标指针&#xff09;悬停在元素上时触发*/ .el-card:hover{background: #f5f5f6; } /*active--按下按键和松开按键之间的时间触发*/ .el-card:active{background: #e0dfdf; }

Linux--管道文件:|

作用&#xff1a; 传输资源&#xff0c;你现在可以单纯的把资源看作是数据 》管道的作用是传导数据 构成&#xff1a;入口与出口 存储&#xff1a; 内存级的文件&#xff0c;没有在磁盘上&#xff01;

Emacs之sr-speedbar替代neotree显示目录(一百一十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【Linux进程】进程优先级和其他概念 {查看进程优先级,PRI和NI,修改进程优先级;竞争性,独立性,并发和并行,进程上下文}

进程优先级和其他概念 一、进程优先级 1.1 基本概念 什么是优先级&#xff1f; 进程的优先权&#xff08;priority&#xff09;就是用来确定CPU资源分配的先后顺序的。进程的优先级是调度器调度进程到CPU执行的重要指标。 为什么要存在优先级&#xff1f; 由于CPU资源有限…

注册登录账号系统

目录 前言 一、项目介绍 二、项目分析 1.框架介绍 框架流程图&#xff1a;​ 板块分析&#xff1a; 前提&#xff1a; &#xff08;1&#xff09;注册板块 &#xff08;2&#xff09;登录板块 &#xff08;3&#xff09;main方法主板块 2.实操展示 &#xff08;1&#x…

并发List:CopyOnWriteArrayList

CopyOnWriteArrayList 适合写多读少 介绍 JUC包中的并发List只有CopyOnWriteArrayList。CopyOnWriteArrayList是一个线程安全的ArrayList&#xff0c;使用了写时复制策略&#xff0c;对其进行的修改操作都是在底层的一个复制的数组上进行的。 CopyOnWriteList 实现的接口和 Ar…

async异步任务_同步任务选项

需要先看完上文&#xff1a;async创建异步任务_御坂美琴1的博客-CSDN博客 让类里面的一个成员函数当作线程的参数。 async里面有三个参数&#xff0c;一个是成员函数的地址&#xff0c;第二个是 类&#xff0c;第三个是传入的参数。 接下来介绍async的同步线程创建。 asy…

C++类Day2,作业思维

1.昨天的基础上完成运算符重载 #include <iostream> using namespace std;class Complex { private:int real;int vir; public://无参构造Complex(){cout << "无参构造" << endl;}//有参构造Complex(int a,int b):real(a),vir(b){cout << &q…

Ubuntu18.04本地部署Stable-Diffusion-webui绘画

记录Ubuntu下安装Stable-Diffusion-webui&#xff0c;比较简单,以供参考。 系统&#xff1a;Ubuntu 18.04.4 LTS 内存&#xff1a;40G 显卡&#xff1a;32G 硬盘&#xff1a;500G 一、安装cuda 支持安装的cuda版本可以用nvidia-smi命令查看&#xff1a; ----------------…

Tomcat的优化及多实例部署

文章目录 一.Tomcat的优化1.tomcat启动速度优化——random2.Tomcat配置文件参数优化2.1 常用的优化相关参数2.2 优化的配置文件 二.Tomcat多实例部署1.为什么会有tomcat多实例部署2.多实例部署图示3.多实例部署的配置3.1 安装JDK3.2 安装启动Tomcat3.3 配置 tomcat 环境变量3.4…

筹码分布图高级用法——历史换手衰减系数自动计算公式

在使用筹码分布图时&#xff0c;很多人习惯于采用软件的默认设置&#xff0c;然而默认设置不一定能满足我们的要求。今天将向大家介绍筹码分布图的高级用法——历史换手衰减系数&#xff0c;并编写历史换手衰减系数自动计算公式。有些网友认为通过修改衰减系数&#xff0c;可以…

【远程控制】向日葵连接Ubuntu黑屏

Ubuntu 远程黑屏 Ubuntu 22.04 方法 1&#xff1a;切换桌面工作模式方法 2&#xff1a;安装 lightdm 插件来渲染界面客服工单回答 Ubuntu 22.04 方法 1&#xff1a;切换桌面工作模式 进入到登录页 点击用户名 点击右下角&#xff0c;切换桌面工作模式为Ubuntu on xorg即可 …

基于Python+MySQL所写的音乐网管理系统

点击以下链接获取源码资源&#xff1a; https://download.csdn.net/download/qq_64505944/87971719?spm1001.2014.3001.5503 《甜橙音乐网》程序使用说明 在虚拟环境下输入命令“python manage.py runserver”启动项目&#xff0c;启动成功后&#xff0c;访问“http://127.0…