STM32下315M模块的无线接收解码程序

最近项目需要增加一个控制机器运行的紧急遥控,参考了一个大神的博客,然后我们选择了这样的遥控器和一个315M模块,实现遥控器的按键控制。

附上遥控器链接315M 模块链接淘宝。

首先介绍一下315M模块。315M是指频率为315MHz,还有433M也是比较常用的。其中它使用的芯片是EV1527型,EV1527 每帧数据由 24 个数据位组成,前 20 位为地址码,对于一个芯片来说,地址位的内容是固定的,是出厂前就预制好的,并且理论上每个芯片的地址码是唯一的。后面 4 位为按键码,对应芯片上的K0-K3 4 根数据线,数据线的状态不同,按键码就不同。 具体可以参考链接,我这里只是记录解析。

我们将模块通上电,在它的Data引脚出现无规律的波形。然后按下遥控器之后,芯片会接受到遥控器的信号,出现有规律的波形,如下图。(看着是不是显得头大了?)

根据前者参考资料里了解到,每个帧由24 个数据位组成,前20位是固定不变的地址位,后4位为按键位。在数据位之前,还有一个同步脉冲。我们需要捕获到同步脉冲之后,检测地址数据和按键数据。

同时数据位的“1”和“0”是由高低电平宽度(脉冲宽度)的比例决定的。如果高电平宽度为低电平宽度的 3 倍,就表示逻辑“1”,反过来如果低电平为高电平宽度的 3 倍,就表示逻辑“0”。同步脉冲高电平和低电平的比例固定为 4:124。

我们按下遥控器按键后,检测315M的Data引脚,同时将示波器定住放大如图所示。可以看到有很长一段低电平,此时是它的同步码过程,我们需要检测同步码过程。我们首先检测同步码前面一个的一个脉冲宽度,这个脉冲宽度基本上是遥控器的频率基数(每个遥控器可能脉冲宽度不一样)。将示波器放大,从示波器上看出此时脉冲宽度约为360us,那么CLK频率约为90us。(如果不把示波器放大的话,可能结果CLK可能为100us,影响误差)

那么这样就好办了,我们用stm32定时器定时产生90us的中断,来检测Data引脚的高低电平来检测0或者1。(16个CLK中,若12个为高则为1;若12个为低则为0)。然后在找到同步码后,检测地址码,接着解析按键码。然后判断两次接收的按键码一致,认为按键按下了。

代码如下:

BSP_315M.h

#ifndef __BSP_315M_H__
#define __BSP_315M_H__

#include "stm32f10x.h"                  
#include "delay.h"
#include "usart.h"

#ifdef __cplusplus
extern "C" {
#endif
	
	void EV1527_Init(void); 
	void TIM1_NVIC_Init(void);
	void TIM1_Mode_Init(void);
	void TIM1_UP_IRQHandler(void);
	uint32_t GetAddr_315M(void); //获取设备地址
	uint8_t GetKey_315M(void); //获取1527M按键号
	void Rst_rf_data(void);  //调用GetKey_315M()函数后将rf_data置为零
	
#ifdef __cplusplus
}
#endif
	
#endif

BSP_315M.c

#include "BSP_315M.h"	
//*******************数据定义区*********************************//
uint8_t RF;//接口电平
uint8_t a_code1, a_code2, a_code3; //第一次遥控编码
uint8_t rf_ok1;//第一次遥控编码赋值成功
uint8_t b_code1, b_code2, b_code3; //第二次遥控编码
uint8_t rf_ok2;//第二次遥控编码赋值成功
uint8_t t_code1, t_code2, t_code3; //临时遥控编码
uint8_t last_state;//上一个编码,0为低,1为高
uint8_t hh_w,ll_w;//高低电平宽度
uint8_t flag_syn;//同步码标志位,置1表示已经收到同步码,置0表示未收到同步码
uint8_t rf_data[3]; //最后收到的遥控编码
uint8_t  ma_x;                //接收到第几位编码
uint16_t s; // 收到第一个码和第二个码之间不能超过s个周期
uint8_t rf_ok=1;
//*************************************************************//

