华芯微特SWM34-使用定时器捕获快速解码EV1527编码

在无线应用领域,很多433Mhz和315Mhz的遥控器,红外探测器,门磁报警器,无线门铃等都使用EV1527编码格式来发射数据。发射和接收均有对应的RF芯片完成,而且成本极低(目前市场价3毛钱不到)。接收芯片解调出来数据后,需要进行编码的解码,分离地址码和数据码,以便后续代码使用。

EV1527的编码格式如下:

在这里插入图片描述
在这里插入图片描述
需要特别注意点:

  1. 一帧数据由三个部分组成:同步码,地址码(20bit),数据位(4bit)
  2. 同步码:4个clock的高电平时间+124个clock的低电平时间。
  3. 数据1:12个clock的高电平时间+4个clock的低电平时间。
  4. 数据0:4个clock的高电平时间+12个clock的低电平时间。
  5. 同步码和数据码的脉冲宽度不是用时间来描述的,而是用时钟周期的个数来描述。这就说明,即使用相同的发射芯片,由于使用不同的振荡电阻和制造工艺,pcb走线的不同也会导致脉冲的时间是不同的。但是对于同样工艺,同样设计的pcb,同样芯片的不同产品之间量产具有一致性(同一批产品具有一致性)。

有了以上的基本知识后,我们有两个思路来进行解码:
一. 使用边沿中断加定时器的方式解码.–适合低端单片机,解码复杂。
二. 使用带有脉冲捕获功能的定时器解码。–解码简单。
我们以华芯微特SWM341为例子来讲解如何快速解码:

先定义各个编码的脉冲时间参数(要根据你的发射器实际测量来调整),并且可以允许一定的误差,本项目允许±10%的时间误差(一般的发射器时钟误差小于3%)。

#define EV1527_H4			328 //窄脉冲基本宽度 us,不同的遥控器要实测后确定
#define EV1527_H4_MIN	(EV1527_H4 *90 / 100)
#define EV1527_H4_MAX	(EV1527_H4 *110 / 100)

#define EV1527_H12			998 //宽脉冲基本宽度 us,不同的遥控器要实测后确定
#define EV1527_H12_MIN	(EV1527_H12 *90 / 100)
#define EV1527_H12_MAX	(EV1527_H12 *110 / 100)

#define EV1527_L4			EV1527_H4 //宽脉冲基本宽度 us
#define EV1527_L4_MIN	(EV1527_L4 *90 / 100)
#define EV1527_L4_MAX	(EV1527_L4 *110 / 100)

#define EV1527_L12			EV1527_H12 //宽脉冲基本宽度 us
#define EV1527_L12_MIN	(EV1527_L12 *90 / 100)
#define EV1527_L12_MAX	(EV1527_L12 *110 / 100)

#define EV1527_SYN_L	(11981-328) // 同步脉冲低时间,高时间=EV1527_H4
#define EV1527_SYN_MIN	(EV1527_SYN_L *90 / 100)
#define EV1527_SYN_MAX	(EV1527_SYN_L *110 / 100)

初始化一个带有捕获功能的定时器,测量时间基本单位为1us:

//增强定时器0,捕获应用
void Timer0Init(void)
{
	PORT_Init(PORTB, PIN15, PORTB_PIN15_TIMR0_IN, 1); //pb15,timer0 in for capture
	TIMR_Init(TIMR0, TIMR_MODE_IC, CyclesPerUs, 0xFFFFFF, 0);
	TIMR_IC_Init(TIMR0, 1, 1);
	TIMR_Start(TIMR0);
}

定义几个变量:

static uint32_t highCnt = 0 ,lowCnt = 0; //脉冲的高电平和低电平时间
static uint32_t syn = 0,code = 0,pulseCnt = 0; //同步标志,解码后的code,解码过程中的bit计数
//解码错误后的恢复
static void EV1527Reset(void)
{
	highCnt = 0;
	lowCnt = 0;
	syn = 0;
	code = 0;
	pulseCnt = 0;
}

收到一个有效位后的解码:

