433实例代码, EV1527, 不用占用中断, 代码开放接口, 兼容所有单片机

一个优秀的函数, 有应当做到"省资源", "效率高", "兼容性好", 减少重复造轮子, 杜绝史山从我做起 !

EV1527数据手册:   

链接:https://pan.baidu.com/s/1RARhTqEsCnwZW7-pIqdTZg 
提取码:qmos

EV1527的通讯协议非常简单, 根据手册可知, 在接收到信号后, TXD引脚将会输出如下格式的时序

由此可知, 需要计算1LCK的时间, 根据实际应用, 1LCK并不固定, 不同厂商的芯片时序也不一致, 因此计算OSC CLOCK的方法不现实, 不同环境下不同厂商, 信号长度定义不一样, 上述时序仅参考, 实际波形长度会有出入

因此最好的方法是用逻辑分析仪抓取接收信号, 以下是本人项目中所用的模块抓取的信号波形, (不同电路和芯片厂商的波形不一致!), 以该波形为案例做解析实例.

空闲时的波形:

空闲时接收到许多杂波, 同时每隔5ms左右会强制有一个高电平的脉冲

实际上有5ms一次的高电平脉冲的作用是为了区分"同步码"

接收到信号时的波形:

前半部分基本都是杂波和5ms的周期脉冲, 后半部分就是重复的信号波形, 并且中间间隔时间为11ms左右(大于5ms) , 这对于区分杂波和有效值有着重要作用

放大查看, A1到A2就是"同步码", 在该项目中, 同步码高电平占450us左右, 低电平占11000us左右

因此程序的第1步是检测同步码与杂波

开始写代码之前, 先做初始化工作

初始化和准备工作

初始化一个"时间计数器", 用于计算时间

static uint8_t EV1527_T_Counter = 0;  //计时用

编写一个计时函数, 可放到定时器里, 理论上定时器的周期越大越好, 减少对系统的占用, 我这里使用了200us的定时, 作为时基作用

void EV1527_Timer_Func()//需要单位时间执行一次(当前设置200us执行一次)
{
	if(EV1527_T_Counter<255)
	{
		EV1527_T_Counter++;
	}
}
static void EV1527_ReStart_Timer()//重置计时
{
	EV1527_T_Counter = 0;	
}

好了, 现在可以判断同步码了

检测空闲波或者同步码

上述说到, 空闲时, 5ms左右会有一个高电平短脉冲, 并且5ms内会有杂波

而同步码高电平脉冲后会有11000us的低电平, 不会有杂波,

因此只需要判断高电短平脉冲完成后, 低电平持续的时间即可, 此处阈值设为8000us, 大于8000us则判断为同步码, 同时检测超过140000us则判断为错误码

#define Get_EVA1527_Dat_IO()        (PA0)
#define BOOL_EV1527_BIT_IS_START	(EV1527_T_Counter>=40)//高脉冲过后, 低电平大于8000us则判断是对齐码(40*时基200us=8000us)
#define BOOL_EV1527_TIMEOUT1		(EV1527_T_Counter>=70)//高脉冲过后, 低电平超过14000us则为错误值(70*时基200us=14000us)

static uint8_t EV1527_Step1;    //检测步骤
static uint8_t EV1527_Step2;    //暂不阐述作用
uint8_t EV1527_Code[3];        //暂不阐述作用
uint8_t EV1527_getCode[3];    //暂不阐述作用

void EV1527_main()
{
	switch (EV1527_Step1)
	{
		//-------------检测同步码------------------
		case 0:
			if(Get_EVA1527_Dat_IO()==1)//检测到上升沿
			{
				EV1527_Step1++;
			}
			break;
		case 1:
			if(Get_EVA1527_Dat_IO()==0)//检测下降沿
			{
				EV1527_ReStart_Timer();//重新计时
				EV1527_Step1++;
			}
			break;
            //----此时高脉冲发送完毕--
            //开始检测低电平的时间
		case 2:
			if(BOOL_EV1527_TIMEOUT1)
			{
				//低电平长度超时
				EV1527_Step1 = 0;
			}
			else if(Get_EVA1527_Dat_IO()==1)//检测到上升沿
			{
				if(BOOL_EV1527_BIT_IS_START)
				{
					//对齐码正确
					EV1527_Step1++;

                    EV1527_ReStart_Timer();//下一步还需要计时
                    //此时可为后续步骤做一些变量的初始化
					EV1527_Step2=0;
					EV1527_getCode[0]=0x00;
					EV1527_getCode[1]=0x00;
					EV1527_getCode[2]=0x00;
					
				}
				else
				{
					//不是对齐码,可能是杂波
					EV1527_Step1 = 0;
				}
			}
			break;
		//-------------检测内码和数据码------------------
		case 3:
        ...
	}
}

检测内码和按键码:

跟在同步码之后的就是内码(20位)和按键码(4位), 共24位

内码和按键码的, 根据手册可知, 标准情况下, 每一位数据, 周期是16个LCK, 发送时高电平先行, 低电平紧跟其齐后

标准情况下, 若位为1时, 高电平占12LCK, 低电平占4LCK

标准情况下, 若位为0时, 高电平占4LCK, 低电平占12LCK

