前言

很早一段时间就想把红外解码的思路及代码写到博客上面,但是因为拖延症拖延到现在。
作者是使用的野火的指南针开发板(野火打钱),遥控器也使用的是野火店里面卖的。此处应该收广告费
本文仅介绍解码原理 ,因为发射很简单,就控制一个IO拉高拉低就行了,或者使用pwm等等。当然了如果解码你都会写了,发射那肯定是手到擒来。

1 解码原理

解码原理其实很简单,就是检测一个IO的高低电平持续时间就行了。当然了,红外的时序是有要求的,比如说起始信号、结束信号、数据码、持续信号等。这里的数据码包括系统识别码和操作码。
这里直接贴上野火的讲解
/*
遥控码由三部分组成
1、leader code 9ms的高电平 + 4.5ms 的低电平
2、系统识别码 区别不同的红外遥控设备
3、操作码 8bit操作码和8bit的操作反码组成

0和1均以0.56ms的低电平开始(实际测量是500us的样子),不同的是后面出现的高电平,
如果高电平是0.56ms(实际测量是500us的样子),则表示0,如果高电平是1.68ms(0.56*3=1.68)则表示1

结束码
高电平超过40ms,然后出现9ms的低电平
连发码 2.1ms的高电平
*/

2 思路讲解

本文这里原理讲解比较简单,看不懂的可以自行百度。这不是本文讲解的重点。
作者使用的是定时器加外部中断的方式进行解码。当然还有还有 别的方式可以进行解码,这个都无所谓。
首先的思路是计算IO的高低电平时间,那么定时器当然就少不了了 。

2.1 定时器配置

从解码原理那里可以看到高电平的持续时间范围为0.56ms到大于40ms。
那么我们开始配置定时器了,作者使用的stm32f103频率位72MHz,使用的定时器TIM3(当然你也可以选一个你自己喜欢的定时器)。那么我们配置定时器记一个数的时间位0.01ms,0.01ms对应的是100kHz,定时器的分频系数 = 72M/100K = 720。这个时候我们定时器计数只要超过40ms/0.01ms = 4000即可,这里作者设置为5000。当然了,定时器中断就不需要开了,因为我们用到的仅仅是计时而已。代码如下:

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);TIM_TimeBaseStructure.TIM_Period = (5000-1);
TIM_TimeBaseStructure.TIM_Prescaler = (720-1);//0.01ms   50ms
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);TIM_Cmd(TIM3, ENABLE);

2.2 IO配置

IO的话,我们需要用到中断、输入模式。野火红外接收原理图如下

这里使用的IO是PE5,当然了使用哪个IO口都可以,仅仅是和你自己的板子配合起来使用而已。
这里我们配置IO模式为浮空上拉模式,中断触发模式配置为双边沿触发模式。
因为IO配置位输入模式了,速率是不需要的,所以那一行代码可有可无。
代码如下:

GPIO_InitTypeDef         GPIO_InitStructure;
NVIC_InitTypeDef         NVIC_InitStructure;
EXTI_InitTypeDef         EXTI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource5);
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

2.3 按键中断解码

对IO、TIM的配置可以看到很简单,这里开始讲解中断服务函数里面的内容了。
从最开始的内容我们可以知道红外解码最主要的数据有四个–系统识别码(8bit)+系统识别码反码(8bit)+操作码(8bit)+操作码反码(8bit)。这里我们直接用一个32bit的数据进行存储红外接收到的数据,而且通过分析红外的原理我们可以发现仅仅计算高电平的时间我们就可以完成解码的操作,当然了作者这里是进行了偷懒操作,不提倡大家学习。
高电平时间计算方式位在io上升沿时清零定时器的计数值,在下降沿时记录定时器计数值即可。
再看下面代码时,可以先不看InfraredData结构体的代码内容以及#if、#endif的内容。

void EXTI9_5_IRQHandler(void)
{static uint32_t  irdata = 0;
#if   !Continuousstatic _Bool start = False;
#endifif(EXTI_GetITStatus(EXTI_Line5)){EXTI_ClearITPendingBit(EXTI_Line5);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)){/* 上升沿 */TIM_SetCounter(TIM3,0);InfraredHightime = 0;}else{/* 下降沿 */InfraredHightime = TIM_GetCounter(TIM3);if(InfraredHightime>400 && InfraredHightime<500){#if   !Continuous               start = True;
#endif              irdata = 0;}
#if   !Continuouselse if(start){if(0){}
#endifelse if(InfraredHightime>40 && InfraredHightime<72){irdata <<= 1;irdata |= 0;}else if(InfraredHightime>150 && InfraredHightime<186){irdata <<= 1;irdata |= 1;}else if((InfraredHightime>4000) || (InfraredHightime<220)){
#if   !Continuousstart = False;
#endifInfraredData.sid = irdata>>24;InfraredData.nsid = irdata>>16;InfraredData.opcode = irdata>>8;InfraredData.nopcode = irdata>>0;InfraredData.ismark = True;}
#if   !Continuous}
#endif  }}
}

