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

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

3天内不再提示

STM32之红外遥控信号自学习实现

单片机与嵌入式 来源:博客园 作者:博客园 2022-12-29 09:49 次阅读

1 序言

很早前就想实现这个红外遥控自学习的这个实验,用于来自己控制房子里如空调等红外遥控设备的自动化,NEC的标准到具体的产品上可能就被厂家定义为不一样了,所以自学习就应该是接收到什么就发送什么,不用管内容是什么!

2 硬件实现原理

2c98e01c-86af-11ed-bfe3-dac502259ad0.png

由上述原理图可知,当IE为高电平时发送红外光,为低电平时不发送红外光。

在NEC协议中,信息传输是基于38K载波,也就是说红外线是以载波的方式传递。

发送波形如下图所示:

2cbdb446-86af-11ed-bfe3-dac502259ad0.png

NEC协议规定:

发送协议数据“0” = 发送载波560us + 不发送载波560us

发送协议数据“1” = 发送载波560us+ 不发送载波1680us

发送引导码 = 发送载波9000us + 不发送载波4500us

在红外接收端,如果接收到红外38K载波,则IR输出为低电平,如果不是载波包括固定低电平和固定高电平则输出高电平。在IR端接收的信号如下所示:

2ce43b66-86af-11ed-bfe3-dac502259ad0.png

2d0f079c-86af-11ed-bfe3-dac502259ad0.png

3 软件实现自学习

设计原理:

2d30df20-86af-11ed-bfe3-dac502259ad0.png

1、 根据接收波形记录电平和电平持续时间,以便于发送。

2、电平记录采用定时器捕获功能,从下降沿接收引导信号开始,每触发一次改变触发方式,从而使每个电平变化都能捕获到。

源码实现如下:

定时器捕获初始化设置(CubeMax软件自动配置生成):

void MX_TIM4_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};




htim4.Instance = TIM4;
htim4.Init.Prescaler = 71;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 10000;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}




}

定时器捕获中断回调处理:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
    {
if(TIM4->CCER & (TIM_CCER_CC4P))   //下降沿触发
        {
            TIM4->CCER &= ~(TIM_CCER_CC4P); //切换
            gu8BitVal = 1;
        }
else                               //上升沿触发
        {
            TIM4->CCER |= TIM_CCER_CC4P;    //切换
            gu8BitVal = 0;
        }








if(gsInfrared.State == NONE_STATE)
        {
            gsInfrared.State = RECV_STATE;
        }
else if(gsInfrared.State == RECV_STATE)
        {
            NowTimCnt = HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_4);
            gsInfrared.KeepTime[gsInfrared.SampleCount] = Round(NowTimCnt);
            gsInfrared.BitValue[gsInfrared.SampleCount ++] = gu8BitVal;
        }




        TIM4->CNT = 0;
    }
}

3、设置的定时器溢出时间为10ms,如果10毫秒内不再接收电平变化则默认接收结束,设置结束标志。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim4)
    {
if(gsInfrared.State == RECV_STATE)
        {
            gsInfrared.State = END_STATE;
        }
    }
}

至此,实现了红外遥控的学习功能,获得的记录数据为记录长度和电平信号数组与电平信号维持的时间数组。

2d533228-86af-11ed-bfe3-dac502259ad0.png

4、发送实现

设置定时器输出38KPWM信号,在记录电平为0是输出记录时间的38K载波信号,如果为1则不输出载波,实现如下:

PWM生成设置(CubeMax自动配置生成):

void MX_TIM5_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};




  htim5.Instance = TIM5;
  htim5.Init.Prescaler = 0;
  htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim5.Init.Period = 1896;
  htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim5) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim5, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim5);




}

发送实现,注意点就是记录为0时发载波,记录为1时不发载波:

void InfraredSend(void)
{
uint16_t Count = 0;


while(Count < gsInfrared.SampleCount &&  gsInfrared.State == END_STATE)
    {
if(gsInfrared.BitValue[Count] == 0)
        {
            TIM5->CCR2 = 948;
            delay_us(gsInfrared.KeepTime[Count]);
            TIM5->CCR2 = 0;
        }
else
        {
            TIM5->CCR2 = 0;
            delay_us(gsInfrared.KeepTime[Count]);
            TIM5->CCR2 = 0;
        }




        Count ++;
    }




    delay_us(20000);
}

