STM32: NEC红外线协议解码(超低成本无线传输方案)

发布者:JoyfulHarmony最新更新时间:2024-06-13 来源: elecfans关键字:STM32  NEC 手机看文章 扫描二维码
随时随地手机看文章

一、环境介绍

MCU: STM32F103ZET6


编程软件环境: keil5

红外线传输协议: NEC协议---38KHZ载波:。NEC协议是红外遥控协议中常见的一种。

解码思路: 外部中断 + 定时器方式

代码风格: 模块化编程,寄存器直接操作方式


二、NEC协议与解码思路介绍

2.1 采用的相关硬件

图1: 这是NEC协议的红外线遥控器: 如果自己手机没有红外线遥控器的功能,可以淘宝上买一个小遥控器来学习测试,成本不高,这个遥控器也可以自己做,能解码当然也可以编码发送,只需要一个红外光发射管即可。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


图2: 这是红外线接收头模块。如果自己的开发板没有自带这个接收头,那就单独买一个接收头模块,使用杜邦线接到开发板的IO口上即可用来测试学习,接线很方便。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


poYBAGDYdXCAWkKMAAAAK8RNs4s030.png



图3: 这是红外线发射管,如果自己想做遥控器的发射端,自己做遥控器,那么就可以直接购买这种模块即可。

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


2.2 红外线协议介绍

在光谱中波长自760nm至400um的电磁波称为红外线,它是一种不可见光。红外线通信的例子我们每个人应该都很熟悉,目前常用的家电设备几乎都可以通过红外遥控的方式进行遥控,比如电视机、空调、投影仪等,都可以见到红外遥控的影子。这种技术应用广泛,相应的应用器件都十分廉价,因此红外遥控是我们日常设备控制的理想方式。

红外线的通讯原理: 红外光是以特定的频率脉冲形式发射,接收端收到到信号后,按照约定的协议进行解码,完成数据传输,在消费类电子产品里,脉冲频率普遍采用 30KHz 到 60KHz 这个频段,NEC协议的频率就是38KHZ。 这个以特定的频率发射其实就可以理解为点灯,不要被复杂的词汇难住了,就是控制灯的闪烁频率(亮灭),和刚学单片机完成闪光灯一样的意思,只不过是灯换了一种类型,都是灯。 接收端的原理: 接收端的芯片对这个红外光比较敏感,可以根据有没有光输出高低电平,如果发送端的闪烁频率是有规律的,接收端收到后输出的高电平和低电平也是有规律对应的,这样发送端和接收端只要约定好,那就可以做数据传输了。

红外线传输协议可以说是所有无线传输协议里成本最低,最方便的传输协议了,但是也有缺点,距离不够长,速度不够快;当然,每个传输协议应用的环境不一样,定位不一样,好坏没法比较,具体要看自己的实际场景选择合适的通信方式。


2.3 NEC协议介绍

NEC协议是众多红外线协议中的一种(这里说的协议就是他们数据帧格式定义不一样,数据传输原理都是一样的),我们购买的外能遥控器、淘宝买的mini遥控器、电视机、投影仪几乎都是NEC协议。 像格力空调、美的空调这些设备使用的就是其他协议格式,不是NEC协议,但是只要学会一种协议解析方式,明白了红外线传输原理,其他遥控器协议都可以解出来。

下图是NEC协议传输一次数据的完整格式:

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


NEC协议一次完整的传输包含: 引导码、8位用户码、8位用户反码、8位数据码、8位数据反码。

(注意:下面的解释都是站在红外线接收端的角度来进行说明的,就是解码端的角度)

引导码: 由9ms的高电平+4.5ms的低电平组成。

4个字节的数据: 用户码+用户反码+数据码+数据反码。 这里的反码可以用来校验数据是否传输正确,有没有丢包。


重点: NEC协议传输数据位的时候,0和1的区分是依靠收到的高、低电平的持续时间来进行区分的---这是解码关键。

标准间隔时间:0.56ms

收到数据位0: 0.56ms

收到位1: 1.68ms

所以,收到一个数据位的完整时间表示方法是这样的:

收到数据位0: 0.56m低电平+ 0.56ms的高电平

收到数据位1: 0.56ms低电平+1.68ms的高电平

红外线接收头模块输出电平的原理: 红外线接收头感应到有红外光就输出低电平,没有感应到红外光就输出高电平。


这是使用逻辑分析采集红外线接收头输出的信号:

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


这是采集红外线遥控器上的LED灯输出电平时序图,刚好和接收端相反:

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png



单片机编写解码程序的时候,常见的方式就是采用外部中断+定时器的方式进行解析,中断可以设置为低电平触发,因为接收头没有感应到红外光默认是输出高电平,如果收到NEC引导码,就会输出低电平,进入到中断服务函数,完成解码,解码过程中开启定时器记录每一段的高电平、低电平的持续时间,按照NEC协议进行判断,完成最终解码。