可以看到作者是在下降沿的中断里才开始处理,代码具体内容就不进行讲解了,读者自行观看即可。
InfraredData结构体内容如下
ismark代表的是解码完成,也就是当前结构体的数据有效。
宏Continuous控制的是支持连续解码还是必须松开才能进行下次解码。

typedef struct
{uint8_t sid;//System identification codeuint8_t nsid;//System identification code inverse codeuint8_t opcode;//operation codeuint8_t nopcode;//operation code inverse code_Bool ismark;//Infrared switching mark
}infrared_t;

完整代码如下

infrared.c

#include "infrared.h"infrared_t InfraredData;
static uint16_t InfraredHightime = 0;static void InfraredDataInit(void)
{InfraredData.ismark = False;InfraredData.opcode = 0;InfraredData.nopcode = 0;InfraredData.sid = 0;InfraredData.nsid = 0;
}
void InfraredInit(void)
{GPIO_InitTypeDef         GPIO_InitStructure;NVIC_InitTypeDef         NVIC_InitStructure;EXTI_InitTypeDef         EXTI_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);//   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource5);EXTI_InitStructure.EXTI_Line = EXTI_Line5;    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);TIM_TimeBaseStructure.TIM_Period = (5000-1);TIM_TimeBaseStructure.TIM_Prescaler = (720-1);//0.01ms   50msTIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);TIM_Cmd(TIM3, ENABLE);InfraredDataInit();
}void EXTI9_5_IRQHandler(void)
{static uint32_t  irdata = 0;
#if   !Continuousstatic _Bool start = False;
#endifif(EXTI_GetITStatus(EXTI_Line5)){EXTI_ClearITPendingBit(EXTI_Line5);if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5)){/* 上升沿 */TIM_SetCounter(TIM3,0);InfraredHightime = 0;}else{/* 下降沿 */InfraredHightime = TIM_GetCounter(TIM3);if(InfraredHightime>400 && InfraredHightime<500){#if   !Continuous               start = True;
#endif              irdata = 0;}
#if   !Continuouselse if(start){if(0){}
#endifelse if(InfraredHightime>40 && InfraredHightime<72){irdata <<= 1;irdata |= 0;}else if(InfraredHightime>150 && InfraredHightime<186){irdata <<= 1;irdata |= 1;}else if((InfraredHightime>4000) || (InfraredHightime<220)){
#if   !Continuousstart = False;
#endifInfraredData.sid = irdata>>24;InfraredData.nsid = irdata>>16;InfraredData.opcode = irdata>>8;InfraredData.nopcode = irdata>>0;InfraredData.ismark = True;}
#if   !Continuous}
#endif  }}
}

infrared.h

#ifndef   __INFRARED_H
#define   __INFRARED_H#include "stm32f10x.h"#define   False    0
#define   True     1#define   Continuous    Falsetypedef struct
{uint8_t sid;//System identification codeuint8_t nsid;//System identification code inverse codeuint8_t opcode;//operation codeuint8_t nopcode;//operation code inverse code_Bool ismark;//Infrared switching mark
}infrared_t;extern infrared_t InfraredData;void InfraredInit(void);#endif

main.c

#include "stm32f10x.h"
#include "infrared.h"
#include "usart.h"uint16_t Systime;
void EstimateOpcode(uint8_t opcode);
int main(void)
{//SysTick_Config(72000000 / 1000);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);UsartInit(115200);InfraredInit();printf("红外测试程序\r\n");while (1){if(InfraredData.ismark){InfraredData.ismark = False;           EstimateOpcode(InfraredData.opcode);printf("读取的值%.2x\r\n",InfraredData.opcode);}}
}
void EstimateOpcode(uint8_t opcode)
{switch(InfraredData.opcode){case 162:printf("电源\r\n");break;case 226:printf("menu\r\n");break;case 34:printf("test\r\n");break;case 2:printf("+\r\n");break;case 194:printf("return\r\n");break;case 224:printf("|<<\r\n");break;case 168:printf(">\r\n");break;case 144:printf(">>|\r\n");break;case 104:printf("0\r\n");break;case 152:printf("-\r\n");break;case 176:printf("c\r\n");break;case 48:printf("1\r\n");break;case 24:printf("2\r\n");break;case 122:printf("3\r\n");break;case 16:printf("4\r\n");break;case 56:printf("5\r\n");break;case 90:printf("6\r\n");break;case 66:printf("7\r\n");break;case 74:printf("8\r\n");break;case 82:printf("9\r\n");break;default:printf("unknown\r\n");break;}
}

结语

关于解码作者还想到一种通过定时器输入捕获的方式进行解码,等作者拖延症结束了编写完再发上来吧。
特别说明,使用的遥控器不同,操作码可能就不一样以及高电平持续时间可能会有误差,这个需要自己自行测试即可。