往PWM比较寄存器设置948即为设置38KPWM波,也可在初始化时固定948,在此函数内启停定时器即可;

至此,自学习功能的全部思路已实现,通过对各个不同类型的红外遥控进行功能测试,均成功。

PS:查看很多资料发现很多红外解码未判断低电平时间,个人感觉不是很好,应该是不仅高电平时间得符合,低电平时间也应该符合。

自己写了一个小函数验证了一下,这个函数只是验证,未经仔细推敲,还可优化,仅供参考这一思想。

误差设计:±200us(拍脑袋值)

void InFraredDataDeal(void)
{
uint32_t DataBuff = 0;
uint16_t Count = 0;




if(gsInfrared.State == END_STATE)
    {
        gsInfraredData.State = 0;




do
        {
switch(gsInfraredData.State)
            {
case 0:   //引导码识别
            {




if(gsInfrared.KeepTime[0] >= 8800 && gsInfrared.KeepTime[0] <= 9200 && gsInfrared.BitValue[0] == 0)
                {
if(gsInfrared.KeepTime[1] >= 4300 && gsInfrared.KeepTime[1] <= 4700 && gsInfrared.BitValue[1] == 1)
                    {
if(gsInfrared.KeepTime[2] >= 360 && gsInfrared.KeepTime[2] <= 760 && gsInfrared.BitValue[2] == 0)
                        {
                            Count = 3;
                            gsInfraredData.State = 1;
                        }
                    }
else if(gsInfrared.KeepTime[1] >= 2300 && gsInfrared.KeepTime[1] <= 2700 && gsInfrared.BitValue[1] == 1)
                    {
if(gsInfrared.KeepTime[2] >= 360 && gsInfrared.KeepTime[2] <= 760 && gsInfrared.BitValue[2] == 0)
                        {
                            gsInfraredData.ReDataCount ++;
                            gsInfraredData.State = 3;
                        }
                    }
else
                    {
                        gsInfraredData.State = 3;
                    }




                }
else
                {
                    gsInfraredData.State = 3;
                }








            }
break;








case 1:   //数据解析
            {




if(gsInfrared.KeepTime[Count + 1] >= 360 && gsInfrared.KeepTime[Count + 1] <= 760 && gsInfrared.BitValue[Count + 1] == 0)
                {




if(gsInfrared.BitValue[Count] == 1)
                    {
if(gsInfrared.KeepTime[Count] >= 1480 && gsInfrared.KeepTime[Count] <= 1880)
                        {
                            DataBuff <<= 1;
                            DataBuff |= 1;
                        }
else if(gsInfrared.KeepTime[Count] >= 360 && gsInfrared.KeepTime[Count] <= 760 && gsInfrared.BitValue[Count] == 1)
                        {
                            DataBuff <<= 1;
                            DataBuff |= 0;
                        }
else
                        {
                            gsInfraredData.State = 3;
                        }
                    }
                }




if(Count < gsInfrared.SampleCount)
                {
                    Count += 2;
                }
else
                {
                    gsInfraredData.State = 2;
                }




            }
break;




case 2:   //成功解析
            {
                gsInfraredData.Data = DataBuff;
                gsInfraredData.State = 3;




            }
break;




default:
            {
                gsInfraredData.State = 3;   //解析结束




            }
break;
            }




        }
while(gsInfraredData.State != 3);




        gsInfrared.State = NONE_STATE;
        gsInfrared.SampleCount = 0;
    }




}

解析的话一般高位在前,所以左移,经测试帧格式为:引导码+用户码+用户码反码+命令码+命令码反码,能成功解析数据!解析的话根据具体协议,具体分析。

审核编辑:汤梓红

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

    关注

    0

    文章

    238

    浏览量

    99112
  • STM32
    +关注

    关注

    2270

    文章

    10896

    浏览量

    355767
  • 信号
    +关注

    关注

    11

    文章

    2790

    浏览量

    76732
  • 定时器
    +关注

    关注

    23

    文章

    3246

    浏览量

    114734
  • 红外遥控
    +关注

    关注

    22

    文章

    347

    浏览量

    45590

原文标题:STM32之红外遥控信号自学习实现