STM32可以使用输入捕获方式完成解码,其实输入捕获就是外部中断+定时器的组合,只不过是STM32内部封装了一层。


完整keil工程源码下载(解压即可编译运行测试):

https://download.csdn.net/download/xiaolong1126626497/19863275


外部中断服务器里的解码程序如下(这个在其他单片机上思路是一样的):

/*

函数功能:  外部中断线9_5服务函数

*/

void EXTI9_5_IRQHandler(void)

{

    u32 time;

    u8 i,j,data=0;

  

    //清除中断线9上的中断请求

EXTI->PR|=1<<9;

  

    time=Infrared_GetTime_L();       //得到低电平时间

    if(time<7000||time>10000)return; //标准时间: 9000us

    time=Infrared_GetTime_H();       //得到高电平时间

    if(time<3000||time>5500)return;  //标准时间4500us

    

    //正式解码NEC协议

    for(i=0;i<4;i++)

    {

        for(j=0;j<8;j++)

        {

             time=Infrared_GetTime_L();       //得到低电平时间

             if(time<400||time>700)return;    //标准时间: 560us

             

             time=Infrared_GetTime_H();       //得到高电平时间

             if(time>1400&&time<1800)         //数据1 1680us

             {

                data>>=1;

                data|=0x80;

             }

             else if(time>400&&time<700)   //数据0 560us

             {

                data>>=1;

             }

             else return;

        }

        InfraredRecvData[i]=data; //存放解码成功的值

      }

    

      //解码成功

      InfraredRecvState=1;

}


三、核心完整代码

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png


poYBAGDYdXCAWkKMAAAAK8RNs4s030.png



本程序的解码思路是: 将红外线接收模块的输出脚接到STM32的PB9上,配置STM32的PB9为外部中断模式,下降沿电平触发;如果收到红外线信号就进入到中断服务函数里解码,如果解码过程中发现数据不符合要求就终止解码,如果数据全部符合要求就按照协议接收,直到解码完成,设置标志位,在main函数里打印解码得到的数据。

代码都是模块化编程,阅读起来也很方便。

3.1 红外线解码.c

复制

#include 'nec_Infrared.h'

u8 InfraredRecvData[4]; //存放红外线解码接收的数据

u8 InfraredRecvState=0; //0表示未接收到数据,1表示接收到数据 

/*

函数功能: 红外线解码初始化(接收)

*/

void Infrared_RecvInit(void)

{

    Infrared_Time6_Init(); //定时器初始化

    

    /*1. 配置GPIO口*/

    RCC->APB2ENR|=1<<3; //PB

    GPIOB->CRH&=0xFFFFFF0F;

    GPIOB->CRH|=0x00000080;

    GPIOB->ODR|=1<<9;

  

    /*2. 配置外部中断*/

    EXTI->IMR|=1<<9; //外部中断线9,开放中断线的中断请求功能

    EXTI->FTSR|=1<<9; //中断线9_下降沿

  

    RCC->APB2ENR|=1<<0; //开启AFIO时钟

    AFIO->EXTICR[2]&=~(0xF<<1*4);

    AFIO->EXTICR[2]|=0x1<<1*4;

    STM32_NVIC_SetPriority(EXTI9_5_IRQn,1,1);

}


/*

函数功能: 初始化定时器,用于红外线解码

*/

void Infrared_Time6_Init(void)

{

    RCC->APB1ENR|=1<<4;

RCC->APB1RSTR|=1<<4;

RCC->APB1RSTR&=~(1<<4);

    TIM6->PSC=72-1; //预分频器

    TIM6->ARR=65535;   //重装载寄存器

    TIM6->CR1|=1<<7; //开启缓存功能

  //TIMx->CR1|=1<<0; //开启定时器

}


/*

函数功能: 测量高电平持续的时间

*/

u32 Infrared_GetTime_H(void)

{

    TIM6->CNT=0;

    TIM6->CR1|=1<<0;    //开启定时器

    while(NEC_IR){}     //等待高电平结束

    TIM6->CR1&=~(1<<0); //关闭定时器

    return TIM6->CNT;

}


/*

函数功能: 测量低电平持续的时间

*/

u32 Infrared_GetTime_L(void)

{

    TIM6->CNT=0;

    TIM6->CR1|=1<<0;    //开启定时器

    while(!NEC_IR){}     //等待低电平结束

    TIM6->CR1&=~(1<<0); //关闭定时器

    return TIM6->CNT;

}



/*

函数功能:  外部中断线9_5服务函数

*/

void EXTI9_5_IRQHandler(void)

