当前位置: 首页 > article >正文

stm32对EV1527波形进行解码

最近学习了红外协议,用的是基于EV1527协议,对于从来没搞过红外协议的人来说,初次上手的确略显迷茫,网上的文章也是讲的一知半解,看完原理后,压根没有办法去编写代码,所以,我将整理网上的概述,用通俗易懂的语言进行讲解!若对你有帮助,那么最好不过,共勉!

首先:你得确保你用的协议是EV1527,因为市面上,还有NEC的红外协议,这两者的波形是有区分的。所以要先确保这一点

其次:你得有示波器或者逻辑分析仪,没有这个,你将无法捕获波形,分析波形,这样你是一头雾水的

最后:根据我的代码,一行一行的进行讲解!

正题开始

        一开始,你总得有个IC手册吧,没手册,你怎么知道相关信息是什么呢,这里我就打开了EV1527的手册,可以去嘉立创商城下载,这个步骤我就不教了。

        看到手册,我们知道

1.这个IC的封装长这样的

2.相关引脚功能是这样的

3.波形时序图编码规则是这样的

ok,了解到这些就足够了

下面就用示波器/逻辑分析仪捕获波形

这个就是整个波形的一个周期,里面就包含了,同步码+24BIT的数据位

分析这个波形之前,我们得测量这个波形高低电平的脉宽时间,这是写代码的关键,如果不知道这个,代码是没办法完成编写的

ok,这些时间都知道了,现在我就先说个编写代码的大概原理,读者可以先自行编写,若无果。则可参考笔者的,笔者的代码也是从网上参考借鉴,若有不对之处,有劳各位读者批评指正!

思路:根据这些波形,我们可以基于定时器100us中断产生一次中断,然后读取IO口电平高低所占的时间,来判断是否接收到了同步码→数据位

下面先解析我写的代码

//*******************************************************************
主函数:
int main(void)
{

	
	RCC_GetClocksFreq(&RCC_Clocks);
	EV1527_GPIO_Init();
	Timer_Init();
	LED_Init();

	while(1)
	{
      if(decode_ok == 1)   //解码成功
        {
            switch(rf_data[2])
            {
                case 0x91:   //解码为0xf8,点亮LED
									GPIO_ResetBits(GPIOC, GPIO_Pin_13);
                

                break;
                
                case 0x92:   //解码为0xf2,熄灭LED
                  GPIO_ResetBits(GPIOC, GPIO_Pin_13);

                break;
								
                case 0x94:   //解码为0xf8,点亮LED
                GPIO_SetBits(GPIOC, GPIO_Pin_13);

                break;
                
                case 0x96:   //解码为0xf2,熄灭LED
                GPIO_SetBits(GPIOC, GPIO_Pin_13);
                break;
            }

        }				
	}
}

//*******************************************************************

//*******************************************************************
Timer.c

void EV1527_GPIO_Init(void) //EV1527 IO口初始化
{
    GPIO_InitTypeDef GPIO_InitStruct;
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // PB9 输入端
	
    GPIO_InitStruct.GPIO_Pin     = GPIO_Pin_9; 
    GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
}
//*******************************************************************


void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//50ms
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;//10000=1S
	TIM_TimeBaseInitStructure.TIM_Prescaler =72-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}



uint8_t RF;
uint8_t decode_ok;            //解码成功
uint8_t  hh_w,ll_w;           //高,低电平宽度
uint8_t  ma_x;                //接收到第几位编码了
uint8_t  bma1,bma2,bma3,bma4; //用于接收过程存放遥控编码,编码比较两次,这是第一次
uint8_t  mma1,mma2,mma3,mma4;
uint8_t mmb1,mmb2,mmb3,mmb4; // 用于接收过程存放遥控编码,第二次
//extern uint8_t mmb1,mmb2,mmb3,mmb4;

uint8_t rf_ok1,rf_ok2,rf_ok;         //解码过程中的临时接收成功标志,接收到一个完整的遥控命令后置1,通知解码程序可以解码了
uint8_t old_rc5;             //保存上一次查询到的电平状态
uint8_t tb_ok;               //接收到同步的码时置1   
uint8_t D0,D1,D2,D3 ;
uint16_t s ,s1; 
uint8_t bt_auto;     //自动设置遥控接收波特率标志
extern uint8_t rf_data[4];  

