STM32定时器实现红外接收与解码

news2024/10/2 14:25:09

1.NEC协议

         红外遥控是一种比较常用的通讯方式,目前红外遥控的编码方式中,应用比较广泛的是NEC协议。NEC协议的特点如下:

  1. 载波频率为 38KHz
  2. 8位地址和 8位指令长度
  3. 地址和命令2次传输(确保可靠性)
  4. PWM 脉冲位置调制,以发射红外载波的占空比代表“0”和“1”

        其逻辑1与逻辑0的表示如图所示

        可以看到,逻辑1的位时间为2.25ms,脉冲时间560us;逻辑0的位时间为1.12ms,脉冲时间560us。

        一个完整的NEC数据包如下:

        首次发送的是9ms高电平+4.5ms低电平,为引导码。

        接下来是8bit的地址码+8bit地址码的反码+8bit命令码+8bit命令码的反码。

        以上是一个正常的数据包,但可能存在一种情况:当长按某个键时,发送的是以110ms为周期的重复码,如下图:

        重复码由9ms高电平和2.25ms的低电平以及560us的高电平组成

2.解码程序

        在上面的图中可以看到,逻辑1和逻辑0的位时间是不同的,占空比也不同。所以我们可以根据位时间的长短来解码,也可以根据占空比的不同(1/2或1/4)来解码,或者二者同时作为解码条件。这里我们介绍根据位时间来解码。

        需要注意的是,很多红外一体接收头为了提高接受灵敏度。输入高电平,其输出的是相反的低电平。下图为示波器实际捕获的一组数据:

 

        可以看到,空闲时为高电平,引导码为9ms低电平+4.5ms高电平。根据位时间解码的话,我们就不必关系高低电平各自的时间,只需关系总时间就行,即:引导码-13.5ms,逻辑1-2.25ms,逻辑0-1.12ms。

        首先用STM32CubeMx配置定时器。系统时钟等的配置这里不在赘述,参考其它教程。

        这里使用TIM3的Channel1作为捕获通道配置如下:

  1. 定时器时钟为内部时钟
  2. Channel1配置为输入捕获模式
  3. 分频系数为63,因为系统时钟为64M,这样定时器实际时钟为64/(63+1)=1M,主要是为了程序中方便计算。
  4. 捕获方式为下降沿捕获
  5. 最后别忘了打开定时器的中断

        最后生成代码。在生成的TIM3中断函数中,屏蔽生成的中断处理还是,添加自己的解码程序如下:

uint32_t TIM3_Over_Cnt = 0;//tim3溢出次数
uint32_t TIM3_Sum_Cnt = 0;//两次下降沿之间的时间间隔
uint32_t cnt0 = 0;
uint8_t IR_Data[60];

void TIM3_IRQHandler(void)
{
  /* USER CODE BEGIN TIM3_IRQn 0 */

  /* USER CODE END TIM3_IRQn 0 */
//  HAL_TIM_IRQHandler(&htim3);
  /* USER CODE BEGIN TIM3_IRQn 1 */
    if(__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_UPDATE))      //定时器溢出中断
    {
        __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_UPDATE);    //清除中断标记
        TIM3_Over_Cnt++;
    }
    cnt0 = __HAL_TIM_GET_COUNTER(&htim3);
    TIM3_Sum_Cnt = (TIM3_Over_Cnt << 16) + cnt0;//获取计数器的值
    __HAL_TIM_SetCounter(&htim3,0);//清零重新计数
    TIM3_Over_Cnt = 0;//清零重新计数

    if (__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_CC1) != RESET)//TIM3CH1捕获中断
    {
       if(StartRevFlag == 1)//接收到引导码,开始解码
       {
         if(TIM3_Sum_Cnt > 36000)//大于36ms认为是结束
         {
           RevComplete = 1;//解码完成
           IR_Tick = 0;
         }
         else if(RevComplete == 0)
         {
           if(TIM3_Sum_Cnt > 1000 && TIM3_Sum_Cnt < 1300)//1ms~1.3ms认为是低电平
            IR_Data[IR_Idx] = 0;
           else  if(TIM3_Sum_Cnt > 2100 && TIM3_Sum_Cnt < 2400)//2.1ms~2.4ms认为是高电平
            IR_Data[IR_Idx] = 1;
           else //接收错误,重新开始
             StartRevFlag = 0;
           IR_Idx++;
           if(IR_Idx > 59)
             IR_Idx = 59;
        }

       }
       else
       {
         if(TIM3_Sum_Cnt > 13000 && TIM3_Sum_Cnt < 14000)//13~14ms引导码
         {
           StartRevFlag = 1;
         }
         IR_Tick = 0;
         RevComplete = 0;//解码完成标志置零
         IR_Idx = 0;//有效解码位
         TIM3_Over_Cnt = 0;
         TIM3_Sum_Cnt = 0;//定时器计数清零
       }
        __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_CC1);
    }

  /* USER CODE END TIM3_IRQn 1 */
}

        解码程序根据每次捕获下降沿之间的间隔判断是引导码还是逻辑1或逻辑0。接收到引导码之后,再开始将解码的数据保存下来。最后通过也是时长来判断解码结束。这里没有判断重复码,有兴趣的小伙伴可以自己加上。

         中断函数中,只是将每一位解码并保存,最后还需要在主程序中组合成字节并判断处理。