{

    u32 time;

    u8 i,j,data=0;

  

    //清除中断线9上的中断请求

EXTI->PR|=1<<9;

  

    time=Infrared_GetTime_L();       //得到低电平时间

    if(time<7000||time>10000)return; //标准时间: 9000us

    time=Infrared_GetTime_H();       //得到高电平时间

    if(time<3000||time>5500)return;  //标准时间4500us

    

    //正式解码NEC协议

    for(i=0;i<4;i++)

    {

        for(j=0;j<8;j++)

        {

             time=Infrared_GetTime_L();       //得到低电平时间

             if(time<400||time>700)return;    //标准时间: 560us

             

             time=Infrared_GetTime_H();       //得到高电平时间

             if(time>1400&&time<1800)         //数据1 1680us

             {

                data>>=1;

                data|=0x80;

             }

             else if(time>400&&time<700)   //数据0 560us

             {

                data>>=1;

             }

             else return;

        }

        InfraredRecvData[i]=data; //存放解码成功的值

      }

    

      //解码成功

      InfraredRecvState=1;

}

poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

3.2 主函数.c

#include 'stm32f10x.h'

#include 'led.h'

#include 'delay.h'

#include 'key.h'

#include 'usart.h'

#include 'at24c02.h'

#include 'W25Q64.h'

#include 'spi.h'

#include 'nec_Infrared.h'


int main()

{

LED_Init();

BEEP_Init();

KeyInit();

  USARTx_Init(USART1,72,115200);

  IIC_Init();

  

  W25Q64_Init();

  

  printf('芯片ID号:0x%Xn',W25Q64_ReadID());

  

  Infrared_RecvInit();

  

while(1)

{

if(InfraredRecvState)

    {

        InfraredRecvState=0;

        printf('用户码:%d,按键码:%dn',InfraredRecvData[0],InfraredRecvData[2]);

        printf('user反码:%d,key反码:%dn',(~InfraredRecvData[1])&0xFF,(~InfraredRecvData[3])&0xFF);

        BEEP=!BEEP;

        LED0=!LED0;

    }

}

}


poYBAGDYdXCAWkKMAAAAK8RNs4s030.png

四、扩展提高

如果上面的NEC的解码思路已经看到,程序已经可以自己编写,就可以试着使用STM32的输入捕获+定时器方式写一版解码代码,既能更加熟悉NEC协议、也可以学习STM32定时器捕获捕获的用法;也可以做一些小东西来锻炼,比如:红外线遥控小车、音乐播放器支持红外线遥控器切歌,电机的开关、灯的开关等等。


搞定协议解码之后,我们下一步就是完成自定义的NEC协议红外线制作,采用STM32模拟一个万能红外线遥控器。


关键字:STM32  NEC 引用地址:STM32: NEC红外线协议解码(超低成本无线传输方案)

上一篇:STM32开发板+机智云IoT+智能楼宇照明灯控
下一篇:IC卡读写系统的单片机实现 STM32+MFRC522实现IC卡读写

推荐阅读最新更新时间:2024-11-12 18:11

