通用外设-红外遥控器(NEC协议)

news2025/3/1 11:34:24

目录

前言

一、前期的准备

1. 结构体

2. 中断

1.定时中断

2.外部中断(下降沿中断)

二、功能实现

1.时序说明

2.逻辑实现

3.代码实现

总结


前言

简单介绍红外遥控器的使用,可以正常使用,但是部分功能未启用,给大家抛砖引玉介绍下思路。

环境:正常室内

芯片:STM32F103C8T6

Keil:V5.24.2.0

接收头:VS1838

信号源:配套的遥控器


一、前期的准备

1. 结构体

使用结构体可以方便我们使用全局变量,并且可以增加代码的可读性。

如果没了解的可以看下我之前对结构体的简单介绍:

学习记录6-结构体的应用icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/135315602

上代码:

typedef struct {
//		uint32_t	OLED_Count;
		uint8_t 	ifr_state;//信号的状态
		uint32_t	time_ms;
		uint32_t	time_10us;//10us时间计算
		uint8_t		Trigger_cnt;//case的值计算
		uint8_t		jump_cnt;//在case里进行跳跃计数,跳过1,2,4阶段
		uint8_t		ifr_val;//信号值的计算
	   	 }USER;

extern USER user;

2. 中断

1.定时中断

为方便计算时间使用,我设计为10us进入一次中断。

频繁进入中断,不知道实际精度如何。有大佬能解释下就更好了,不过不影响我们这个实验

上代码:

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 72 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 10-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);

}

void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
		user.time_10us++;
		if(user.time_10us>=100000)
		{
//			user.time_ms ++;
//			user.time_10us = 0;
			user.Trigger_cnt = 0;
		}
		
	}
}

注意点:1.待会还有外部中断,这个抢占优先级一定要高于外部的优先级。

                2.user.Trigger_cnt 变量在下个中断会说明。

        常规计数中断函数,没什么说的了

2.外部中断(下降沿中断)

不啰嗦,上代码:

void IFR_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line1;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);


}

注意点:1.我配置的引脚为A1脚,自己使用时记得和自己的匹配。

                2. 中断触发设置为下降沿触发。

                3.抢占优先级低于计时中断。

二、功能实现

1.时序说明

上时序图:

时序说明:1:第一次进入中断,进入起始码的开始

        2:第二次进入中断,正式进入数据阶段

        3:和2是一处,这边只是方便理解。

        4:和5是一样的,一位数据只会有一次。就是说要么是4要么是5

2.逻辑实现

信号正确的逻辑:

引导码:第一次进入中断到第二次进入中断,时间应该是13.5ms(9+4.5)

数据码:第二次后的每次中断都是一位数据位,就是说第三次和第二次时间间隔,如果为1120us(560+560)就是数据0;如果时间是2520us(560+1690)就是数据1;

数据位数:地址码+地址反码+数据码+命令反码

                每个是8位数据,总共是32位。

3.代码实现

上代码:

void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line1) == SET)
	{
		EXTI_ClearITPendingBit(EXTI_Line1);
		
		if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0)
		{
			user.OLED_Count++;
			switch(user.Trigger_cnt)
			{
				case 0:user.Trigger_cnt++;user.time_10us = 0;break;
				case 1:
					if(user.time_10us>1400)//9ms+4.5ms,时间是1350,这里给了余量
					{
						user.ifr_state = 3;//超时
					}
					else if(user.time_10us>1000)//800同上
					{
						user.ifr_state = 2;	//正常
						user.Trigger_cnt++;
						user.time_10us = 0;
					}
					else
					{
						user.ifr_state = 1;//异常
						user.Trigger_cnt = 0;
					}
					break;
				case 2:
					user.jump_cnt++;
					if(user.jump_cnt >= 16)
					{
						user.Trigger_cnt++;
						user.time_10us = 0;
						user.jump_cnt = 0;
					}
					break;
				case 3:
//					OLED_ShowNum(2, 1, user.jump_cnt, 8);
					user.jump_cnt++;				
					user.ifr_val <<= 1;
				
					if(user.time_10us >= 200)//2000us
					{
						user.ifr_val |= 0x01;
					}					
					user.time_10us = 0;
					if(user.jump_cnt >= 8)
					{
						user.Trigger_cnt++;
						user.jump_cnt = 0;
					}
					break;
				case 4:
					user.jump_cnt++;
					if(user.jump_cnt >= 8)
					{
						user.Trigger_cnt = 0;
						user.jump_cnt = 0;
					}
					break;			
			}			
		}
	}
}

在运行前,验证下是否可以正常进入中断:

user.OLED_Count++;