文章出处:【微信号:单片机与嵌入式,微信公众号:单片机与嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    STM32红外遥控信号自学习实现

    STM32红外遥控信号自学习实现
    的头像 发表于 09-18 15:52 3248次阅读
    <b class='flag-5'>STM32</b><b class='flag-5'>之</b><b class='flag-5'>红外</b><b class='flag-5'>遥控</b><b class='flag-5'>信号</b><b class='flag-5'>自学习</b><b class='flag-5'>实现</b>

    自学习空调控制器

    最近的项目是做一个485控制的具有自学习功能的空调控制器,本来以为是个挺简单的红外收发,然后发现红外编码真的是个很复杂的事情,有没有相关项目经验的提供点思路和经验,谢谢大神
    发表于 08-31 12:55

    哪位有基于M3的红外自学习模块的程序吗 求打赏

    我现在有一个红外自学习的程序但是功能貌似没有实现so哪位大神打赏一个参考参考
    发表于 12-12 21:53

    红外遥控器怎么相互兼容?

    自学习红外遥控器的设计与实现
    发表于 11-08 09:00

    红外自学习芯片和红外编解码芯片之间的区别?

    红外自学习芯片和红外编解码芯片之间的区别在哪里?
    发表于 04-07 11:37

    如何让电机自学习

    变频器换应用场合,恢复出厂设置了,如何让电机自学习? 经常有人电话给我们,变频器更换了应用场合(为了省钱把变频器最大化利用,你懂得)。比之前要求的环境呢精度要高,有没有什么办法。我们建议他让电机
    发表于 12-24 16:04

    自学习红外遥控器的设计与实现

    自学习红外遥控器的设计与实现 给出了自学习红外遥控
    发表于 05-04 21:43 7598次阅读
    <b class='flag-5'>自学习</b><b class='flag-5'>红外</b><b class='flag-5'>遥控</b>器的设计与<b class='flag-5'>实现</b>

    自学习红外遥控器的设计与实现

     给出了自学习红外遥控器的一种设计,采用测量脉冲宽度的原理,适用于大多数电子产品的遥控器。介绍了转发红外
    发表于 05-09 12:08 2383次阅读
    <b class='flag-5'>自学习</b><b class='flag-5'>红外</b><b class='flag-5'>遥控</b>器的设计与<b class='flag-5'>实现</b>

    STM32外部中断实现红外遥控功能

    STM32外部中断实现红外遥控功能。
    发表于 12-14 15:49 67次下载

    基于交流异步电机驱动磨床进给位移的自学习控制

    基于交流异步电机驱动磨床进给位移的自学习控制
    发表于 04-25 10:00 8次下载

    自学习差异进化算法

    为解决动态环境下的多中心优化问题,提出自学习差异进化算法。通过评估特定个体检测到环境变化,自学习算子将群体引至新的环境,并保持群体的拓扑结构不变,以继续当前的进化趋势。采用邻域搜索机制加快算法的收敛
    发表于 03-13 16:46 0次下载

    利用单片机和软件载波方式实现通用型红外遥控的设计

    一种利用单片机设计通用自学习红外遥控的方法,可以实现对多种产品红外线遥控。本装置采用了最小化模
    发表于 04-19 09:36 1401次阅读
    利用单片机和软件载波方式<b class='flag-5'>实现</b>通用型<b class='flag-5'>红外</b><b class='flag-5'>遥控</b>的设计

    基于ESP8266智能家居自学习红外遥控设计 单片机源代码+PCB电路图

    基于ESP8266智能家居自学习红外遥控设计 单片机源代码+PCB电路图(51单片机)-基于ESP8266智能家居自学习红外
    发表于 07-22 15:11 88次下载
    基于ESP8266智能家居<b class='flag-5'>自学习</b><b class='flag-5'>红外</b><b class='flag-5'>遥控</b>设计 单片机源代码+PCB电路图

    STM32红外遥控信号自学习实现

    红外接收端,如果接收到红外38K载波,则IR输出为低电平,如果不是载波包括固定低电平和固定高电平则输出高电平。
    发表于 02-08 15:08 6次下载
    <b class='flag-5'>STM32</b><b class='flag-5'>之</b><b class='flag-5'>红外</b><b class='flag-5'>遥控</b><b class='flag-5'>信号</b><b class='flag-5'>自学习</b><b class='flag-5'>实现</b>

    红外遥控自学习实现原理详解

    很早前就想实现这个红外遥控自学习的这个实验,用于来自己控制房子里如空调等红外遥控设备的自动化,N
    的头像 发表于 04-24 16:16 7161次阅读