在Mac OS X 系统下做STM32开发
前言 本文只是一个提纲,提供一个参考,具体操作请查看文中的链接。 搭建环境 初学STM32开发,首先解决开发环境的问题,由于Mac OS X系统下没有keil环境,故需要自己搭建开发环境,参考大师“胡茂晓 的 BLOG”:在Mac OS X中搭建STM32开发环境(1)等系列。 编译 环境搭好了,然后就是编译,keil下编译就比较简单了,但是Mac OS X就只能自己写makefile来使用make编译了,当然,还可以使用autoconfigure来实现makefile文件,但autoconfigure同样难以入手。 写makefile,当然要了解makefile的基本知识,建议抽时间阅读“GNU make中文手册”。
[单片机]
基于STM32编写一个SPI接口例程
引言 SPI是串行外设接口的缩写,是一种高速的,全双工,同步的通信总线。由于SPI高速和同步的特性,使其成为嵌入式系统和小型设备中使用最广泛的几种通信接口之一。本文将详细讲解一下SPI,并且最后基于STM32编写一个例程。 介绍 SPI简介 SPI(Serial Peripheral Interface)是一种串行外设接口,用于在微控制器(MCU)或数字信号处理器(DSP)等主设备与外部设备之间进行通信。SPI的设计旨在实现高速数据传输和简单的硬件实现。 SPI接口通常由一个主设备(Master)和一个或多个从设备(Slave)组成。主设备控制通信的时序和数据传输,而从设备根据主设备的指令进行响应。SPI通信基于全双工传输方式
[单片机]
基于<font color='red'>STM32</font>编写一个SPI接口例程
STM32系列第25篇--CAN总线
简介: CAN是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议。由德国电气商博世公司在1986年率先提出。此后,CAN通过ISO11898及ISO11519进行了标准化。现在在欧洲已是汽车网络的标准协议。 CAN协议经过ISO标准化后有两个标准:ISO11898标准和ISO11519-2标准。其中ISO11898是针对通信速率为125Kbps~1Mbps的高速通信标准,而ISO11519-2是针对通信速率为125Kbps以下的低速通信标准。 CAN具有很高的可靠性,广泛应用于:汽车电子、工业自动化、船舶、医疗设备、工业设备等方面。 特点: 多主控制。总线空闲时
[单片机]
<font color='red'>STM32</font>系列第25篇--CAN总线
基于STM32的PS2遥控小车
摘要:PS2手柄是索尼的PlayStation2游戏机的遥控手柄。索尼的psx系列游戏主机在全球很是畅销。不知什么时候便有人打起ps2手柄的主意,破解了通讯协议,使得手柄可以接在其他器件上遥控使用,比如遥控我们熟悉的智能小车。突出的特点是这款手柄性价比极高,按键丰富,方便扩展到其它应用中。 1.PS2手柄控制 PS2手柄由手柄与接收器两部分组成,手柄主要负责发送按键信息;接收器与单片机(也可叫作主机,可直接用在PS2游戏机上)相连,用于接收手柄发来的信息,并传递给单片机,单片机也可通过接收器,向手柄发送命令,配置手柄的发送模式。 2.PS2手柄时序 1、CS线在通讯期间拉低,通信过程中CS信号线在一串数据(9个字节,每
[单片机]
基于<font color='red'>STM32</font>的PS2遥控小车
STM32 CRC寄存器
1、CRC计算公式 所有的STM32芯片都内置了一个硬件的CRC计算模块,可应用到通信程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式: X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2 + X + 1 写成16进制就是:0x04C11DB7 2、使用这个内置CRC模块操作步骤: 复位CRC模块(设置CRC_CR=0x01),这个操作把CRC计算的余数初始化为0xFFFFFFFF 把要计算的数据按每32位分割为一组数据字,并逐个地把这组数据字写入CRC_DR寄存器(既下图中的绿色框) 写完所有的数据字后
[单片机]
STM32进阶-串口及蓝牙通信 控制开发板硬件详细步骤-USART1/2
处理器与外部通信概述 串行通信 -传输原理:数据按位顺序传输。 -优点:占用引脚资源少 -缺点:速度相对较慢 并行通信 -传输原理:数据各个位同时传输。 -优点:速度快 -缺点:占用引脚资源多 串口作为 MCU 的重要外部接口,基本上所有的 MCU 都会带有串口。而STM32F407ZET6 最多可提供 6 路串口。 通信按传输方向以下几种方式: a.单工: 数据传输只支持数据在一个方向上传输(收音机、遥控器) b.半双工: 允许数据在两个方向上传输,但是,在某一时刻,只允许数 据在一个方向上传输,它实际上是一种切换方向的单工通信;(对讲机) c.全双工: 允许数据同时在两个方向上传输,因此,全双工通信是两个
[单片机]
<font color='red'>STM32</font>进阶-串口及蓝牙通信 控制开发板硬件详细步骤-USART1/2
STM32 ADC转换
STM32具有1~3个ADC。这些ADC可以相互独立使用,也可以使用双重模式。STM32的ADC是12位逐次逼近型的模拟/数字转换器。它有18个通道,可测量16个外部和2个内部信号源。各通道可以单次、连续、扫描或间断模式执行。 ADC其实检测的是电压信号,然后在将它转换数字信号。在我使用开发板上,ADC能检测的电压范围为0~3.3v,其转换成数字信号后对应的数字量范围为:0~4095。 下面就讲讲STM32 ADC转换功的实现。还是基于我自己的规范工程上修改!! 1、工程的修改 1)由于要使用ADC功能,必须使用到库文件stm32f10x_adc.c,所以将是stm32f10x_adc.c文件添加到STM32F10x_Std
[单片机]
<font color='red'>STM32</font> ADC转换
STM32的IWDG使用
关于独立看门狗,很简单,打开喂狗,就这么简单,很多书上讲了很多什么寄存器什么的,对于初学者而言,这些还不是很重要,重要的是先学会用,用了之后慢慢去消化,为什么这东西要这么设置。好了下面来看看我的程序,很简单: void Iwdg_Init(void) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); IWDG_SetPrescaler(IWDG_Prescaler_256); IWDG_SetReload(0xfff);//设置这个就可以调整IWDG的喂狗时间 //如果在这段时间内没有喂狗,那么就会重启 IWDG_ReloadCounter(); IWDG_Enable(); IWDG
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved