433M遥控器无线解码1527协议,定时器轮询法
1527协议,最前面是引导码,紧接着前20位为地址码,每个遥控器不一样,后4位是按键码,每个遥控器都是一样的,
逻辑分析仪捕捉图形如下图:
分别按下遥控器的四个按键结果如下图:
#define GPIO_IRQ 0//测试gpio硬件中断
#define GPIO_LUOFEN 0//测试逻辑分析
#define LED GPIO_PB4//B4 需要关闭打印口
#define KEY GPIO_PA0
extern unsigned char RxFlag;//接收状态标记
extern unsigned int RxBuf[4+1];//多开一个
void timer_irq_handler(void);
void ev1527_init(void);
void ev1527decode(void);
void ev1527_task(void);
//----------------------------------
typedef enum{
OFF,
ON,
BLINK,
}LED_TypeDef;
typedef enum{
NO_KEY,
KEY1_PRESS, /* 按下 */
KEY1_SHORT_RELEASE, /* 按下立马释放 */
KEY1_LONG_PRESS, /* 长按 */
KEY1_LONG_RELEASE, /* 长按后释放 */
KEY2_PRESS, /* 按下 */
KEY2_SHORT_RELEASE, /* 按下立马释放 */
KEY2_LONG_PRESS, /* 长按 */
KEY2_LONG_RELEASE, /* 长按后释放 */
}KEY_TypeDef;
#define KEY1 GPIO_PB7//S1 配对按键
#define KEY2 GPIO_PB6//S2 up stop down stop
#define LED1 GPIO_PB5//LED指示灯
#define MOTORUP GPIO_PD3//上升
#define MOTORDOWN GPIO_PD6//下降
#define LED1ON() gpio_write(LED1, 0)
#define LED1OFF() gpio_write(LED1, 1)
#define MOTORUPON() gpio_write(MOTORUP, 1)
#define MOTORUPOFF() gpio_write(MOTORUP, 0)
#define MOTORDOWNON() gpio_write(MOTORDOWN, 1)
#define MOTORDOWNOFF() gpio_write(MOTORDOWN, 0)
extern LED_TypeDef LedFlag;
extern unsigned char learning_flag;
void motor_set(unsigned char a);
void led_task(void);
void motor_auto_stop(void);
void led_auto_off(void);
void led_auto_off1(void);
void user_led_key_init(void);
unsigned char key_scan(void);
void key_task(void);
void led_task(void);
void learning_key(void);
void ble_task(void);
#define NUMBER_COUNT 1 //1判断1次 2判断2次 3 判断3次
static Timer LedTimeHandle;//led闪烁定时器句柄
#define LED_OFF_TIME (10*1000)//ms
static Timer LedOffTimeHandle;//led自动关闭定时器句柄
#define MOTOR_OFF_TIME (2*60*1000)//ms 4分钟
static Timer MotorOffTimeHandle;//电机自动关闭句柄
#define MOTOR_ON_TIME (600)//ms 600豪秒
static Timer MotorOnTimeHandle;//电机延迟启动句柄
#if (NUMBER_COUNT == 1)
#define K433_OFF_TIME (110)
#endif
#if (NUMBER_COUNT == 2)
#define K433_OFF_TIME (140)
#endif
#if (NUMBER_COUNT == 3)
#define K433_OFF_TIME (170)
#endif
static Timer K433TimeHandle;//433超时关闭
unsigned char learning_flag = 0;//学习遥控器flag,1开始学习,0学习结束
LED_TypeDef LedFlag = ON;//led状态
void timer_irq_handler(void)//放irq_handler();里面
{
// static unsigned char a = 0;
static unsigned char msindex = 0;
#if GPIO_IRQ
if((reg_irq_src & FLD_IRQ_GPIO_EN)==FLD_IRQ_GPIO_EN){
reg_irq_src |= FLD_IRQ_GPIO_EN; // clear the relevant irq
gpio_irqsrc = (reg_gpio_irq_from_pad & KEY);
DBG("KEY = %d\n", gpio_irqsrc);
gpio_irq_cnt++;
}
#endif
if(timer_get_interrupt_status(FLD_TMR_STA_TMR0))
{
timer_clear_interrupt_status(FLD_TMR_STA_TMR0); //clear irq status
#if !GPIO_LUOFEN
ev1527decode();
#endif
#if GPIO_LUOFEN
static int gpio_irq_cnt = 0;
if(gpio_irq_cnt++ % 2) gpio_write(LED, 0);
else gpio_write(LED, 1);
#endif
}
if(msindex++ >= 20)
{
msindex = 0;
software_timer_ticks();
}
}
void ev1527_init(void)
{
#if GPIO_IRQ
gpio_set_func(LED ,AS_GPIO);
gpio_set_output_en(LED, 1); //enable output
gpio_set_input_en(LED ,0); //disable input
gpio_write(LED, 0);
gpio_set_func(KEY ,AS_GPIO);
gpio_set_output_en(KEY, 0); // disable output
gpio_set_input_en(KEY ,1); // enable input
gpio_setup_up_down_resistor(KEY, PM_PIN_PULLUP_10K);
/****GPIO_IRQ POL_FALLING Press SW2 to connect KEY1 and KEY3 to trigger an interrupt. **/
/* POL_FALLING(下降沿) POL_FALLING(上升沿) */
gpio_set_interrupt(KEY, POL_FALLING); //When SW2 is pressed, the falling edge triggers the interrupt.
irq_enable();
#endif
gpio_set_func(KEY ,AS_GPIO);
gpio_set_output_en(KEY, 0); // disable output
gpio_set_input_en(KEY ,1); // enable input
gpio_setup_up_down_resistor(KEY, PM_PIN_PULLUP_10K);
#if GPIO_LUOFEN
gpio_set_func(LED ,AS_GPIO);
gpio_set_output_en(LED, 1); //enable output
gpio_set_input_en(LED ,0); //disable input
gpio_write(LED, 0);
#endif
timer0_set_mode(TIMER_MODE_SYSCLK, 0, 50 * CLOCK_SYS_CLOCK_1US);// set timer 50us
timer_start(TIMER0);
irq_enable();
//timer_stop(TIMER0);
}
//-------------------------------------------------------------------
unsigned char RxFlag = 0;//接收状态标记
unsigned int RxBuf[4+1];//多开一个,只有前3个有效,第4个有时候只有半截数据
static int t_high=0,t_low=0,gpio_sta=0,getdata=0;
//static int rx_index=0;
static unsigned int rxlong=0;
#define TIMEOUT 70//超时时间
void k433_clear(void)//超时清楚
{
software_timer_stop(&K433TimeHandle);
getdata = 0;
DBG("getdata = 0\n");
}
//解码函数
// 50us 对应4k,容差1K,,,
//其他速率请 按比例调整定时器时间 比如8k对应20us,2k对应100us等,40k对应5us,速率高请保证单片机速率够快,
//getdata==1时候才是真正的数据接收到,其他非0都是中间状态
//当getdata==1就能提取数据了,取出完毕应当尽快的清零,否则会阻塞住
void ev1527decode(void)
{
if(gpio_sta ==0)
{
if(gpio_read(KEY)==1) // 如果高就一直循环
{
t_high++; //高时间计时
if(t_high > TIMEOUT * 7) //超时处理
{
t_high = TIMEOUT*7; // 即使超时也不退出但是不再增加,防止溢出
}
}
else
{
gpio_sta = 1;
t_low=0;
}
}
if(gpio_sta == 1)
{
if(gpio_read(KEY)==0) //低计时
{
t_low++;
// if(t_low > 150) DBG("t_low:%d\n", t_low);
if(t_low >= TIMEOUT)//50*150 = 7500
{
if(t_low == TIMEOUT && RxFlag == 0)//开始信号触发,但是要等处理结束才收
{
//tl_printf(">%d\n", getdata);
switch(getdata)//接收到的状态处理,1527如果接受到24个bit后,
{
#if (NUMBER_COUNT == 1)
case 0://第1波开始信号触发
getdata++;
memset(RxBuf, 0, sizeof(RxBuf));//接收前先清除一下
// software_timer_init(&K433TimeHandle, k433_clear, K433_OFF_TIME, 0);
// software_timer_start(&K433TimeHandle);//超时处理
break;
case 1://第2 3 4波开始信号触发,保存1 2 3波数据
RxBuf[getdata - 1] = (rxlong >> 1) & 0x00FFFFFF;
rxlong = 0;//clear
getdata++;
break;
case 2://结束
RxFlag = 1;
getdata = 0;
break;
default:break;
#endif
#if (NUMBER_COUNT == 2)
case 0://第1波开始信号触发
getdata++;
memset(RxBuf, 0, sizeof(RxBuf));//接收前先清除一下
software_timer_init(&K433TimeHandle, k433_clear, K433_OFF_TIME, 0);
software_timer_start(&K433TimeHandle);//超时处理
break;
case 1://第2 3 4波开始信号触发,保存1 2 3波数据
case 2:
RxBuf[getdata - 1] = (rxlong >> 1) & 0x00FFFFFF;
rxlong = 0;//clear
getdata++;
break;
case 3://结束
RxFlag = 1;
getdata = 0;
break;
default:break;
#endif
#if (NUMBER_COUNT == 3)
case 0://第1波开始信号触发
getdata++;
memset(RxBuf, 0, sizeof(RxBuf));//接收前先清除一下
software_timer_init(&K433TimeHandle, k433_clear, K433_OFF_TIME, 0);
software_timer_start(&K433TimeHandle);//超时处理
break;
case 1://第2 3 4波开始信号触发,保存1 2 3波数据
case 2:
case 3:
RxBuf[getdata - 1] = (rxlong >> 1) & 0x00FFFFFF;
rxlong = 0;//clear
getdata++;
break;
case 4://结束
RxFlag = 1;
getdata = 0;
break;
default:break;
#endif
}
}
if(t_low > TIMEOUT * 6 || t_high > TIMEOUT * 6)//超时处理,防止溢出,//70*6 *50 = 21ms
{
getdata = 0;
t_low = TIMEOUT+1;
}
}
}
else
{
gpio_sta = 2;
}
}
if(gpio_sta == 2)
{
if(t_low>TIMEOUT) //超时
t_low=0; //超时与时间不够是一样的处理,反正都是错误
if(t_high>TIMEOUT) //同上
t_high=0;
if(getdata > 0)//确定数据tick在范围内
{
if(t_high > t_low) //高电平时间大于低电平时间
{
//DBG("l\n");
rxlong |=0x000001;
}
else
{
//DBG("0\n");
rxlong &=0xfffffe;
}
rxlong<<=1;
}
gpio_sta = 0;
t_high=0;
t_low=0;
}
}
static unsigned lock_button = 0;//锁键的flag,按一下上下没有反应,按停止解锁,或者再次按这个按键解锁
static unsigned lock_button1 = 0;
//放while(1)循环处理
void ev1527_task(void)
{
unsigned int add = 0;//地值
unsigned char data = 0;//码值
if(RxFlag == 1)
{
RxFlag = 0;
#if (NUMBER_COUNT == 1)
if(1)// 确认第一次 第二次按键的值一样
{
add = RxBuf[0] >> 4;
data = RxBuf[0] & 0x0F;
#endif
#if (NUMBER_COUNT == 2)
if(RxBuf[0] == RxBuf[1])// 确认第一次 第二次按键的值一样
{
add = RxBuf[0] >> 4;
data = RxBuf[0] & 0x0F;
#endif
#if (NUMBER_COUNT == 3)
//if(RxBuf[0] == RxBuf[1])// 确认第一次 第二次按键的值一样
if(RxBuf[0] == RxBuf[1] || RxBuf[1] == RxBuf[2] || RxBuf[2] == RxBuf[0])//三次有两次是一样的
{
if(RxBuf[0] == RxBuf[1]){
add = RxBuf[0] >> 4;
data = RxBuf[0] & 0x0F;
}else if(RxBuf[1] == RxBuf[2]){
add = RxBuf[1] >> 4;
data = RxBuf[1] & 0x0F;
}else{
add = RxBuf[2] >> 4;
data = RxBuf[2] & 0x0F;
}
#endif
if(learning_flag == 1)//开始学习遥控器按键
{
//任何按键都进行学习
//if(data == 0x02)//按下遥控器的学习按键,才进行学习
learning_tasks(add);
return;
}
for(int i = 0; i < REMOTE_LEN; i++)//判断遥控器是否已经录制
{
if(REMOTE_BUFF[i] == add)//匹配成功
{
switch (data) {
case 0x08://up
if(lock_button) break;
motor_set(0);
break;
case 0x01://down
if(lock_button) break;
motor_set(2);
break;
case 0x04://stop
lock_button = 0;
motor_set(1);
break;
case 0x02://锁键,按一下上下没有反应,按停止解锁
//learning_key();
software_timer_init(&LedOffTimeHandle, led_auto_off1, 300, 300);
software_timer_start(&LedOffTimeHandle);
lock_button = 1;
lock_button1 = 1;
break;
default:
break;
}
}
}
}
#if 0
DBG("=1527_RX_OK=\n");
DBG("%04x\n", RxBuf[0]);
DBG("%04x\n", RxBuf[1]);
DBG("%04x\n", RxBuf[2]);
// DBG("%04x\n", RxBuf[3]);
// DBG("%04x\n", RxBuf[4]);
log_bin(RxBuf[0]);
log_bin(RxBuf[1]);
log_bin(RxBuf[2]);
// log_bin(RxBuf[3]);
// log_bin(RxBuf[4]);
DBG("%04x, %01x\n", add, data);
#endif
DBG("%04x, %01x\n", add, data);
memset(RxBuf, 0, sizeof(RxBuf));
}
}
//学习按键
void learning_key(void)
{
// software_timer_init(&LedOffTimeHandle, led_auto_off, LED_OFF_TIME, 0);//LED自动关闭10秒
// software_timer_start(&LedOffTimeHandle);
if(learning_flag == 0)
{
LedFlag = OFF;
learning_flag = 1;
}
else
{
LedFlag = ON;
learning_flag = 0;
}
}
static void motorup(void)
{
software_timer_stop(&MotorOnTimeHandle);
DBG("[AUTO]%s\n", __FUNCTION__);//log
LedFlag = BLINK;
MOTORUPON();
}
static void motordown(void)
{
software_timer_stop(&MotorOnTimeHandle);
DBG("[AUTO]%s\n", __FUNCTION__);//log
LedFlag = BLINK;
MOTORDOWNON();
}
static void motordelayset(unsigned char a)//1 up 2 down
{
switch (a) {
case 1:
software_timer_init(&MotorOnTimeHandle, motorup, MOTOR_ON_TIME, 0);//电机延迟启动1s
software_timer_start(&MotorOnTimeHandle);
break;
case 2:
software_timer_init(&MotorOnTimeHandle, motordown, MOTOR_ON_TIME, 0);//电机延迟启动1s
software_timer_start(&MotorOnTimeHandle);
break;
default:
break;
}
}
void motor_set(unsigned char a)// 0 up 1 stop 2 down 3 stop, 4 minute auto stop
{
if(a > 3) return;
software_timer_init(&MotorOffTimeHandle, motor_auto_stop, MOTOR_OFF_TIME, 0);//电机自动关闭4分钟
software_timer_start(&MotorOffTimeHandle);
static unsigned char lasta = 0;
if(Remote_inversion)//遥控反转功能
{
if(a == 0) a = 2;
else if(a == 2) a = 0;
}
if(a == lasta) return;
switch (a)
{
case 0:
DBG("MOTORUP\n");
LedFlag = ON;
MOTORDOWNOFF();
if(lasta == 2){//由下降到上升延迟1s,
motordelayset(1);
}else{
LedFlag = BLINK;
MOTORUPON();
}
break;
case 1:
DBG("MOTORSTOP\n");
LedFlag = ON;
software_timer_stop(&MotorOnTimeHandle);//停止定时器,防止定时器在等待上升
MOTORUPOFF();
MOTORDOWNOFF();
break;
case 2:
DBG("MOTORDOWN\n");
LedFlag = ON;
MOTORUPOFF();
if(lasta == 0){//由上升到下降延迟1s,
motordelayset(2);
}else{
LedFlag = BLINK;
MOTORDOWNON();
}
break;
case 3:
DBG("MOTORSTOP\n");
LedFlag = ON;
software_timer_stop(&MotorOnTimeHandle);//停止定时器,防止定时器在等待上升
MOTORUPOFF();
MOTORDOWNOFF();
break;
default:
break;
}
lasta = a;
}
void user_rest(void)//复位擦掉flash保存的信息
{
LedFlag = BLINK;
learning_flag = 0;
REMOTE_LEN = 0;
software_timer_init(&LedOffTimeHandle, led_auto_off, 2000, 0);//LED复位2秒
software_timer_start(&LedOffTimeHandle);
flash_erase_sector(FLASH_1527KEY_ADDR);
}
//--------------------------------------------------------------------------
void led_task(void)//200ms定时器
{
//DBG("%s\n", __FUNCTION__);//log
static unsigned char i = 0;
if(lock_button1 == 1)
return;
switch (LedFlag) {
case OFF:
LED1OFF();
break;
case ON:
LED1ON();
break;
case BLINK:
if(i++ % 2) LED1ON();
else LED1OFF();
break;
default:
break;
}
}
void motor_auto_stop(void)
{
software_timer_stop(&MotorOffTimeHandle);
DBG("[AUTO]%s\n", __FUNCTION__);//log
LedFlag = ON;
MOTORUPOFF();
MOTORDOWNOFF();
}
void led_auto_off(void)//默认led为打开状态 所以LedFlag = ON;
{
software_timer_stop(&LedOffTimeHandle);
DBG("[AUTO]%s\n", __FUNCTION__);//log
LedFlag = ON;
learning_flag = 0;
}
void led_auto_off1(void)//shanshuo
{
static unsigned char i = 0;
if(i++ >= 4)
{
i = 0;
lock_button1 = 0;//控制主线led
software_timer_stop(&LedOffTimeHandle);
}
DBG("[AUTO]%s\n", __FUNCTION__);//log
if(i % 2) LED1OFF();
else LED1ON();
}
void user_led_key_init(void)
{
//led
gpio_set_func(LED1, AS_GPIO);
gpio_set_output_en(LED1, 1); //enable output
gpio_set_input_en(LED1 ,0); //disable input
gpio_setup_up_down_resistor(LED1, PM_PIN_PULLUP_10K);
gpio_write(LED1, 1);//off led
//key
gpio_set_func(KEY1, AS_GPIO);
gpio_set_output_en(KEY1, 0); // disable output
gpio_set_input_en(KEY1, 1); // enable input
gpio_setup_up_down_resistor(KEY1, PM_PIN_PULLUP_10K);
gpio_set_func(KEY2, AS_GPIO);
gpio_set_output_en(KEY2, 0); // disable output
gpio_set_input_en(KEY2, 1); // enable input
gpio_setup_up_down_resistor(KEY2, PM_PIN_PULLUP_10K);
//motor
gpio_set_func(MOTORUP, AS_GPIO);
gpio_set_output_en(MOTORUP, 1); //enable output
gpio_set_input_en(MOTORUP, 0); //disable input
gpio_setup_up_down_resistor(MOTORUP, PM_PIN_PULLDOWN_100K);
gpio_write(MOTORUP, 0);//off motor
gpio_set_func(MOTORDOWN, AS_GPIO);
gpio_set_output_en(MOTORDOWN, 1); //enable output
gpio_set_input_en(MOTORDOWN, 0); //disable input
gpio_setup_up_down_resistor(MOTORDOWN, PM_PIN_PULLDOWN_100K);
gpio_write(MOTORDOWN, 0);//off motor
software_timer_init(&K433TimeHandle, k433_clear, K433_OFF_TIME, 0);//433延迟关闭,为了支持BQ3180
software_timer_init(&LedOffTimeHandle, led_auto_off, LED_OFF_TIME, 0);//LED自动关闭10秒
software_timer_init(&MotorOffTimeHandle, motor_auto_stop, MOTOR_OFF_TIME, 0);//电机自动关闭10秒
software_timer_init(&LedTimeHandle, led_task, 100, 100);
software_timer_start(&LedTimeHandle);
}
#define KEY_TIME_OUT 50//消抖时间,取决于while(1)的速度
KEY_TypeDef key_scan(void)
{
static KEY_TypeDef status = NO_KEY;
static unsigned int index = 0;
if(gpio_read(KEY1) == 0 || gpio_read(KEY2) == 0)
{
index++;
//DBG("index = %d\n", index);
if(index == KEY_TIME_OUT)//根据scanf_key执行频率设置具体数值
{
if(gpio_read(KEY1) == 0){
status = KEY1_PRESS;
return status;
}else if(gpio_read(KEY2) == 0){
status = KEY2_PRESS;
return status;
}
}
if(index == KEY_TIME_OUT * 150)// 150 大概等于 3s 根据scanf_key执行频率设置具体数值
{
if(gpio_read(KEY1) == 0){
status = KEY1_LONG_PRESS;
return status;
}else if(gpio_read(KEY2) == 0){
status = KEY2_LONG_PRESS;
return status;
}
}
}
else
{
switch (status) {
case KEY1_PRESS: status = KEY1_SHORT_RELEASE; return status; break;
case KEY2_PRESS: status = KEY2_SHORT_RELEASE; return status; break;
case KEY1_LONG_PRESS: status = KEY1_LONG_RELEASE; return status; break;
case KEY2_LONG_PRESS: status = KEY2_LONG_RELEASE; return status; break;
default: break;
}
index = 0;
status = NO_KEY;
}
return NO_KEY;
}
//放while(1)循环处理
void key_task(void)
{
static unsigned char key_index = 0;// up stop down stop
KEY_TypeDef key = key_scan();
if(key) DBG("key = %d, key_index = %d\n", key, key_index);
switch (key) {
case KEY1_SHORT_RELEASE://学习配对按键
learning_key();
break;
case KEY2_SHORT_RELEASE://电机控制按键
motor_set(key_index++);
key_index = key_index%4;//控制key_index范围 0-3
break;
case KEY1_LONG_PRESS: //清楚配对按键
user_rest();
break;
case KEY2_LONG_PRESS: //遥控器上下转向
Remote_inversion = !Remote_inversion;
user_flash_Remote_write(Remote_inversion);//保存到flash
LedFlag = BLINK;
software_timer_init(&LedOffTimeHandle, led_auto_off, 2000, 0);
software_timer_start(&LedOffTimeHandle);
DBG("Remote_inversion = %d\n", Remote_inversion);
break;
default:
break;
}
}
//---------------------------------------BLE-------------------------------
#if 1
char * LE_CMD[] = {//接收sj的命令
"AC00000001",//up
"AC00000002",//down
"AC00000003",//stop
"AP12345678",//
};
extern unsigned char LE_Rx_Len;
extern unsigned char LE_Rx_Buf[30];
//放while(1)循环处理
void ble_task(void)
{
if(LE_Rx_Len > 0)
{
DBG("BLERXLEN: %d BLERXDATA: %s\n", LE_Rx_Len, LE_Rx_Buf);
// DBG("BLERX:%01x\n", LE_Rx_Buf[0]);
// DBG("BLERX:%01x\n", LE_Rx_Buf[1]);
// DBG("BLERX:%01x\n", LE_Rx_Buf[2]);
// DBG("BLERX:%01x\n", LE_Rx_Buf[3]);
// DBG("BLERX:%01x\n", LE_Rx_Buf[4]);
for(int i = 0; i < sizeof(LE_CMD) / sizeof(LE_CMD[0]); i++)
{
if(memcmp(LE_Rx_Buf, LE_CMD[i], 10) == 0)
{
switch (i)
{
case 0: DBG("000\n"); motor_set(0); break;
case 1: DBG("111\n"); motor_set(2); break;
case 2: DBG("222\n"); motor_set(1); break;
case 3: DBG("444\n"); learning_key(); break;
default: break;
}
}
}
memset(LE_Rx_Buf, 0, LE_Rx_Len);
LE_Rx_Len = 0;
}
}
#else
extern unsigned char LE_Rx_Len;
extern unsigned char LE_Rx_Buf[30];
//放while(1)循环处理
void ble_task(void)
{
if(LE_Rx_Len > 0)
{
DBG("BLERXLEN: %d BLERXDATA: %s\n", LE_Rx_Len, LE_Rx_Buf);
if(LE_Rx_Buf[0] == 0xAC)//电机命令
{
switch (LE_Rx_Buf[4])
{
case 0x01: DBG("000\n"); motor_set(0); break;
case 0x02: DBG("111\n"); motor_set(2); break;
case 0x03: DBG("222\n"); motor_set(1); break;
default: break;
}
}
else if(LE_Rx_Buf[0] == 0xAF)//设置命令
{
switch (LE_Rx_Buf[4])
{
case 0x78:
DBG("rest\n");
learning_key();
break;
default: break;
}
}
memset(LE_Rx_Buf, 0, LE_Rx_Len);
LE_Rx_Len = 0;
}
}