void TIM2_IRQHandler(void)//100us产生一次中断
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update); 

        //接收数据的电平 PB9
        RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9); 
        if (!RF) // 检测到低电平 低电平时间加1
        { 
            ll_w++;   
                      // 保存上一次查询到的电平状态
            old_rc5=0; 
        }               
         else         // 检测到高电平
         { 
            hh_w++;
            if (!old_rc5)  // 检测到从低到高的跳变,已检测, 到一个完整(高-低)电平周期                          
            {   
                if (((hh_w>=2)&&(hh_w<=5))&&((ll_w>=100)&&(ll_w<=130))) //判同步码    2/5 100/130
                { 
                    tb_ok = 1 ;//接收到同步码标志位
                    ma_x = 0;
                    bma1=0; bma2=0; bma3=0; bma4=0;    
                }
                else if ((tb_ok)&&((ll_w>=8)&&(ll_w<=13))) //8/13
                {   
                    ma_x++; //已经接收到同步码,判0
                    if(ma_x>23)
                    {
                        if(!rf_ok1) //rf_ok1临时接收成功
                        {   //将接收到的编码复制到解码寄存器中 
                            mma1=bma1;
                            mma2=bma2;
                            mma3=bma3;
                            mma4=bma4; 
                            // 通知解码子程序可以解码了                                                        
                            rf_ok1=1;                    
                            tb_ok=0;
                            s=1000;                             
                         }
												 else
												 {  //将接收到的编码复制到解码寄存器中  
														mmb1=bma1;
														mmb2=bma2;
														mmb3=bma3;
														mmb4=bma4;  
														// 通知解码子程序可以解码了                                             
														rf_ok2=1;                     
														tb_ok=0;                                                                        
                          }
                      }
                 }  
								 else if ((tb_ok)&&((ll_w>=2)&&(ll_w<=7)))   // 2/7
								 { 
										 switch (ma_x)
										 {  //遥控编码第1位
											 case 0 :  bma1=bma1 | 0x80;  break;   
											 case 1 :  bma1=bma1 | 0x40;  break; 
											 case 2 :  bma1=bma1 | 0x20;  break; 
											 case 3 :  bma1=bma1 | 0x10;  break; 
											 case 4 :  bma1=bma1 | 0x08;  break; 
											 case 5 :  bma1=bma1 | 0x04;  break; 
											 case 6 :  bma1=bma1 | 0x02;  break; 
											 case 7 :  bma1=bma1 | 0x01;  break; 
											 case 8 :  bma2=bma2 | 0x80;  break; 
											 case 9 :  bma2=bma2 | 0x40;  break; 
											 case 10:  bma2=bma2 | 0x20;  break; 
											 case 11:  bma2=bma2 | 0x10;  break; 
											 case 12:  bma2=bma2 | 0x08;  break; 
											 case 13:  bma2=bma2 | 0x04;  break; 
											 case 14:  bma2=bma2 | 0x02;  break; 
											 case 15:  bma2=bma2 | 0x01;  break; 
											 case 16:  bma3=bma3 | 0x80;  break; 
											 case 17:  bma3=bma3 | 0x40;  break; 
											 case 18:  bma3=bma3 | 0x20;  break; 
											 case 19:  bma3=bma3 | 0x10;  break; 
											 case 20:  bma3=bma3 | 0x08;  break; // 按键状态第1位
											 case 21:  bma3=bma3 | 0x04;  break; 
											 case 22:  bma3=bma3 | 0x02;  break; 
											 case 23:  
												 bma3=bma3 | 0x01;              
													if(!rf_ok1)
													{
															mma1=bma1;
															mma2=bma2;
															mma3=bma3;       // 将接收到的编码复制到解码寄存器中                             
															rf_ok1=1;        // 通知解码子程序可以解码了
															tb_ok=0;	
															s=1000;
															break;                                 
													}
													else
													{
															mmb1=bma1;
															mmb2=bma2;
															mmb3=bma3;			// 将再次接收到的编码复制到解码寄存器中,                             
															rf_ok2=1;         // 通知解码子程序可以解码了
															tb_ok=0;
															break;                                                                          
												 }                                    
										 }
								} 
               ma_x++; 
								
            }
					  else
					  {
							ma_x=0; 
							tb_ok=0;
							bt_auto=0;
							bma1=0;
							bma2=0; 
							bma3=0; 
							hh_w=1;
							ll_w=0;
					  }    
						 //接收到不符合的高-低电平序列
						 ll_w=0;hh_w=1; 
         }          
             old_rc5=1;      // 记录本次电平状态
       }
	 if(rf_ok1)  //规定时间内接受到2帧相同的编码数据才有效
	 {
		s--;
		if(!s) rf_ok1=0;
		if(rf_ok2) 
		{
			if((mma1==mmb1)&&(mma2==mmb2)&&(mma3==mmb3))
			{
					rf_ok=1;
					rf_ok1=0;
					rf_ok2=0;                    
			}
			else
			{
					rf_ok=0;
					rf_ok1=0;
					rf_ok2=0;
			}          
		}                   
	 }

	if((rf_ok))      //判断是否接收成功
	{   
			TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
			rf_ok=0; 
			rf_data[0]=mma1;
			rf_data[1]=mma2;
			rf_data[2]=mma3;

			decode_ok=1;

			TIM_ITConfig(TIM2  , TIM_IT_Update, ENABLE);
	}
}


如有不懂的,欢迎讨论!


http://www.kler.cn/a/389684.html

相关文章:

  • 【OceanBase 诊断调优】—— ocp上针对OB租户CPU消耗计算逻辑
  • 每日一练:二分查找-搜索插入位置
  • 什么是数字图像?
  • Unity3D学习FPS游戏(12)敌人检测和攻击玩家
  • 多叉树笔记
  • 算法演练----24点游戏
  • 贪心算法-汽车加油
  • oneplus6总结记录-Lineage19.1-android12
  • 密码学的基本原理
  • [ARM-2D 专题]6.脏矩形定义的宏使用技巧和分析
  • node.js电子发票(铁路电子客票)查验接口,让您的企业报销流程更顺畅
  • Java List——针对实习面试
  • 【Java多线程】线程安全及解决方案(详解)
  • monkey-安卓稳定性测试
  • Web3 游戏周报(11.03 - 11.09)
  • springboot苍穹外卖实战:十一:复盘总结
  • 除草机器人算法以及技术详解!
  • Debezium日常分享系列之:异步 Debezium 嵌入式引擎
  • 【计算机图形学】3DIT的训练数据总结
  • 问:说说Spring中构造函数注入和Setter注入的区别?
  • Maven 中央仓库地址 mvnrepository.com
  • Maven从浅入深(理解篇)
  • K8S之Prometheus 部署(二十)
  • 《实时流计算系统设计与实现》-Part 1-笔记
  • 算法每日双题精讲——滑动窗口(长度最小的子数组,无重复字符的最长子串)
  • FreeRTOS学习11——时间片任务调度