void EV1527_Init() //EV1527
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 
	  GPIO_InitStruct.GPIO_Pin     = GPIO_Pin_13; 
    GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
		TIM1_Mode_Init();
		TIM1_NVIC_Init();
}

void TIM1_NVIC_Init()   
{
NVIC_InitTypeDef NVIC_InitStructure;    
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

NVIC_InitStructure.NVIC_IRQChannel =   TIM1_UP_IRQn; 

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 

NVIC_Init(&NVIC_InitStructure); 
}

void TIM1_Mode_Init()
{    
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  NVIC_InitTypeDef NVIC_InitStructure;  
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 
  //((1+71)/72M))*(1+89)=90us
  TIM_TimeBaseStructure.TIM_Period = 89;  
  TIM_TimeBaseStructure.TIM_Prescaler = 71;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
  TIM_ClearFlag(TIM1, TIM_FLAG_Update); 
  
  TIM_ITConfig(     
    TIM1,            
    TIM_IT_Update |   TIM_IT_Trigger,  
    ENABLE      
    );  
      
  
  NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;    
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;       
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);   
  
  TIM_Cmd(TIM1, ENABLE);    
}

void TIM1_UP_IRQHandler(void)  
{
	
      if(TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM1, TIM_IT_Update); 
				
        RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
	//printf("%d", RF);
	//接收到低电平,ll_w自加,上一状态设为低电平
        if (!RF){ 
            ll_w++;                         
            last_state = 0;
	//printf("low!\r");
        }    
	//接收到高电平,hh_w自加
	//所有的同步码最后一位,每个编码的最后一位都是由低变为高的。
        else { 
            hh_w++;
	//如果上一状态为低电平,即由低变为高的上升沿	
	//printf("hh_w =%d!\r\n", hh_w);
            if (!last_state)  
            {   
	//printf("ll_w =%d!\r\n", ll_w);
	//如果未接收到同步码,判断同步码的开始时刻
                if (((hh_w>=1)&&(hh_w<=5))&&((ll_w>=90)&&(ll_w<=140))){ 
                    flag_syn = 1 ;
                    ma_x = 0;
                    t_code1=0; t_code2=0; t_code3=0; //初始化 
	//printf("\r\n\r\n");									
                }
	//如果已接收到了同步码并且接到3个CLK的位0
                else if ((flag_syn)&&((ll_w >= 7)&&(ll_w <= 14))){   
                    ma_x++; 
	//printf("L\r\n");
	//如果接收的码大于了23个
                    if(ma_x>23){
	//rf_ok1接收未完成
                        if(!rf_ok1){ 
	//第一次接收的编码标志
                            a_code1=t_code1;
                            a_code2=t_code2;
                            a_code3=t_code3;													
                           // 可以解码了                                                         
                            rf_ok1=1;                    
                            flag_syn=0; 
		//计时开始
		s=1000;
                         }
		//如果rf_ok1接收成功,将数据存到第二组
                        else{
                            b_code1=t_code1;
                            b_code2=t_code2;
                            b_code3=t_code3;  																																 
		            rf_ok2=1;                     
		            flag_syn=0;                                                                        
                       }
                    }
                  }  
                  else if ((flag_syn)&&((ll_w>=2)&& (ll_w<=6))) { 
		//printf("H\r\n");	
		 switch (ma_x)
		 { 
		     case 0 : { t_code1=t_code1 | 0x80; break;} 
                     case 1 : { t_code1=t_code1 | 0x40;break; }
                     case 2 : { t_code1=t_code1 | 0x20;break; }
                     case 3 : { t_code1=t_code1 | 0x10;break; }
                     case 4 : { t_code1=t_code1 | 0x08;break; }
		     case 5 : { t_code1=t_code1 | 0x04;break; }
		     case 6 : { t_code1=t_code1 | 0x02;break; }
		     case 7 : { t_code1=t_code1 | 0x01;break; }
		     case 8 : { t_code2=t_code2 | 0x80;break; }
		     case 9 : { t_code2=t_code2 | 0x40;break; }
		     case 10: { t_code2=t_code2 | 0x20;break; }
		     case 11: { t_code2=t_code2 | 0x10;break; }
		     case 12: { t_code2=t_code2 | 0x08;break; }
		     case 13: { t_code2=t_code2 | 0x04;break; }
		     case 14: { t_code2=t_code2 | 0x02;break; }
		     case 15: { t_code2=t_code2 | 0x01;break; }
		     case 16: { t_code3=t_code3 | 0x80;break; }
		     case 17: { t_code3=t_code3 | 0x40; break; }
		     case 18: { t_code3=t_code3 | 0x20;break; }
		     case 19: { t_code3=t_code3 | 0x10;break; }
		     case 20: { t_code3=t_code3 | 0x08;break; }
		     case 21: { t_code3=t_code3 | 0x04;break; }
		     case 22: { t_code3=t_code3 | 0x02;break; }
		     case 23: { t_code3=t_code3 | 0x01;              
                                  if(!rf_ok1)
                                  {
                                      a_code3=t_code3;
                                      a_code2=t_code2;
                                      s=100;
                                  }
                                  else
                                  {
                                      b_code3=t_code3;
                                      b_code2=t_code2;
                                      b_code1=t_code1;
				}   
			               flag_syn=0;
                                       break;  	
                          }
                    } 
                    ma_x++; 
                 }
                 else{ ma_x=0; flag_syn=0;t_code3=0;t_code2=0; t_code1=0;ll_w=0; }                                    
                    ll_w=0;hh_w=1; 
             }          
                 last_state=1; 
		//printf("ma_x = %d", ma_x);						 
				}
	 if(rf_ok1)  
		{
		//printf("ok1\r\n");
		s--;
		if(!s) rf_ok1=0;
		if(rf_ok2) {
			if((a_code1==b_code1)&&(a_code2==b_code2)&&(a_code3==b_code3)){
				rf_ok=1;
				rf_ok1=0;
				rf_ok2=0;                    
					}
			else{
				rf_ok=0;
				rf_ok1=0;
				rf_ok2=0;
					}          
				}                   
		}

    if((rf_ok))     
    {   //printf("ok2\r\n");
	TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE);
        rf_ok=0; 
        rf_data[0]=a_code1;
        rf_data[1]=a_code2;
        rf_data[2]=a_code3;
	//printf("rf_data[2] =%d\r\n",rf_data[2]);
        TIM_ITConfig(TIM1  , TIM_IT_Update, ENABLE);
        }
    }
		
}

uint32_t GetAddr_315M(){		
	uint32_t result = ((rf_data[0] << 16) + (rf_data[1] << 8) + (rf_data[2] & 0xF0) )>> 4;
	//printf("%d\r\n",result);
	return result;
}
	
uint8_t GetKey_315M(){
	uint8_t result = (rf_data[2] & 0x0F);
	//printf("result = %d\r\n",result);
	return result;
}	

void Rst_rf_data(){
	rf_data[2]= 0x00;
}	

mian.c

#include "BSP_315M.h"


int main(void)
{	
	SystemInit();//系统初始化
	delay_init(72);	//延时初始化 
	EV1527_Init(); 	
	while(1)
	{
		tmp = GetKey_315M();				
		if(tmp == 0x08){
		//定义你自己的按键A函数
			Rst_rf_data();
		}

		if(tmp == 0x04){
		//定义你自己的按键B函数
			Rst_rf_data();							
		}
		if(tmp == 0x02){
		//定义你自己的按键C函数
			Rst_rf_data();
		}
	}

}

 

 

 

  • 17
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值