因此判断位码开始的高电平的时间, 即可完成0和1的判断, 可忽略低电平的时间

以下是波形实测

由此可见, 同步码之后, 第一位的高电平比低电平长, 明显为1

第二位的高电平比低电平长,也是1

第三位的高电平比低电平短, 是0

可以看出, 为1时, 高电平的长度为11300us左右

为0时, 高电平长度为420us左右

(可看出实际波形与数据手册时序并不完全对应, 实际应用还是要抓波形实测)

现在按照波形读取以下内码和按键码

EV1527支持4个按键, 当对应的按键按下时, 对应的按键码位为1, 组合键时会有多个位为1

因此可判断高电平的长度, 可设置阈值为800us, 小于为0, 大于为1

static uint8_t EV1527_Step1;//检测步骤
static uint8_t EV1527_Step2;//内码和数据码的检测步骤

uint8_t EV1527_Code[3];//存放检测完毕后完整的码
uint8_t EV1527_getCode[3];//存放检测中的码(检测中码会不完整)

uint8_t EV1527_KEYCode;//存放纯按键码

#define BOOL_EV1527_BIT_IS_HIGH		(EV1527_T_Counter>=4)//起始高电平大于等于800us则判断该位是1, 否则为0
#define BOOL_EV1527_TIMEOUT2		(EV1527_T_Counter>=7)//此时设置判断任何电平超过1400us则为错误值

//#define INER_CODE 0b110110001101001010110000 //20位内码, 按照24位3字节左对齐, 低4位为按键码全为0

void EV1527_main()
{
	//抓波形实测, 该模块1LCK约等于90us
	switch (EV1527_Step1)
	{
		...
        case 2:
                ...
				if(BOOL_EV1527_BIT_IS_START)
				{
                    EV1527_Step1++;

					//同步码正确后初始化要用的变量
					EV1527_Step2=0;
					EV1527_getCode[0]=0x00;
					EV1527_getCode[1]=0x00;
					EV1527_getCode[2]=0x00;
                    EV1527_ReStart_Timer();//同时开始重新计算时间
					
				}
				else
				{
					...
				}
			}
			break;
		//-------------检测内码和数据码------------------
		case 3:
			if(BOOL_EV1527_TIMEOUT2)
			{
				//超时重新检测
				EV1527_Step1 = 0;
				break;
			}
			else if(Get_EVA1527_Dat_IO()==0)//直到检测到下降沿
			{
                //此时检测到了下降沿
                //判断高电平的长度
                //大于800us则该位为1
                //小于800us则该位为0

				uint8_t i;
				if(BOOL_EV1527_BIT_IS_HIGH)
				{
					//该位位1
					i=0x80;
				}
				else
				{
					//该位为0
					i=0;
				}
				if(EV1527_Step2 < 8)
				{
					EV1527_getCode[2] |= (i>>EV1527_Step2);
				}
				else if(EV1527_Step2 < 16)
				{
					EV1527_getCode[1] |= (i>>(EV1527_Step2-8));
				}
				else if(EV1527_Step2 < 24)
				{
					EV1527_getCode[0] |= (i>>(EV1527_Step2-16));
				}
				
				if(EV1527_Step2<23)
				{
                    //检测还没完成
					EV1527_Step1 = 4;//切换到步骤4, 等待低电平发送完毕
					EV1527_ReStart_Timer();//重新计时
				}
				else
				{
					//检测完毕
					//重新检测
					EV1527_Step1 = 0;

                    //把完整的码储存到EV1527_Code中供使用
					EV1527_Code[2] = EV1527_getCode[2];
					EV1527_Code[1] = EV1527_getCode[1];
					EV1527_Code[0] = EV1527_getCode[0];
					
					//判断接收到的内码是否正确
					if((EV1527_getCode[0]>(uint8_t)(INER_CODE&0xFF))
					&&(EV1527_getCode[1]==(uint8_t)(INER_CODE>>8))
					&&(EV1527_getCode[2]==(uint8_t)(INER_CODE>>16)))
					{
                        //内码正确, 存放按键码到变量中供系统使用
						EV1527_KEYCode = (EV1527_getCode[0]&0x0F);
					}
					break;
				}
				EV1527_Step2++;
			}
			break;
		case 4:
			{
				if(BOOL_EV1527_TIMEOUT2)
				{
					//超时重新检测
					EV1527_Step1 = 0;
					break;
				}
				else if(Get_EVA1527_Dat_IO()==1)//直到重新检测到上升沿
				{
					EV1527_ReStart_Timer();//重新计时
					EV1527_Step1 = 3;
				}
			}
	}
}

因此代码完成, 当前项目只需要把

void EV1527_Timer_Func()//函数200us执行一次

void EV1527_main()//函数可放到主程序循环里, 或者跟随200us执行一次亦可以

其中200us只是参考值, 要根据实际项目做调整

在实际项目中, 根据实际的波形, 匹配相应的宏定义即可

程序全程不阻塞, 不使用中断, 兼容所有单片机

杜绝史山从我做起 !

进主页可索取完整代码

【免费】433-EV1527解码程序,兼容所有单片机资源-CSDN文库

  • 51
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值