0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

用STM32CubeMx配置定时器

嵌入式技术开发 来源:嵌入式技术开发 2023-02-16 09:08 次阅读

1.NEC协议

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

NEC协议的特点如下:

1)载波频率为 38KHz

2)8位地址和 8位指令长度

3)地址和命令2次传输(确保可靠性)

4)PWM 脉冲位置调制,以发射红外载波的占空比代表“0”和“1” 其逻辑1与逻辑0的表示如图所示:

c6375f78-ad47-11ed-bfe3-dac502259ad0.png

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

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

c65f5bd6-ad47-11ed-bfe3-dac502259ad0.png

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

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

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

c67cf09c-ad47-11ed-bfe3-dac502259ad0.png

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

2.解码程序

在上面的图中可以看到,逻辑1和逻辑0的位时间是不同的,占空比也不同。

所以我们可以根据位时间的长短来解码,也可以根据占空比的不同(1/2或1/4)来解码,或者二者同时作为解码条件。这

里我们介绍根据位时间来解码。 需要注意的是,很多红外一体接收头为了提高接受灵敏度。

输入高电平,其输出的是相反的低电平。

下图为示波器实际捕获的一组数据:

c69fcd6a-ad47-11ed-bfe3-dac502259ad0.png

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

系统时钟等的配置这里不在赘述,参考其它教程

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

c6c2bce4-ad47-11ed-bfe3-dac502259ad0.png

1)定时器时钟为内部时钟

2)Channel1配置为输入捕获模式

3)分频系数为63,因为系统时钟为64M,这样定时器实际时钟为64/(63+1)=1M,主要是为了程序中方便计算。

4)捕获方式为下降沿捕获

5)最后别忘了打开定时器的中断

c7009f00-ad47-11ed-bfe3-dac502259ad0.png

最后生成代码。

在生成的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>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;
  }
}





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • NEC
    NEC
    +关注

    关注

    0

    文章

    238

    浏览量

    98892
  • STM32
    +关注

    关注

    2240

    文章

    10675

    浏览量

    348882
  • 定时器
    +关注

    关注

    23

    文章

    3148

    浏览量

    112090
  • 红外遥控
    +关注

    关注

    22

    文章

    346

    浏览量

    45008

原文标题:STM32定时器实现红外接收与解码

文章出处:【微信号:嵌入式技术开发,微信公众号:嵌入式技术开发】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    STM32CubeMx入门教程(3):定时器的使用

    导语“ 使用STM32CubeMx 生成初始化定时器代码,实现定时器特定定时
    发表于 07-11 15:22 2359次阅读
    <b class='flag-5'>STM32CubeMx</b>入门教程(3):<b class='flag-5'>定时器</b>的使用

    STM32CubeMx入门教程(4):PWM应用

    导语“使用STM32CubeMx配置定时器输出PWM波,生成初始化代码。”
    发表于 07-11 15:23 910次阅读
    <b class='flag-5'>STM32CubeMx</b>入门教程(4):PWM应用

    基于STM32CUBEMX驱动低压步进器电机驱动器STSPIN220(3)----定时器中断产生指定数量脉冲

    在步进电机控制过程中,为了实现精确的位置和速度控制,经常需要输出指定数量的脉冲。这就需要使用定时器功能来生成PWM脉冲信号。本文将详细介绍如何利用STM32CUBEMX配置定时器以输出
    的头像 发表于 12-01 15:26 585次阅读
    基于<b class='flag-5'>STM32CUBEMX</b>驱动低压步进器电机驱动器STSPIN220(3)----<b class='flag-5'>定时器</b>中断产生指定数量脉冲

    stm32cubemx配置定时器

    stm32cubemx配置定时器,文章目录前言keil主函数时钟配置中断响应CUBE主函数配置函数中断响应前言本文主要介绍使用keil和
    发表于 08-10 07:55

    STM32CUBEMX配置教程

    STM32CUBEMX配置教程(四)定时器中断配置基于STM32H743VI使用STM32CUBEMX
    发表于 08-17 09:02

    Stm32CubeMx基本定时器的概念

    Stm32CubeMx基本定时器基本定时器概念Stm32CubeMx 配置基本配置
    发表于 08-18 08:18

    怎样使用STM32cubemx配置通用定时器

    STM32定时器的功能特点有哪些呢?STM32的通用定时器有哪些应用?怎样使用STM32cubemx
    发表于 10-22 07:46

    求助STM32CubeMX是如何配置定时器中断的呢

    STM32CubeMX是如何配置定时器中断的呢?有哪些基本配置步骤?
    发表于 11-23 06:12

    STM32CubeMX基本定时器接口怎么使用?

    STM32CubeMX基本定时器接口怎么使用?
    发表于 11-24 07:35

    【MCU】基于STM32CubeMX定时器中断实现LED闪烁

    基于STM32CubeMX定时器中断实现 LED 闪烁本实验基于STM32CubeMX实现对STM32开发板的配置,通过
    发表于 10-29 11:06 20次下载
    【MCU】基于<b class='flag-5'>STM32CubeMX</b><b class='flag-5'>定时器</b>中断实现LED闪烁

    STM32CUBEMX配置教程(十二)STM32定时器触发的固定频率ADC采样(使用DMA)

    STM32CUBEMX配置教程(十二)STM32定时器触发的固定频率ADC采样(使用DMA)
    发表于 11-24 13:51 83次下载
    <b class='flag-5'>STM32CUBEMX</b><b class='flag-5'>配置</b>教程(十二)<b class='flag-5'>STM32</b>的<b class='flag-5'>定时器</b>触发的固定频率ADC采样(使用DMA)

    STM32CUBEMX配置教程(十三)STM32定时器触发的固定频率DAC输出(使用DMA)

    STM32CUBEMX配置教程(十三)STM32定时器触发的固定频率DAC输出(使用DMA)
    发表于 11-24 14:06 44次下载
    <b class='flag-5'>STM32CUBEMX</b><b class='flag-5'>配置</b>教程(十三)<b class='flag-5'>STM32</b>的<b class='flag-5'>定时器</b>触发的固定频率DAC输出(使用DMA)

    STM32CUBEMX配置教程(一)基础配置

    STM32CUBEMX配置教程合集(一)
    发表于 12-14 18:41 16次下载
    <b class='flag-5'>STM32CUBEMX</b><b class='flag-5'>配置</b>教程(一)基础<b class='flag-5'>配置</b>

    STM32定时器TIM用作输入捕获

    MCU:STM32H750XB编译平台:Keil-MDK5STMCubeMX版本:MX:V6.2.1 Pack:STM32Cube_FW_H7_V1.9.01.打开STM32CubeMX,
    发表于 12-14 18:58 2次下载
    <b class='flag-5'>STM32</b>的<b class='flag-5'>定时器</b>TIM用作输入捕获

    STM32CubeMx配置定时器的编码器模式

    上次文章写了编码器是如何工作的,今天就来用STM32F103C8T6的TIM3的通道1跟通道2编写一个编码器识别程序。
    的头像 发表于 08-21 11:47 2536次阅读
    <b class='flag-5'>STM32CubeMx</b><b class='flag-5'>配置</b><b class='flag-5'>定时器</b>的编码器模式