STM32 EV1527无线通信(433)

  • EV1527无线通信

先说一下这个通信协议的数据格式,这个图片是我在手册里截的。

  1. 大家按照单片机类型计算周期,我的是STM32f103vb (4CLK大致等于350um)
  2. 发送时按照 先发同步码后发DATA 的顺序   逻辑1或者逻辑0按照以上高低电平延时时间长度发送
  • 无线通信发送模式

  1. 发送很简单,按照数据格式发就行,就是在处理数据上有所变化。无论想发什么数据,16进制10进制最后都要转化成2进制,01发送,从低位向高位发送。
  2. 初始化函数在发送模式里。
/*
@Description 输出高低电平按EV1527协议  
@mode 逻辑0或1
*/
void S433_SendBit(u8 mode){

    if(mode==1)
    {
        PEout(9)=1;    
        SysTick_Delay_Us(350*3);
        PEout(9)=0;
        SysTick_Delay_Us(350);

    }else if(mode==0)
    {
        PEout(9)=1;    
        SysTick_Delay_Us(350);
        PEout(9)=0;
        SysTick_Delay_Us(350*3);

    }else{
        debug_led(1, LED_TOGGLE);
    }

}

/*
@Description 同步脉冲(或叫引导) 
*/
//同步脉冲 4:124
void Sync_Pulse(){


    PEout(9)=1; 
    SysTick_Delay_Us(350); 
    PEout(9)=0; 
    SysTick_Delay_Us(350*31);

}

/*
@Description 发送码函数调用
@num 24位二进制的 10进制数
*/
//对发送过来的10进制数进行处理 , 根据需求可以更改
void S433_Send(u32 num){
u8 i;
u32 result=24,temp;
temp = num;

Sync_Pulse();

    while(result){
        i = temp%2; //对十进制数取余 结果等于最低位二进制数
        S433_SendBit(i);
        temp = temp/2;//除二取整
        result--;
    }

}
  • 无线通信接收模式

  接收要比发送复杂得多,思路就是

  通过触发外部中断处理函数,来检测数据,每触发一次上升或下降沿,记一下时间,根据时间长度来判段杂波,同步波还是数据波,接收关键在于判断。

  下面一段是一些值的初始化,和IO引脚的初始化

static volatile unsigned long long rx433_previous_time = 0;//上一次进入中断时间
static volatile unsigned char Sync_Pulse_begin =0;//检测同步脉冲完整性 1是同步脉冲 
static volatile unsigned char  rx433_begin= 0;//同步脉冲开启标志1开启 0没开
static volatile unsigned short interval_previous_time=0;//上一个间隔时间
////////////
static volatile u8 Rx433Cnt=0;
static volatile u8 Rx433bit[30]={0}; 
static volatile u8 rxbit=0;
static volatile u8 firstbit=0;
static volatile u32 Rx433[64]={0};
///////////



//对管脚初始化 参考普通IO管脚用通信
void S433_SR_Init(){

    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //使能GPIOE时钟

    //E9使能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOE, GPIO_Pin_9);//  引脚拉低
    //接收 E7
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;   //输入为低
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource7);

    EXTI_InitStructure.EXTI_Line=EXTI_Line7;
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling;
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);


}

是否是同步波判断,以及检测发送完成度

/*
@Description 判断是否是同步脉冲
@pre 之前时间段数
@now 现在时间段数
@return rebit开启同步 success同步成功 synerror 不是同步脉冲
*/
u8 Sync_PulseRx(u8 pre,u8 now){

    if(!PEin(7)){//每次下降沿开始测

    Sync_Pulse_begin=1;//开始检测同步脉冲
    
    
    }else if(Sync_Pulse_begin==1&&(pre==1)&&(now==31)){//满足条件则判断出时间脉冲

    Sync_Pulse_begin=0;//同步成功将同步码关掉
    rx433_begin=1;//正式开始传输数据
    rxbit=0;//将数据位数清零
    firstbit=1;//置一等待下个跳变正式开始
    return success;
    }else{

    Sync_Pulse_begin=0;//不是脉冲置0
    return synerror;
    }
    return rxbit;

}


/*
@Description 判断逻辑0和1
@pre 之前时间段数
@now 现在时间段数
@return  rxerror 接收超位
*/
u8 RX433_Bit(u8 pre,u8 now){
if(firstbit==1){
firstbit=0;//此步骤防止引导完成后直接进入此函数
}else if(rx433_begin==1&&PEin(7)){//上升沿检测

    if(rxbit>24){//能加到24 说明一帧数据获取到了
    rxbit=0;//归零
    rx433_begin=0;//归零 及下一组做准备

    }

    if(now==3&&pre==1){//逻辑0
        Rx433bit[rxbit]=0;
        rxbit++;
    }else if(now==1&&pre==3){//逻辑1
        Rx433bit[rxbit]=1;
        rxbit++;
    }else{
    //跑飞
    rx433_begin=0;
    rxbit=0;
    return rxerror;
    } 

return rxbit-1;
}
return 0;
}

外部中断处理函数,常常被触发,因为接收各种杂波,但进入不了关键的处理函数。

//先判断同步脉冲
//如果是同步脉冲,begin开启判断数据接收并判断情况情况
//如果数据接收位超过预期24位,数据位数接收超量(状态)
//如果从一半开始接收,无视这一段,从下一段开始
void EXTI9_5_IRQHandler(void){

    if(EXTI_GetITStatus(EXTI_Line7)!=RESET)
    {
        unsigned char skip_index = 0;//这次几个数据位
        unsigned char skip_pervious_index=0;//之前几个数据位
        unsigned long long now_time=sys_micros();//此刻时间
        unsigned short interval_time = now_time - rx433_previous_time;//计算一个电平状态持续的时长
        rx433_previous_time = now_time;//为下次计算时长做准备
        skip_index = (interval_time/349);//得出某个电平持续时长的倍数 计算出几段高或低电平
        skip_pervious_index=(interval_previous_time/349);//同上 不过是前一次的
        
        Sync_PulseRx(skip_pervious_index,skip_index);//同步脉冲
        RX433_Bit(skip_pervious_index,skip_index);//数据位
        
        if(interval_time<45000){
        interval_previous_time = interval_time;
        
        }else{
        interval_previous_time = 0;    
    
        }
        EXTI_ClearITPendingBit(EXTI_Line7);//清除中断挂起标志位

    }

}

猜你喜欢

转载自www.cnblogs.com/zhy-alive/p/11304422.html