基本原理:

发射器采用红外发光二级管发射红外光波;

接收器由红外接收二极管、三极管或硅光电池组成,它们将发射器发射的红外光接收转换为相应的电信号。

但是,我们怎么确定我们按了什么键呢?

在计算机的世界里,世界的真理就是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,做为接收数据。

RmtSta
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学习之红外遥控相关推荐

  1. 51单片机学习:红外遥控实验

    实验名称:红外遥控实验 接线说明:     实验现象:下载程序后,数码管上显示数码管上显示红外解码遥控器键值 注意事项:红外接收头凸起处要与PCB板接口凸起丝印处对应                  ...

  2. 我谈学习型红外遥控(一)

    跟着项目组长一起做了几个空鼠项目,一直觉得自己长劲不大,因为自己只负责简单的键盘定义部分,最终的整个软件架构其实自己都不太了解.从去年11月份开始,一直都很忙,一个接着一个做,我的任务也只是键盘部分. ...

  3. 【STM32学习】红外传感器实现——广告自动关闭和自动打开功能

    所用硬件设备: 1.电脑 2.STM32嵌入式最小系统--其实51控制成本会更低,也同样稳定.(* ̄︶ ̄) 3.HC-SR501 RD-624人体红外感应电子模块  淘宝上多的一塌糊涂,几块钱即可购买 ...

  4. STM32单片机智能语音温控摇头电风扇落地扇可红外遥控可PWM调速定时温度显示

    实践制作DIY- GC0074-智能语音温控摇头电风扇 一.功能说明: 基于STM32单片机设计-智能语音温控摇头电风扇 功能介绍: 硬件组成:STM32单片机+语音识别模块+DS18B20温度传感器 ...

  5. STM32红外遥控实验(发射器和接收器)

    这个实验是学院的开放实验,2个小时写完了代码,使用STM32控制器,特此记录一下,比较水,有需要的朋友可以参考一下,想要代码请加入群.欢迎加入QQ群:681976114,点击这里加群 文章来源地址:h ...

  6. STM32之红外遥控信号自学习实现

    文章目录 一.序言 二.硬件实现原理 三.软件实现自学习 一.序言 很早前就想实现这个红外遥控自学习的这个实验,用于来自己控制房子里如空调等红外遥控设备的自动化,NEC的标准到具体的产品上可能就被厂家 ...

  7. STM32单片机WIFI-APP智能温控空调冷热可调红外遥控

    STM32单片机WIFI-APP智能温控空调冷热可调红外遥控 实践制作DIY- GC0127-WIFI-APP智能温控空调 一.功能说明: 基于STM32单片机设计-WIFI-APP智能温控空调 二. ...

  8. 【正点原子STM32连载】 第三十八章 红外遥控实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  9. 【STC单片机学习】高级外设和项目篇二:红外遥控

    [朱老师课程总结 侵删] 第一部分.章节目录 2.2.1.红外遥控背景知识 2.2.2.原理图电路分析 2.2.3.NEC协议讲解 2.2.4.官方示例代码解析 2.2.5.红外接收程序的移植和调试1 ...

  10. 学习型红外遥控器设计(4) 红外遥控编码还原

    学习型红外遥控器设计(0) 摘要   (1) 绪论  (2) 方案设计   (3) 遥控解码   (4) 编码还原  (5) 硬件实现   (6) 总结展望 如方案设计所述,制作红外编码发射装置,该装 ...

最新文章

  1. Unity 总裁 John Riccitiello 发话:VR足以匹敌互联网
  2. PHPstudy新版小P面板进行设置版本
  3. 关于网站图片格式 png,jpg,
  4. SQL注入——基于报错的注入(五)
  5. 出现字迹模糊迹象_改变迹象:如何使用动态编程解决竞争性编程问题
  6. 大整数的因子(信息学奥赛一本通-T1171)
  7. 教程 | Hadoop集群搭建和简单应用
  8. 「leetcode」450. 删除二叉搜索树中的节点:【递归】【迭代】详解
  9. 演示账号激活的过程:注册——向指定邮箱发送邮件——用户登录邮箱,激活账号
  10. 计算并输出九九乘法表用c语言流程图,输出九九乘法表 (C语言代码)
  11. Sublime Text3配置LaTeX环境及使用Sumatra PDF作为阅读器——亲测可用
  12. springSecurity分离资源服务器分析
  13. Java——Session使用
  14. 多糖类水凝胶构建制备介绍(瑞禧多糖水凝胶简述)
  15. 天翼云服务器搭建网站必须要知道的血泪史!
  16. 服务器停机除尘VS服务器带电清洗
  17. XML学习-方立勋视频学习
  18. excel表格末尾添加一行_教你使用Python批量读写excel文件
  19. 天下数据支招如何防范域名被劫持
  20. children()和children以及childrenNode的区别

热门文章

  1. 永远的Beyond, 永远的家驹
  2. 学完后端还要学前端,在这之间还有中间件
  3. Android TTS 自动发声
  4. access中如何画斜线_在Excel单元格中如何用斜线分割填写?
  5. VBA 贴片电阻名称转换
  6. 获取U盘 VID,PID
  7. 基于多进程架构的嵌入式软件框架研究与实现
  8. 使用Qt给微信头像添加国旗
  9. ls只显示文件名/只显示文件夹名
  10. 4星|《千年金融史》:金融技术就是一个我们自己建造的时间机器