链接:SYN480R模块解码EV1527教程.
单片机解码需要带自唤醒功能,看门狗或者定时器唤醒以实现低功耗。
#ifndef _DECODE_H_
#define _DECODE_H_
#include "..\Include\config.h"
#define rfRead P24 //数据口
#define RF_EN 1
#define RF315M_EN 0
#define RF433M_EN 1
#if RF_EN
#define INTREVAL 100 //定时器中断周期 INTREVAL(us)
#define RELEASE_CNT 100 //松手计数 大于同步头时间长度即可 100*100=10(ms)
#define ECOUNT 3 //按键有效计数
#define DELAY_SLEEP 4 //进入低功耗计数 延迟时间=DELAY_SLEEP*扫描周期(ms)
#define EV1527_ADDRESS 0xB6CF //EV1527 2字节地址码
//逻辑分析仪实际测量
#if RF315M_EN
#define _start_us_min (11500/INTREVAL) //12.5ms
#define _start_us_max (13500/INTREVAL)
#define _num0_us_min (1000/INTREVAL) //1.2ms
#define _num0_us_max (1400/INTREVAL)
#define _num1_us_min (100/INTREVAL) //0.48ms
#define _num1_us_max (800/INTREVAL)
#endif
#if RF433M_EN
#define _start_us_min (8000/INTREVAL) //8.8ms
#define _start_us_max (9500/INTREVAL)
#define _num0_us_min (500/INTREVAL) //0.83ms
#define _num0_us_max (1100/INTREVAL)
#define _num1_us_min (0/INTREVAL) //0.26ms
#define _num1_us_max (600/INTREVAL)
#endif
void soft_count(void);
void soft_decode(void);
void setStaticAddress(u8 writeAddh,u8 writeAddl);
u16 getStaticAddress (void);
u16 getRemoteAddress(void);
u8 acceptingData(void);
u8 getRemotekeyData(void);
u8 getRemotelongpressCnt(void);
bit getSyncFlag(void);
//extern u8 release_key_cnt; //松手计数
//extern u16 RF_Value_Cnt; //长按计数
extern bit IR_OVER; //接收完一帧数据
extern bit pair_flag;
extern u8 Address_h;
extern u8 Address_l;
#endif
#endif
#include "decode.h"
#if RF_EN
u8 release_key_cnt=0; //松手计数
u8 RF_Value_Cnt=0; //长按计数
u8 Temp_addrl=0,Temp_addrh=0,Address_l=0,Address_h=0;
u8 cntint=0,IR_Key=0;
u16 Low=0; //低电平计数
u32 RF_data=0; //24位数据码
bit start_flag=0; //解码开始标志
bit IR_OVER=0; //一组数据接收完成标志
bit Jump_flag=0; //电平跳变标志
bit pair_flag=0; //对码标志
u8 tranCnt=0;
//---------定时中断扫描函数-------------------
void soft_count()
{
if(tranCnt>0)
tranCnt--; //松手计数
if(rfRead==0)
{
Low++; //低电平累加计数
if(Jump_flag)Jump_flag=0;
}
else if(rfRead==1)
{
if(!Jump_flag)
{
Jump_flag=1;
soft_decode(); //上升沿进入解码程序。
Low=0;
}
}
}
void soft_decode()
{
if(!start_flag)
{
if(( Low > _start_us_min ) && ( Low < _start_us_max )) //同步码
{
start_flag=1;
cntint=0; //数据长度清零
IR_Key=0;
RF_data=0;
tranCnt=RELEASE_CNT;
//IR_OVER=0;
}
//---------松手计数 有缺陷 解码完成的下降沿和来临的第一个上升沿 时间为150ms---------
else
{
RF_Value_Cnt=0;
pair_flag=0; //对码标志位清零
if(++release_key_cnt>=10) //这里累加的是150ms的低电平的个数,并不是松手后的绝对时间 易受环境干扰
{
release_key_cnt=10;
}
}
}
else if((start_flag)&&(cntint<24))
{
//--------数据码0判断--------
if(( Low > _num0_us_min ) && ( Low < _num0_us_max ))
{
RF_data=RF_data<<1;
cntint++;
tranCnt=RELEASE_CNT;
}
//--------数据码1判断--------
else if(( Low > _num1_us_min ) && ( Low < _num1_us_max ))
{
RF_data=RF_data<<1;
RF_data|=1;
cntint++;
tranCnt=RELEASE_CNT;
}
//--------数据码判断错误--------
else
{
start_flag=0;
cntint=0;
}
}
else ;
//---------315解码完毕大概需要52ms-----------------
//---------433解码完毕大概需要37ms-----------------
if(cntint==24)
{
release_key_cnt=0;
RF_Value_Cnt++;
if(RF_Value_Cnt>100)RF_Value_Cnt=100;
cntint=0;
start_flag=0;
IR_Key=RF_data&0x0000000f; //按键码
Temp_addrl=(RF_data>>4)&0x000000ff; //低8位地址码
Temp_addrh=(RF_data>>12)&0x000000ff; //高8位地址码
//-----连续接收到3个正确的码才是有效的--------------
if(RF_Value_Cnt>=ECOUNT) pair_flag=1; //对码标志位
IR_OVER=1; //解码完成
}
}
//------设置静态遥控地址码------------
void setStaticAddress(u8 writeAddh,u8 writeAddl)
{
Address_h=writeAddh;
Address_l=writeAddl;
}
//------得到静态遥控地址码------------
u16 getStaticAddress (void)
{
u16 address=0;
address=(Address_h<<8)+Address_l;
return address;
}
//------得到临时遥控地址码------------
u16 getRemoteAddress(void)
{
u16 address=0;
address=(Temp_addrh<<8)+Temp_addrl;
return address;
}
//------返回按键键码---------------
u8 getRemotekeyData(void)
{
return IR_Key;
}
//------得到长按计数值--------------
u8 getRemotelongpressCnt(void)
{
return RF_Value_Cnt;
}
//------是否正在接受遥控数据--------
u8 acceptingData(void)
{
if(tranCnt==0)
return 1;
return 0;
}
bit getSyncFlag(void)
{
return start_flag;
}
/*
//-----------------------进入打嗝模式------------------------
void burp_mode(void)
{
static unchar sleep_cnt=DELAY_SLEEP;
if(-- sleep_cnt==0)
{
sleep_cnt=DELAY_SLEEP;
if((!getSyncFlag()))
{
pwr_timer0(); //开启定时唤醒功能
_clrwdt(); //喂狗
//red=1; //周期测试
_nop_();
_nop_();
STOP();
_nop_();
_nop_();
//red=0; //周期测试
timer0_close();
}
}
}
*/
#endif
#ifndef _TIMER_H_
#define _TIMER_H_
#include "..\Include\config.h"
#define timer0_EN 0
#define T0EXT_LOSC_SET 0x80 //flosc
#define T0RATE_128 0x00
#define T0RATE_64 0x10
#define T0RATE_32 0x20
#define T0RATE_16 0x30
#define T0RATE_8 0x40
#define T0RATE_4 0x50
#define T0RATE_2 0x60
#define T0RATE_1 0x70
#define T1RATE_128 0x00
#define T1RATE_64 0x10
#define T1RATE_32 0x20
#define T1RATE_16 0x30
#define T1RATE_8 0x40
#define T1RATE_4 0x50
#define T1RATE_2 0x60
#define T1RATE_1 0x70
//遥控器按下连续发4个数据包 要保证至少接收到一个则 3*52=156ms
//遥控器按下连续发4个数据包 要保证至少接收到一个则 3*37=111ms
/****
16K/64=0.25K
125/0.25=500ms
*/
#define WAKE_T0RATE_SET T0RATE_64
#define WAKE_TIMER_CNT (256-50)
void pwr_timer0(void);
void timer0_close(void);
void time1_init(void);
u16 getSYSTimer(void);
#if timer0_EN
void init_timer0(void);
#endif
#endif
#include "timer.h"
unint SYS_TIMER=0; //时基
//-----------切换到低速时钟,进入定时唤醒模式----------------
void pwr_timer0(void)
{
TMOD |= 0x06; // Mode 2 of Timer 1 as a 8-bit auto-reload Timer
TH0 = WAKE_TIMER_CNT; //200MS;
TL0 = WAKE_TIMER_CNT; //200MS;
TCON0 &= 0x0f; // T1RATE is Fosc/128
TCON0 |= (T0EXT_LOSC_SET|WAKE_T0RATE_SET); // 16K
ET0 = 1; // Timer 0 isr disable
TR0 = 1; // enable Timer 0 Run control
SYSMOD |= 0X01; //STOP模式下低速时钟运行
}
void timer0_close(void)
{
SYSMOD &= 0xfe;
ET0=0;
TR0=0;
}
//-----------切换到高速时钟,普通模式用---------------
#if timer0_EN
void init_timer0(void)
{
TMOD |= 0x06; // Mode 2 of Timer 0 as a 8-bit auto-reload Timer
TH0 = (256-125); //500uS;
TL0 = (256-125); //500uS;
TCON0 &= 0x0f; // 切换到高速时钟
TCON0 |= T0RATE_64; // T0RATE is Fosc/64
ET0 = 1; // Timer 0 isr disable
TR0 = 1; // enable Timer 0 Run control
}
#endif
/***************************************************************
time1 1ms定时
****************************************************************/
void time1_init(void)
{
TMOD |= 0x60; // T1 8位自动装载
#if RF_EN
TH1 = (256-25); // Initial values
TL1 = (256-25);
#else
TH1 = (256-250); // Initial values
TL1 = (256-250);
#endif
TCON0 &=0xf0; // fosc/128=32M/128=250K (256-6)/250K=0.001s=1ms
TCON0 |= T1RATE_128;
ET1 = 1; // Timer 1 isr enable
TR1 = 1; // enable Timer 1 Run control
}
u16 getSYSTimer(void)
{
return SYS_TIMER;
}
void Timer1_ISR (void) interrupt ISRTimer1 // Vector @ 0x1B
{
#if RF_EN
static unchar isr_cnt=10;
soft_count();
//定时溢出标志自动清零。
if(--isr_cnt==0)
{
isr_cnt=10;
SYS_TIMER++;
//red=!red; //周期测试
}
#else
SYS_TIMER++;
#endif
}
void decodeKey_handle(void)
{
//同一个按键不能同时实现按下触发和长按的功能
u8 IR_key=0;
u8 IR_addh=0;
u8 IR_addl=0;
static u8 key_lock=0;
IR_key=getRemotekeyData(); //得到按键码
IR_addh=(u8)(getRemoteAddress()>>8); //得到地址码
IR_addl=(u8)getRemoteAddress();
//-------------松手后10ms使能短按按键处理,否则锁死--------------
if(key_lock)
{
if(acceptingData())
key_lock=0;
}
//--------------对码并写入flash 超过5S则重新对码---------
if(pair_start) //按键按下,则pair_start置位,开始对码
{
green=1; //指示灯
if(getSYSTimer()-PAIR_TIMER>=5000) //5S没有对码则结束对码
{
pair_start=0;
green=0;
pair_flag=0;
}
if(pair_flag)
{
pair_flag=0;
green=0;
pair_start=0;
//-----------把遥控器的地址码保存到flash中-------------------
ROMByteWrite(ROMADDRH,&IR_addh);
_nop_();_nop_();
ROMByteWrite(ROMADDRL,&IR_addl);
_nop_();_nop_();
setStaticAddress(IR_addh,IR_addl); //设置静态地址
key_lock=1; //按键自锁
}
}
//if((IR_addh==(u8)(getStaticAddress()>>8)) && (IR_addl==(u8)getStaticAddress))
if(IR_OVER)
{
IR_OVER=0;
if((IR_addh==(u8)(getStaticAddress()>>8)) && (IR_addl==(u8)getStaticAddress()))
//if((IR_addh==0xb6) && (IR_addl==0xcf))
{
//------------------短按按键处理---------------------
if(!key_lock)
{
switch(IR_key)
{
case 0x04:led=!led;key_lock=1;break;
default:break;
}
}
}
}
}