STM32学习之红外遥控
基本原理:
发射器采用红外发光二级管发射红外光波;
接收器由红外接收二极管、三极管或硅光电池组成,它们将发射器发射的红外光接收转换为相应的电信号。
但是,我们怎么确定我们按了什么键呢?
在计算机的世界里,世界的真理就是0与1,看,我们定义发射器一个编号,在让接收器只接受这个编号的设备发出的信息,那么两者就有了联系。发射器有不同的按键,我们让每个按键都有不同的编号(键码),每次按键,就发编号,那么接收器上也就能收到不同的编号,我们要做的,就是解码,根据NEC协议这本密码书,解出按了什么键。
红外遥控的NEC协议:载波:38khz,波长940nm
0与1:
如图,0与1这样表示,假如我们把时间放慢1百万倍,接收器先保持了560s的载波,然后保持了560s的空闲,那么相应的就产生了一个逻辑“0”,逻辑"1"也是同样的道理。正常情况下,在电路中,都是一直保持低电平的,而当接收器接收到了红外光波,电路导通,才会有高电平。
有了0,1,选择我们就可以读出发射器的地址编码和按键编码了,这是我们一开始就已经知道的。
我们的NEC密码书是这样读的:
数据格式:引导码+地址码+地址反码+数据码+数据反码
每一次按键,都是这样发出信息的,同时也是这样读取信息的。
引导码是固定的,9ms的载波,其后是4.5ms的空闲
然后就是地址码(遥控器的地址编号),地址反码是为了进一步确认,数据码就是按键编号。当然,读取地址码和数据码都是低位在前的读法。
如上图,地址码为:01011001(0x59) 数据码为:00010110(0x16)
这只是发送一次的正常序列,那我们按着一个键一直发怎么办?
重复码
我们并不是继续发上图的序列来重复发,而是设置了一个专属于重复码的序列,来说明,我要重复!
序列是这样的:
在发射器中,我们以110ms为周期,发射这样的重复码序列,具体如图:
以上就是NEC协议了,就是我们MCU解码发射器的密码书,相当与我们掌握了加减乘除的方法,接着就是具体的使用密码书(解码)。
此实验中,我们定义了一个RmtSta变量,但是作为寄存器使用,还定义了32位的Rmartc,做为接收数据。
bit7 | bit6 | bit5 | bit4 | bit3~0 |
收到引导码标志 | 得到一个按键所有信息标志 | 保留位 | 上升沿捕获标志 | 溢出计数器 |
整个实验,我们采用输入捕获来获取各个电平长度,但是我们只通过记录低电平的电平长度来判断0,1,引导码,重复码。从而进行一系列的判断。
前情提要:通过设置预分频器,计数器1us+1,设置自动重载值10000,10ms溢出
这基本上就是整个解码的顺序图,一定是先走步骤1,再走步骤2,具体怎么走,那要看具体的地址码和数据码是什么了,如果长按,就会发生更新中断,然后就会发生步骤3.
通过以上,我们就获得了32位的接收数据(地址码,地址反码,数据码,数据反码)和按键次数
/*******************************************************************************
* 函数名 : Remote_Init
* 功能 : NEC协议的红外遥控初始化
* 输入 : 无
* 输出 : 无
*******************************************************************************/
#include "remote.h"
#include "delay.h"
#include "usart.h"void Remote_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_ICInitTypeDef TIM_ICInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PORTB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //TIM4 时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PB9 输入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //上拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_9); //初始化GPIOB.9TIM_TimeBaseStructure.TIM_Period = 10000; //设定计数器自动重装值 最大10ms溢出 TIM_TimeBaseStructure.TIM_Prescaler = (72 - 1); //预分频器,1M的计数频率,1us加1. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMxTIM_ICInitStructure.TIM_Channel = TIM_Channel_4; // 选择输入端 IC4映射到TI4上TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频 TIM_ICInitStructure.TIM_ICFilter = 0x03;//IC4F=0011 配置输入滤波器 8个定时器时钟周期滤波TIM_ICInit(TIM4, &TIM_ICInitStructure);//初始化定时器输入捕获通道TIM_Cmd(TIM4, ENABLE); //使能定时器4NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级0级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC4, ENABLE);//允许更新中断 ,允许CC4IE捕获中断
}//遥控器接收状态
//[7]:收到了引导码标志
//[6]:得到了一个按键的所有信息
//[5]:保留
//[4]:标记上升沿是否已经被捕获
//[3:0]:溢出计时器
u8 RmtSta = 0;
u16 Dval; //下降沿时计数器的值
u32 RmtRec = 0; //红外接收到的数据
u8 RmtCnt = 0; //按键按下的次数
//定时器4中断服务程序
void TIM4_IRQHandler(void)
{if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET){if (RmtSta & 0x80) //上次有数据被接收到了{RmtSta &= ~0X10; //取消上升沿已经被捕获标记if ((RmtSta & 0X0F) == 0X00)RmtSta |= 1 << 6; //标记已经完成一次按键的键值信息采集if ((RmtSta & 0X0F) < 14)RmtSta++;else{RmtSta &= ~(1 << 7); //清空引导标识RmtSta &= 0XF0; //清空计数器 }}}if (TIM_GetITStatus(TIM4, TIM_IT_CC4) != RESET){if (RDATA)//上升沿捕获{TIM_OC4PolarityConfig(TIM4, TIM_ICPolarity_Falling); //CC4P=1 设置为下降沿捕获TIM_SetCounter(TIM4, 0); //清空定时器值RmtSta |= 0X10; //标记上升沿已经被捕获}else //下降沿捕获{Dval = TIM_GetCapture4(TIM4); //读取CCR4也可以清CC4IF标志位TIM_OC4PolarityConfig(TIM4, TIM_ICPolarity_Rising); //CC4P=0 设置为上升沿捕获if (RmtSta & 0X10) //完成一次高电平捕获 {if (RmtSta & 0X80)//接收到了引导码{if (Dval > 300 && Dval < 800) //560为标准值,560us{RmtRec <<= 1; //左移一位.RmtRec |= 0; //接收到0 }else if (Dval > 1400 && Dval < 1800) //1680为标准值,1680us{RmtRec <<= 1; //左移一位.RmtRec |= 1; //接收到1}else if (Dval > 2100 && Dval < 2500) //得到按键键值增加的信息 2250为标准值2.25ms{RmtCnt++; //按键次数增加1次RmtSta &= 0XF0; //清空计时器 }}else if (Dval > 4200 && Dval < 4700) //4500为标准值4.5ms{RmtSta |= 1 << 7; //标记成功接收到了引导码RmtCnt = 0; //清除按键次数计数器}}RmtSta &= ~(1 << 4);}}TIM_ClearITPendingBit(TIM4, TIM_IT_Update | TIM_IT_CC4);
}
接下来就是对数据进行处理,这一步很简单:
具体代码采用是正点原子的实验代码:
/*******************************************************************************
* 函数名 : Remote_Scan
* 功能 : 对32位解码值处理
* 输入 : 无
* 输出 : 无8位数据值(键码)
*******************************************************************************/
u8 Remote_Scan(void)
{u8 sta = 0;u8 t1, t2;if (RmtSta & (1 << 6))//得到一个按键的所有信息了{t1 = RmtRec >> 24; //得到地址码t2 = (RmtRec >> 16) & 0xff; //得到地址反码 if ((t1 == (u8)~t2) && t1 == REMOTE_ID)//检验遥控识别码(ID)及地址 {t1 = RmtRec >> 8;t2 = RmtRec;if (t1 == (u8)~t2)sta = t1;//键值正确 }if ((sta == 0) || ((RmtSta & 0X80) == 0))//按键数据错误/遥控已经没有按下了{RmtSta &= ~(1 << 6);//清除接收到有效按键标识RmtCnt = 0; //清除按键次数计数器}}return sta;
}
至于main函数,只要用which语句,case用各个按键的键码来识别即可。
———————————————————————————————————————————
参考资料:
1.《STMF1开发指南—库函数版》 正点原子
STM32学习之红外遥控相关推荐
- 51单片机学习:红外遥控实验
实验名称:红外遥控实验 接线说明: 实验现象:下载程序后,数码管上显示数码管上显示红外解码遥控器键值 注意事项:红外接收头凸起处要与PCB板接口凸起丝印处对应 ...
- 我谈学习型红外遥控(一)
跟着项目组长一起做了几个空鼠项目,一直觉得自己长劲不大,因为自己只负责简单的键盘定义部分,最终的整个软件架构其实自己都不太了解.从去年11月份开始,一直都很忙,一个接着一个做,我的任务也只是键盘部分. ...
- 【STM32学习】红外传感器实现——广告自动关闭和自动打开功能
所用硬件设备: 1.电脑 2.STM32嵌入式最小系统--其实51控制成本会更低,也同样稳定.(* ̄︶ ̄) 3.HC-SR501 RD-624人体红外感应电子模块 淘宝上多的一塌糊涂,几块钱即可购买 ...
- STM32单片机智能语音温控摇头电风扇落地扇可红外遥控可PWM调速定时温度显示
实践制作DIY- GC0074-智能语音温控摇头电风扇 一.功能说明: 基于STM32单片机设计-智能语音温控摇头电风扇 功能介绍: 硬件组成:STM32单片机+语音识别模块+DS18B20温度传感器 ...
- STM32红外遥控实验(发射器和接收器)
这个实验是学院的开放实验,2个小时写完了代码,使用STM32控制器,特此记录一下,比较水,有需要的朋友可以参考一下,想要代码请加入群.欢迎加入QQ群:681976114,点击这里加群 文章来源地址:h ...
- STM32之红外遥控信号自学习实现
文章目录 一.序言 二.硬件实现原理 三.软件实现自学习 一.序言 很早前就想实现这个红外遥控自学习的这个实验,用于来自己控制房子里如空调等红外遥控设备的自动化,NEC的标准到具体的产品上可能就被厂家 ...
- STM32单片机WIFI-APP智能温控空调冷热可调红外遥控
STM32单片机WIFI-APP智能温控空调冷热可调红外遥控 实践制作DIY- GC0127-WIFI-APP智能温控空调 一.功能说明: 基于STM32单片机设计-WIFI-APP智能温控空调 二. ...
- 【正点原子STM32连载】 第三十八章 红外遥控实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...
- 【STC单片机学习】高级外设和项目篇二:红外遥控
[朱老师课程总结 侵删] 第一部分.章节目录 2.2.1.红外遥控背景知识 2.2.2.原理图电路分析 2.2.3.NEC协议讲解 2.2.4.官方示例代码解析 2.2.5.红外接收程序的移植和调试1 ...
- 学习型红外遥控器设计(4) 红外遥控编码还原
学习型红外遥控器设计(0) 摘要 (1) 绪论 (2) 方案设计 (3) 遥控解码 (4) 编码还原 (5) 硬件实现 (6) 总结展望 如方案设计所述,制作红外编码发射装置,该装 ...
最新文章
- Unity 总裁 John Riccitiello 发话:VR足以匹敌互联网
- PHPstudy新版小P面板进行设置版本
- 关于网站图片格式 png,jpg,
- SQL注入——基于报错的注入(五)
- 出现字迹模糊迹象_改变迹象:如何使用动态编程解决竞争性编程问题
- 大整数的因子(信息学奥赛一本通-T1171)
- 教程 | Hadoop集群搭建和简单应用
- 「leetcode」450. 删除二叉搜索树中的节点:【递归】【迭代】详解
- 演示账号激活的过程:注册——向指定邮箱发送邮件——用户登录邮箱,激活账号
- 计算并输出九九乘法表用c语言流程图,输出九九乘法表 (C语言代码)
- Sublime Text3配置LaTeX环境及使用Sumatra PDF作为阅读器——亲测可用
- springSecurity分离资源服务器分析
- Java——Session使用
- 多糖类水凝胶构建制备介绍(瑞禧多糖水凝胶简述)
- 天翼云服务器搭建网站必须要知道的血泪史!
- 服务器停机除尘VS服务器带电清洗
- XML学习-方立勋视频学习
- excel表格末尾添加一行_教你使用Python批量读写excel文件
- 天下数据支招如何防范域名被劫持
- children()和children以及childrenNode的区别