在显示器上显示这个变量,看看是否能进入,如果值有变化,说明进入中断没有问题。

user.Trigger_cnt:为现在执行的阶段判断,方便进行操作

case 0:第一次进入中断,并对状态进行+1,下次进入第二阶段,对计时数据进行清零。

case 1:第二次进入中断,需要对时间进行计算,计算第一次到现在的时间,按正常时间计算,应该是13500us。如果不对并进行判断,这些代码有些啰嗦了,熟悉后可以精简。

如果正常,状态再次进行+1,进入地址码阶段。

case 2:   

user.jump_cnt++:向大家问下,如何读取全部的32位数据?我是跳过前面的地址码和地址反码。所以用这个进行计数,如果大于16 则进入数据码的读取。

如果大于16,则对状态进行+1,并对一些数据进行清零。

case 3:

					user.ifr_val <<= 1;
				
					if(user.time_10us >= 200)//2000us
					{
						user.ifr_val |= 0x01;
					}

 本文的数据读取

计入8次后进行下一阶段,就是数据反码。我也是直接跳过了。

最后,说下定时中断中进行清零操作:

user.Trigger_cnt = 0;因为理想状态下,接收完一次完整信号后。下次信号就是引导码的开始。但是实际情况比较复杂,造成外部中断状态可能不是在引导码待命。所以我对它进行清零。0.1S没有操作,对状态进行清零。它就在引导码待命了。


总结

本文中可完善地方很多,让大家了解了原汁原味的思考方法。也给大家留了不少坑,后期我尽量把它补全。

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

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

相关文章

风险评估在应对网络安全威胁中扮演着重要的角色

如今&#xff0c;IT 安全专家面临各种重大威胁&#xff0c;从勒索软件、网络钓鱼&#xff0c;到对基础设施的攻击&#xff0c;再到对知识产权、客户数据的窃取&#xff1b;从不安全的供应链合作伙伴&#xff0c;再到组织内部人员的恶意行为。同时&#xff0c;随着云计算、远程工…

关于ASP.NET Core WebSocket实现集群的思考

前言 提到WebSocket相信大家都听说过&#xff0c;它的初衷是为了解决客户端浏览器与服务端进行双向通信&#xff0c;是在单个TCP连接上进行全双工通讯的协议。在没有WebSocket之前只能通过浏览器到服务端的请求应答模式比如轮询&#xff0c;来实现服务端的变更响应到客户端&…

【鹅厂摸鱼日记(二)】(生活篇)初到深圳的人情冷暖

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:重生之我在鹅厂摸鱼⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多知识   &#x1f51d;&#x1f51d; 摸鱼日记 1. 前言2. 鹅厂的人文关怀…

FFmpeg: 简易ijkplayer播放器实现--03UI界面设计

文章目录 UI设计流程图UI设计界面点击播放功能实现 UI设计流程图 UI设计界面 主界面 控制条 播放列表 画面显示 标题栏 设置界面 提示框 点击播放功能实现 槽函数实现&#xff1a; connect(ui->ctrlBarWind, &CtrlBar::SigPlayOrPause, this, &Main…

09 Php学习:数组和排序

数组概念 在PHP中&#xff0c;数组是一种复合数据类型&#xff0c;用于存储多个值。以下是关于PHP数组的详细解释&#xff1a; 索引数组&#xff1a;索引数组是最基本的数组类型&#xff0c;其中每个元素都有一个唯一的数字索引&#xff0c;从0开始递增。 关联数组&#xff…

1、Qt UI控件 -- qucsdk

前言&#xff1a;Qt编写的自定义控件插件的sdk集合&#xff0c;包括了各个操作系统的动态库文件以及控件的头文件和sdk使用demo。类似于Wpf中的LivChart2控件库&#xff0c;都是一些编译好的控件&#xff0c;可以直接集成到项目中。该控件是飞扬青云大神多年前开发的&#xff0…

算法刷题应用知识补充--搜索与图

这里写目录标题 DFS题结 BFS题结 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 DFS 题 知识点1&#xff1a;本题在dfs的for循环搜索中&#xff0c;进行了剪枝&#xff0c;即写一个判断函数&#xff0c;把不符合题意的…

PHP Storm 2024.1使用

本文讲的是phpstorm 2024.1最新版本激活使用教程&#xff0c;本教程适用于windows操作系统。 1.先去idea官网下载phpstorm包&#xff0c;我这里以2023.2最新版本为例 官网地址&#xff1a;https://www.jetbrains.com/zh-cn/phpstorm/ 2.下载下来后安装&#xff0c;点下一步 …

【数据结构与算法】搜索算法(深度优先搜索 DFS和广度优先搜索 BFS)以及典型算法例题