void IR_Rev()
{
  uint8_t num = IR_Idx / 8;
  uint8_t IRValue[8];

  if(RevComplete == 1 && StartRevFlag == 1 && IR_Tick > 20)
  {
    if(num > 7)
      num = 7;

    for(uint8_t j=0;j<num;j++)//将每一位解码数据组合成字节数据
    {
      for(uint8_t i = 0;i< 8;i++)
      {
        IRValue[j] = IRValue[j]>>1;
        if(IR_Data[j*8+i])
          IRValue[j] |= 0x80;
      }
    }
    if(IRValue[0] == 0x00 && IRValue[1] == 0xFF)//地址码正确
    {
      switch(IRValue[2])//判断数据码
      {
        case 0x46:
          KeyValue = S_key_Menu;
          break;
        case 0x43:
          KeyValue = S_key_Set;
          break;
        case 0x40:
          KeyValue = S_key_Rst;
          break;
        case 0x15:
          KeyValue = S_key_Down;
          break;
        case 0x09:
          KeyValue = S_key_Up;
          break;
      }
    }
    StartRevFlag = 0;
    RevComplete = 0;
    IR_Tick = 0;
  }
}

       

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

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

相关文章

Shiro简介

介绍 ApacheShiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完成:认证、授权、加密、会话管理、与 Web集成、缓存等。借助Shiro 您可以快速轻松地保护任何应用程序一一从最小的移动应用程序到最大的 Web 和企业应用程序。 1.2:为什么要用 shiro 自2003年以…

GIS状态检测新技术——振动分析法

提示&#xff1a;唐老师好&#xff0c;我之前因为“阳”了&#xff0c;所以就没有参与汇报&#xff0c;给老师带来不便&#xff0c;请老师见谅。以此篇文章代替课堂汇报。 文章目录前言一、不同故障对应的振动频谱和故障特征量二、GIS设备振动特征估计1.GIS设备状态空间2.粒子滤…

npm install报错,node-sass: Command failed

报错如下&#xff1a; gyp verb check python checking for Python executable "python2" in the PATH gyp verb which failed Error: not found: python2 gyp verb which failed at getNotFoundError (C:\Program Files (x86)\Jenkins\jobs\NdbSite-hot-fix-Ma…

《游戏学习》| 微信对话模拟生成器源码分析

简介微信对话生成器&#xff0c;是一款在线微信聊天对话制作的工具&#xff0c;它可以设置苹果或安卓状态栏&#xff0c;包括手机电量、手机时间等&#xff0c;还可以设置不同用户的角色&#xff0c;然后发送文字、语音、红包、转账等多种好玩的功能&#xff0c;可谓是一款娱乐…

es的使用与原理8 -- 初识es及es简单CRUD语法

为什么不能使用数据库做搜索&#xff1f; 1、比方说&#xff0c;每条记录的指定字段的文本&#xff0c;可能会很长&#xff0c;比如说“商品描述”字段的长度&#xff0c;有长达数千个&#xff0c;甚至数万个字符&#xff0c;这个时候&#xff0c;每次都要对每条记录的所有文本…

vue处理一千张图片进行分页加载

vue处理一千张图片进行分页加载 开发过程中&#xff0c;如果后端一次性返回你1000多条图片或数据&#xff0c;那我们前端应该怎么用什么思路去更好的渲染呢&#xff1f; 第一种&#xff1a;我们可以使用分页加载 第二种&#xff1a;我们可以进行懒加载那我们用第一种方法使用…

Mysql 与 磁盘交互的过程

从之前的Mysql架构可以了解到&#xff0c;Mysql 客户端不是直接和磁盘打交道&#xff0c;我们在客户端输入的sql语句会被发送给服务端&#xff0c;服务端对sql语句进行解析、缓存等操作&#xff0c;然后再交由存储引擎去读写磁盘。这其实是从 C/S 的角度去了解Mysql。 站在OS的…

jvm如何判断对象已死?

在堆里面存放着各种各类的Java对象&#xff0c;垃圾收集器在对堆进行垃圾回收时&#xff0c;首要就是判断哪些对象还活着&#xff0c;哪些对象已经死去(即不被任何途径引用的对象)。引用计数器算法&#xff1a;引用计数器算法简单概括为&#xff1a;给对象添加一个引用计数器&a…

