1、首先了解一下433遥控芯片ev1527的基本资料:
这是他编码的关键信息:
也就是说,一帧数据是:一个同步码+20位内码+4位按键码。
内码20位=2^20=1048576个地址。
发送就是一帧数据接一帧数据不间断发送。
2、解码思路
从上面的帧结构来分析,我的解码思路是:
1、STM32单片机配置一个引脚中断,设置为上下沿触发
2、单片机配置1个定时器,用于记录时间
3、抓住关键特征,可以看到,同步码是一帧数据的开头,它的特征是124CLK的低电平时间,所以:
3.1、测量这一帧数据的低电平时间,
3.2、如果低电平时间为124clk,就认为收到同步码,接下来要开始收数据码
3.3、收到同步码后,不断测量数据码的低电平时间,并存入BUF[24]这个数组,
3.4、接收完24个低电平后,一帧数据接收完毕。如果中途接收到同步码,就从头开始接收数据码。
3.5、解码:DATA(H)的低电平是4CLK,DATA(L)的低电平是12CLK,分析数组中的低电平时间,就可以完成解码。
3、配置
定时器配置:
IO口配置为上下边沿触发
记得打开中断
4、程序编写
首先头文件:
#ifndef __EV1527_H
#define __EV1527_H
#include "main.h"
typedef struct
{
uint8_t ucRecOK; /*接收成功*/
uint8_t ucKeyCode; /*按键码*/
uint32_t ulChipID; /*芯片ID*/
uint16_t usaLowTime[24];/*24位低电平数据时间长度*/
}ev1527Type_T;
extern ev1527Type_T g_tEV1527Rx;
void EV1527_Decode(ev1527Type_T *tpEV1527);/*EV1527解码*/
#endif
再C文件:
#include "ev1527.h"
#include "tim.h"
ev1527Type_T g_tEV1527Rx;
/*
******************************************************
* 说明:PA0引脚中断回调函数,上下边沿中断配合定时器1,统计低脉冲宽度,因为引导码的特征值是低脉冲宽度是124CLK。
* 输入:
* 输出:
******************************************************
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
uint16_t usPortLevel;
uint16_t usLowTime;
static uint8_t ucLeadCodeFind = 0;
static uint8_t ucTimePos;
usPortLevel = GPIOA->IDR & 0X0001;
if(usPortLevel)/*上升沿,完成低脉冲检测*/
{
usLowTime = __HAL_TIM_GetCounter(&htim1);
__HAL_TIM_DISABLE(&htim1);
if(usLowTime > 9920 && usLowTime < 14880)/*引导码,12400,误差20%*/
{
ucLeadCodeFind = 1;
ucTimePos = 0;
}
/*可先进行低电平时间判断,滤除杂波干扰*/
else/*其他低脉冲*/
{
if(ucLeadCodeFind)/*只有找到引导码的情况下,才进行数据接收*/
{
g_tEV1527Rx.usaLowTime[ucTimePos++] = usLowTime;
if(ucTimePos >= 24)
{
ucTimePos = 0;
ucLeadCodeFind = 0;
g_tEV1527Rx.ucRecOK = 1;/*置位接收完成标志*/
}
}
}
}
else/*下降沿,启动低脉冲宽度检测*/
{
__HAL_TIM_SetCounter(&htim1,0);
__HAL_TIM_ENABLE(&htim1);
}
}
/*
******************************************************
* 说明:解码EV1527,使用低电平时间判断,低电平280-520ms之内,判断为1,否则为0;
* 输入:tpEV1527指针,解码完毕后,赋值到指向的结构体中的按键码和芯片ID;
* 输出:
******************************************************
*/
void EV1527_Decode(ev1527Type_T *tpEV1527)
{
uint8_t i;
uint32_t ulCombinedCode = 0;
for(i=0; i< 24; i++)/**/
{
ulCombinedCode <<= 1;
/*
* 400us,误差±30%。
* 示波器实测最后一位的低电平时间比其他位的低电平时间要长,可考虑增加宽度。
* 可能是发射芯片发射完最后一位后,转入到引导脉冲所需时间比较长导致。
*/
if(tpEV1527->usaLowTime[i] > 280 && tpEV1527->usaLowTime[i] < 520)
{
ulCombinedCode |= 0x01;
}
}
tpEV1527->ucKeyCode = ulCombinedCode & 0x0000000f;
tpEV1527->ulChipID = (ulCombinedCode & 0xfffffff0) >> 4;
}
文件说明:
接收一帧数据后,就是解码了
注释已经写得非常明白了。
5、使用
直接在main函数里面判断是否接收完成,然后调用解码即可:
if(g_tEV1527Rx.ucRecOK)
{
g_tEV1527Rx.ucRecOK = 0;
EV1527_Decode(&g_tEV1527Rx);
}
实际解码如下图:
6、写在最后
1、直接示波器测量4CLK的时间长度,不要用计算振荡电阻的结果。
2、有些芯片在发完最后一个数据位,然后紧接发同步脉冲的高电平,不知道是他们的芯片速度问题还是其他原因,最后一个数据位的低电平时间,要比其他数据位的低电平时间要长。所以,在判断的时候,要特殊关注一下。这个问题在我的解码函数里面有注释。