目录 搜索算法&#xff08;深度优先搜索DFS和广度优先搜索BFS&#xff09;以及典型算法例题深度优先搜索 &#xff08;Depth First Search 简称 DFS&#xff09;DFS 的设计步骤深度优先搜索&#xff08;DFS&#xff09;算法例题例题一&#xff1a;N皇后问题例题二&#xff1a;路…

李廉洋;4.11黄金原油盘面走势分析及策略。

在周三公布的美国核心消费者价格指数高于预期后&#xff0c;渣打的策略师现在预计美联储今年只会降息两次&#xff0c;而不是四次。渣打全球G-10外汇研究主管Steve Englander周三在报告中写道&#xff0c;该行预测美联储在2024年将降息两次、每次25个基点&#xff0c;预计降息可…

网页文件批量下载工具有哪些 网页文件批量下载工具推荐 IDM免费激活 网络下载加速器

把任务丢给软件&#xff0c;把时间还给自己&#xff0c;批量下载功能让下载变得更高效。它可以有效减少重复性操作&#xff0c;只需要一次简单的设置&#xff0c;就能把大量文件下载到电脑。有关网页文件批量下载工具有哪些&#xff0c;网页文件批量下载工具推荐的问题&#xf…

2024认证杯数学建模C题思路模型代码

目录 2024认证杯数学建模C题思路模型代码&#xff1a;4.11开赛后第一时间更新&#xff0c;获取见文末名片 以下为2023年认证杯C题&#xff1a; 2024年认证杯数学建模C题思路模型代码见此 2024认证杯数学建模C题思路模型代码&#xff1a;4.11开赛后第一时间更新&#xff0c;获…

云服务器上Docker启动的MySQL会自动删除数据库的问题

一、问题说明 除了常见的情况&#xff0c;例如没有实现数据挂载&#xff0c;导致数据丢失外&#xff0c;还需要考虑数据库是否被攻击&#xff0c;下图 REVOVER_YOUR_DATA 就代表被勒索了&#xff0c;这种情况通常是数据库端口使用了默认端口&#xff08;3306&#xff09;且密码…

Coursera吴恩达《深度学习》课程总结(全)

这里有Coursera吴恩达《深度学习》课程的完整学习笔记&#xff0c;一共5门课&#xff1a;《神经网络和深度学习》、《改善深层神经网络》、《结构化机器学习项目》、《卷积神经网络》和《序列模型》&#xff0c; 第一门课&#xff1a;神经网络和深度学习基础&#xff0c;介绍一…

mac电脑安装软件报错:无法检查更新,请检查你的互联网连接

1、点菜单栏搜索图标&#xff0c;输入&#xff1a;终端 &#xff0c;找到后&#xff0c;点击打开 2、输入以下命令&#xff1a;&#xff08;复制粘贴进去&#xff09;回车安装 /usr/sbin/softwareupdate --install-rosetta --agree-to-license 3、提示【Install of Rosetta …

[dvwa] CSRF

CSRF 0x01 low 跨站&#xff0c;输入密码和确认密码直接写在url中&#xff0c;将连接分享给目标&#xff0c;点击后修改密码 社工方式让目标点击短链接 伪造404页&#xff0c;在图片中写路径为payload&#xff0c;目标载入网页自动请求构造链接&#xff0c;目标被攻击 http…

学习云计算HCIE选择誉天有什么优势?

誉天云计算课程优势实战性强 课程注重实践操作&#xff0c;通过实际案例和实验操作&#xff0c;让学员深入了解云计算的应用场景和实际操作技能。课程内容全面 涵盖所有云计算涉及的IT基础知识、服务器、存储、网络等方面的基础知识&#xff0c;开源操作系统Linux&#xff0c;开…

Java 实例 - 在控制台上输入密码要求其数字和字母混搭等长度限制(Pattern正则表达式)

1.在控制台上输入密码&#xff0c;要求密码由数字和字母混搭&#xff0c;关键词是_&#xff0c;且密码的长度至少1位&#xff0c;不得超过6位 package com.guyu.demo;import java.util.Scanner; import java.util.regex.Pattern;/*** * 2024年4月11日 上午9:57:40* author Guyu…

FPGA开源项目分享——基于 DE1-SOC 的 String Art 实现

导语 今天继续康奈尔大学FPGA课程ECE 5760的典型案例分享——基于DE1-SOC的String Art实现。 &#xff08;更多其他案例请参考网站&#xff1a; Final Projects ECE 5760&#xff09; 1. 项目概述 项目网址 ECE 5760 Final Project 项目说明 String Art起源于19世纪的数学…