Java基础面试题——IO和多线程专题

文章目录1.介绍下进程和线程的关系2.说说Java中实现多线程的几种方法3.如何停止一个正在运行的线程4.介绍下线程中的常用方法1.start方法2.run方法3.getName方法4.优先级5.sleep方法6.isAlive7.join8.yield9.wait和notify/notifyAll5.介绍下线程的生命周期6.为什么wait, notify…

什么?30秒生成一个logo

logo 是徽标或者商标的英文说法。logo 承载着企业的无形资产&#xff0c;是企业综合信息传递的媒介。标志作为企业CIS战略的最主要部分&#xff0c;在企业形象传递过程中&#xff0c;是应用最广泛、出现频率最高&#xff0c;同时也是最关键的元素。通过形象的 logo 可以让消费者…

(考研湖科大教书匠计算机网络)第四章网络层-第三节5:IPv4地址的应用规划

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;定长的子网掩码FLSM二&#xff1a;变长的子网掩码VLSM本节对应视频如下 【计算机网络微课堂&#xff08;有字幕无背景音乐版&#xff09;】&#x…

笔记本电脑怎么连接无线网wifi?不同电脑系统的使用教程(2023最新)

现在越多人使用笔记本电脑&#xff0c;在我们的日常生活和工作中是很难离开它的。想要更快速地上网&#xff0c;我们都会选择连接无线网的wifi。有时笔记本电脑无法连接网络&#xff0c;你知道这是什么原因吗&#xff1f;笔记本电脑怎么连接无线网wifi&#xff1f;方法很简单&a…

.NET C# 世界日期格式转换为yyyyMMdd

本文分享了一个按照不同国家的语言生成相应时间格式的案例&#xff0c;有需要做国外网站或者多国语言网站的朋友可以参考一下。 本文在引用 【C# DateTime.ToString根据不同语言生成相应的时间格式】基础上做了一个Demo测试&#xff0c;旨在给更多有需要的人能刷到 官方示例&…

蓝奏云网盘下载链接无法打开的解决方法(详解 全)

&#x1f388;前言蓝奏云是一家国内的比较有良心的网盘提供商&#xff0c;提供有不限量的网盘空间&#xff0c;且不限制下载速度&#xff0c;免费用户只限制上传单文件小于100M的文件。算是比较有良心的。而且下载还不用登录才能下载&#xff08;很多标称免费的网盘均需要下载者…

Python进阶篇(二)-- Django 深入模型

上一节提到了Django是基于MVC架构的Web框架&#xff0c;MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据&#xff08;的表示&#xff09;&#xff0c;所以通常也被称作“数据模型”。在实际的项目中&#xff0c;数据模型通常通过数据库实现持久…

阿里云部署SpringBoot项目

目录 步骤1&#xff1a;购买服务器(新用户免费试用一个月) 步骤2&#xff1a;查看服务器相关信息 ​编辑 步骤3&#xff1a;设置安全组 步骤4&#xff1a;远程连接 步骤5&#xff1a;使用FinalShell连接阿里云服务器 步骤6&#xff1a;阿里云服务器上安装JDK ​编辑 步骤7…

Inception Transformer

paper链接: https://arxiv.org/abs/2205.12956v2 code链接: https://github.com/sail-sg/iFormer Inception Transformer一、引言二、实现细节三、实验一、分类二、检测三、分割四、消融实验一、引言 最近的研究表明&#xff0c;Transformer具有很强的建立远程依赖关系的能力…

vAPI:一个自托管的OWASP Top 10漏洞API靶场

关于vAPI vAPI是一款针对OWASP Top 10漏洞的练习靶场&#xff0c;vAPI项目是一个故意引入了多种漏洞的可编程接口API&#xff0c;广大研究人员可以利用vAPI来研究和练习OWASP Top 10漏洞。 工具要求 PHP MySQL PostMan Mitmproxy 工具安装 Docker安装 docker-compose up -d…

Jira和Confluence Server版终止支持倒计时365天,企业应对策略汇总

本文对Atlassian最新的Server版政策进行了解读&#xff0c;并给出应对方案&#xff1b;同时我们也将国内热门的替代工具与jira进行了比较细致的对比&#xff0c;以及介绍替换的优惠政策等。今天是2023年2月15日&#xff0c;距离 Atlassian 旗下 Jira、Confluence 等系列产品中国…

互联网的路由选择协议

互联网的路由选择协议 文章目录互联网的路由选择协议路由选择协议的几个概念分层次路由选择协议内部网关协议RIP协议距离向量算法RIP协议的报文格式内部网关协议OSPFOSPF的报文格式✨OSPF的特点外部网关协议BGPBGP的报文格式参考本篇主要讨论的是路由表中的路由是如何得出来的。…