static void EV1527Decode(uint32_t v)
{
	code <<= 1;
	if(v)
	{
		code |= 1;
	}
	pulseCnt++;
//	DebugPrintf("c: %d,p= %d \r\n", v,pulseCnt);
	if(pulseCnt == 24)
	{//这里可以根据需要,做不同处理:
	//1. 连续两帧码值相同判定为一次有效码
	//2. 一直是同一个编码的话(中间没有被打断或者停止过),就只有第一次发送,后面的不发送。
	//3. 如果有需要持续按键的应用(比如按住按键调光),可以在满足第一个条件后持续的向上层发送编码信息
	//4. 通过消息队列将解码后的数据发送到应用
		DebugPrintf("Addr: %d,code= %d\r\n", code >> 4,code & 0x000000FF);
		EV1527Reset();
	}
}

捕获中断的处理,也就是一个bit(一个高电平和一个低电平)的解码,每一个脉冲的电平翻转都会产生一次中断,也就能获取到高低电平的持续时间:

void TIMR0_Handler(void)
{
	
	if(TIMR_IC_CaptureH_INTStat(TIMR0))
	{//脉冲的下降沿中断,也就是高电平结束了
		TIMR_IC_CaptureH_INTClr(TIMR0);
		highCnt = TIMR_IC_GetCaptureH(TIMR0);
	}
	else if(TIMR_IC_CaptureL_INTStat(TIMR0))
	{//脉冲的上升沿中断,也就是低电平结束了
		TIMR_IC_CaptureL_INTClr(TIMR0);
		lowCnt = TIMR_IC_GetCaptureL(TIMR0);
		if(syn == 1)
		{//收到同步码后才解码
			if( (lowCnt > EV1527_L4_MIN) && (lowCnt < EV1527_L4_MAX))
			{
					if((highCnt > EV1527_H12_MIN) && (highCnt < EV1527_H12_MAX))
					{ //现在是一个短脉冲,前面必定是一个有效的长脉冲,数据为1,否则就是一个错误脉冲
						EV1527Decode(1);
					}
					else
					{
						EV1527Reset(); //有错误
					}
			}
			else if((lowCnt > EV1527_L12_MIN) && (lowCnt < EV1527_L12_MAX))
			{
					if((highCnt > EV1527_H4_MIN) && (highCnt < EV1527_H4_MAX))
					{ //现在是一个长脉冲,前面必定是一个有效的短脉冲,数据为0,否则就是一个错误脉冲
						EV1527Decode(0);
					}
					else
					{
						EV1527Reset(); //有错误
					}
			}
		}
		else 
		{
			if((lowCnt > EV1527_SYN_MIN) && (lowCnt < EV1527_SYN_MAX))
			{//有满足同步脉冲特征的低电平出现了
				if((highCnt > EV1527_H4_MIN) && (highCnt < EV1527_H4_MAX))
				{ //并且前面是一个有效的同步高脉冲,同步开始(也可能是一个误码)
					syn = 1;
					pulseCnt = 0;
					code = 0;
//					DebugPrintf("syn: %d\r\n", lowCnt);
				}
			}
		}
	}
}

解码程序短小精悍,有几个技巧说明如下:

  1. 由于无线模块会不断输出其他非规则的干扰脉冲,我们需要在中断中快速的处理,降低CPU的负荷。
  2. 根据ev1527的编码特征,我们可以知道无论是同步码还是数据1和数据0,必定是一个高电平后接一个低电平脉冲, 所以高电平结束我们只记录脉宽不做解码,解码在低电平结束后进行。3.
  3. 快速解码的处理方法:先寻找同步脉冲,只有同步脉冲出现后才继续解码后面的有效数据,否则都是干扰数据。
  4. 有同步脉冲后,我们只需要判定低电平脉冲的宽度,然后结合前一个高电平脉冲的宽度就能确定是数据位1还是0.
  5. 要考虑干扰和脉冲丢失的情况,如果出现这种情况,就复位相关变量,丢弃当前帧。等待下一帧数据再次解码。
  6. 因为EV1527编码并不带有任何数据校验位,为了保证数据的可靠性,我们通常会连续接收两帧数据,确认数据相同,才认为是一个有效的数据。
  7. 解码完成一帧数据后,可以根据各自的应用不同做后续处理。
    原创文章,欢迎转载,请注明来源,未经书面允许,请勿用于商业用途。
    关注微信公众号:嵌入式开发实战营,了解更多。某宝搜索<新龙电子>或者<新龙微科技>了解相关产品应用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值