红外解码--基于1838红外接收头相关推荐

  1. 使用PY003基于外部中断+定时器的方式实现NEC红外解码

    写在前边 最近项目用到一款遥控器是38K红外载波,NEC协议的,找了很多帖子有看到用外部中断下降沿判断(但可惜判定数据的方式是while在外部中断里面死等的),有看到用100us定时器定时刷来判断,感 ...

  2. 基于定时器捕获功能的红外解码程序(NEC协议)

    文章目录 前言 一.红外协议简介 1. ITT Protocol 2. NEC 协议 3. Nokia NRC17 协议 二.红外解码程序(NEC协议) 1. 软硬件环境及红外解码状态图 2. 基于定 ...

  3. 【STC15】STC15单片机获取红外解码从软串口输出

    [STC15]STC15单片机获取红外解码从软串口输出 单片机型号:STC15F2K60S2 采用外部晶振,频率:11.0592MHz 红外接收头,数据引脚接P3.2 这里软串口实现主要是位处理时间一 ...

  4. STC单片机获取红外解码从串口输出

    STC单片机获取红外解码从串口输出 串口数据演示 所使用的红外接收头VS1838 VS1838引脚定义 电气特性 所使用的红外按键板 红外遥控接收模块 VS/HX1838 相关的资料: https:/ ...

  5. c语言红外解码程序,[转载]红外遥控和C语言51红外遥控解码程序设计实例

    什么是红外线?人的眼睛能看到的可见光按波长从长到短排列,依次为红.橙.黄.绿.青.蓝.紫.其中红光的波长范围为0.62-0.76μm:比红光波长还长的光叫红外线.红外遥控在生产和生活中应用越来越广泛, ...

  6. 红外遥控——基于STC15W4K32S4

    文章目录 红外遥控 1 红外发射原理简介 2 NEC编码协议 3 红外遥控器解码 4 NEC数据格式: 5 代码 h文件 c文件 红外遥控 1 红外发射原理简介 通用红外遥控系统主要由发射和接收两大部 ...

  7. 红外接收头图片_常见红外接收头引脚型号及测量代换

    一.常见红外接收头型号 二.红外接收头的测量 红外接收头一般有三只引线脚,分别为接地.电源和信号输出.不同型号的红外接收头,其引脚排列也不相同.笔者用电阻法判别红外接收头的引脚简单.快速. 用指针式万 ...

  8. app 如何接收遥控信息_如何选购红外接收头?华新告诉你产品的标准

    关注华新,我们将定时为您推送优质产品信息,为您的业务提供更多的选择! 产品组成 我们知道红外遥控一般分为两部分(发射部分以及接收部分),红外接收头属于接收部分,产品的基础组成为: [内部]PD(光敏器 ...

  9. STM32F4驱动NEC协议的红外接收头

    红外遥控是一种无线.非接触式控制技术,具有抗干扰能力强.传输可靠.价格便宜.功耗低.易实现等优点.被很多的家用电器所采用.目前常用的红外遥控器协议有NEC协议(PWM脉冲宽度调制).Philips R ...

  10. 一体化红外接收头有两种

    一体化红外接收头有两种类型,一种可以响应连续的红外载波,只要有载波接收头就输出低电平,万州光电生产的型号中后面加C的都是这种,称为电平型的,比如W0038C,IRM138C等.另外一种只能响应宽度在一 ...

最新文章

  1. JavaScript arguments对象
  2. 开源一些Delphi系统:mp3play
  3. zcmu1734: 18岁
  4. mysql数据恢复时显示多线程恢复_MySQL多线程备份恢复工具mydumper,myloder
  5. java jnlp_java – 调试JNLP启动应用程序
  6. nlp gpt论文_GPT-3:NLP镇的最新动态
  7. iec61131 3 html5,IEC61131-3{ed3.0}标准资料.doc
  8. Android自己定义DataTimePicker(日期选择器)
  9. USACO-Section1.5 Arithmetic Progressions(枚举)
  10. 与梦城Typecho博客数据站+API站
  11. Flash写操作流程
  12. 在ftp服务器上搜索文件名,ftp服务器上搜索文件
  13. 无线传感器网络定位概念
  14. 入射波反射波和驻波的特性推导
  15. 移动通信核心网技术总结(一)语音与上网业务的实现
  16. 流媒体-RTMP协议-rtmpdump-flv封装解析(一)
  17. python socks代理_如何让任意python程序使用socks代理
  18. 51单片机 c语言小数计算,51单片机怎么实现浮点运算
  19. 腾讯地图数据可视化之热力图
  20. Vue中一些需要注意的点(采坑)

热门文章

  1. python的图导入origin_利用Origin软件做X射线倒易空间图(RSM)的办法
  2. var模型可以用spss做吗_VAR模型一般几个变量
  3. JMeter基础 —脚本录制工具Badboy介绍
  4. DotNetBar 14中文版
  5. 使用注册表文件(REG)添加、修改或删除windows注册表项和值
  6. 获取计算机显示屏高度,CSS 使用calc()获取当前可视屏幕高度
  7. PXE启动错误代码一览表
  8. 工具:BT Sync 同步文件
  9. 使用NATAPP内网穿透
  10. 【Pygame闯关游戏】手残勿入,最新虐心游戏《见缝插针》——不得不玩的一款游戏。