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

这篇具有很好参考价值的文章主要介绍了STM32定时器实现红外接收与解码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.NEC协议

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

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

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

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

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

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

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

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

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

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

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

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

2.解码程序

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

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

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

 

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

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

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

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

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

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

        最后生成代码。在生成的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;
  }
}

       文章来源地址https://www.toymoban.com/news/detail-436833.html

到了这里,关于STM32定时器实现红外接收与解码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32使用定时器实现微秒(us)级延时

    目前开发STM32普遍使用HAL库,但 HAL 库封装的延时函数目前仅支持 ms 级别的延时,日常很多情况下会用到 us 延时,特别是一些传感器的数据读取过程,对时序要求比较严格,us 延时必不可少,因此我们今天来介绍STM32如何使用定时器实现微秒(us)级延时。 Keil 5 STM32CubeMX STM

    2024年02月12日
    浏览(46)
  • STM32不使用中断实现定时器微秒级精确延时

    我们在写代码的时候避免不了要使用延时函数,很多延时函数都是使用中断或者tick来实现的,tick的方式最大到毫秒ms级别,通过中断方式的通用定时器来实现,如果实现1us的延时那么每1us就来一次中断,很影响cpu的效率。 本文提供一种 不使用中断 ,并且很简单的方式实现的

    2024年04月11日
    浏览(33)
  • STM32+摁键与定时器实现Led灯控制(中断)

    中断作为单片机开发必须掌握的内容,它能够在不搭载操作系统的情况下让我们体验多任务处理的快感,保证了高优先级任务的实时性,同时系统中断也能够提供给用户在核心发生错误之后进行处理的机会。STM32F103系列单片机中断非常强大,每个外设都可以产生中断,F103 在

    2024年02月04日
    浏览(47)
  • 【STM32】STM32学习笔记-定时器定时中断 定时器外部时钟(14)

    1.1 TIM_InternalClockConfig 1.2 TIM_TimeBaseInit 1.3 TIM_TimeBaseInitTypeDef 1.4 TIM_ClearFlag 1.5 TIM_ITConfig 1.6 TIM_Cmd 1.7 中断服务函数 参考程序 1.8 TIM_ETRClockMode2Config timer.h timer.c main.c timer.h timer.c main.c 09-定时器定时中断.rar 10-定时器外部时钟.rar 参考: 【STM32】江科大STM32学习笔记汇总

    2024年02月03日
    浏览(38)
  • STM32系统滴答定时器SysTick实现精确ms和us延时

    时间记录:2023/12/11 一、时间的计算 STM32F103C8T6单片机为例,系统时钟为72MHz,则一个时钟周期为(1/72M)秒,即1/72us 二、寄存器介绍 (1)CTRL控制及状态寄存器 位段 名称 描述 16 COUNTFLAG 当计数到0时,该位置为1,当读取该位时,自动清零 2 CLKSOURCE 值为0时选择外部时钟源,值为

    2024年01月24日
    浏览(34)
  • 基于STM32CubeMX和keil采用STM32F407的基本定时器中断实现LED闪烁

    定时器有三种,基本定时器,通用定时器,以及高级定时器。 这篇博客以最简单的基本定时器为例,实现LED的闪烁。 后面两种定时器的用法后面再写。 实现功能: TIM6控制LED每隔0.5s变一次状态。 TIM7控制LED1常量2s后熄灭。 因为都是用到LED,所以和上一篇基于STM32CubeMX与keil采

    2024年02月04日
    浏览(50)
  • STM32定时器编码器模式实现直流有刷电机测速(HAL库)

    最近在做一个单片机大作业,要用到直流有刷,在这里把学习编码器的知识记录一下,学习参考资料: 正点原子DMF407电机控制专题教程_V1.0 我所使用的编码器是市面上常见的 磁电增量式编码器 ,其有AB两相,用于输出电机转动时的 脉冲数 ,AB两相的先后顺序决定了电机的

    2023年04月24日
    浏览(54)
  • HAL STM32基于系统滴答定时器(SysTick)实现多任务时间片轮询

    📑RTOS(实时操作系统)和定时器时间片轮询是两种不同的任务调度和执行方式的差异简介 🔖 以下部分内容,由AI给出的解答: 🔖RTOS(实时操作系统): 🌿RTOS是一种专门设计用于实时系统的操作系统,它可以有效地管理多个任务,提供任务调度、同步和通信等功能。 🌿

    2024年02月21日
    浏览(36)
  • STM32定时器-定时器中断功能详解

    STM32的众多定时器中我们使用最多的是高级定时器和通用定时器,而高级定时器一般也是用作通用定时器的功能,下面我们就以通用定时器为例进行讲解,其功能和特点包括: 通用与基本定时器(2~7)位于低速的APB1总线上 高级定时器(1、8)位于高速的APB2总线上 自动装载计

    2024年02月08日
    浏览(34)
  • STM32CUBEMX配置 定时器中断 和 上升沿中断(实现检测1s以内的脉冲个数)

    ———————————————————————————————————— ⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动,包括ADC、UART、RS485、EEPROM(IIC)、FLASH(SPI)等等。

    2024年02月16日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包