一、1527的数据帧结构
无线遥控的编码,从编码类型上来说,分为2类,一类是固定码,也就是编码芯片的地址是不变的,芯片型号以 EV1527、PT2262 为代表。另一种是滚动码,芯片的地址码是变化的,芯片以HS300、HS301为代表。

1 EV1527 数据帧结构
EV1527 是一片由 CMOS 设计制造的可预烧内码的学习码编码IC ,由软件解码;内码共有 20 个位元可预烧 1048576 组内码组合,降低使用上编码重复的机率。
EV1527 每帧数据由 24 个数据位组成,前 20 位为地址码,对于一个芯片来说,地址位的内容是固定的,是出厂前就预制好的,并且理论上每个芯片的地址码是唯一的。后面 4 位为按键码,对应芯片上的K0-K3 4 根数据线,数据线的状态不同,按键码就不同。
在数据位之前,还有一个同步脉冲,也就是每帧数据都是从同步
脉冲开始的。数据位的“1”和“0”是由高低电平宽度(脉冲宽度)的比例决定的。如果高电平宽度为低电平宽度的 3 倍,就表示逻辑“1”,反过来如果低电平为高电平宽度的 3 倍,就表示逻辑“0”。同步脉冲高电平和低电平的比例固定为 4:124.



二、中断方式的解码
把串行输入的编码数据帧,还原成编码之前的状态,读取其中
的地址码和按键码,称之为解码。
数据帧都是由同步头开始,然后是 24位的数据码,并且此数据帧在遥控器按键的过程中是重复出现的,我们首先要判断同步码,判断出了同步码,就知道数据码是从那一位开始了。对于一款量产的无线遥控器来说,他的编码芯片匹配的电阻是一个固定值,也就是说它发射的数据帧的脉冲宽度是不变的,所以我们可以通过测量高低脉冲宽度的方式来分辨同步码、逻辑“1”、逻辑“0”。
具体的方法是这样的,首先启用定时器,装入一个初值,打开
定时器中断,让其以固定的间隔进入中断程序。在中断程序中,我们查询数据输入管脚的状态,如果为高电平,就在高电平状态累加计数,反之就在低电平状态计数,当电平发生上升沿变化的时候,判断接收到的高低电平宽度的值是否符合同步信号的要求,如果符合就进入数据位的接收,以同样的方式判断逻辑“1”或逻辑“0”。如果接受过程中出现不符合要求的电平状态,就退出接收,为了增加可靠性,我们一般要求规定时间内,成功接收到完全相同的 2 帧数据才算有效。
接收完成后,24 个数据位被放入 3 个字节中。下一步我们要对接收到的数据进行处理,判断编码的类型,分离地址码和按键码。

三、程序代码

/*main.c*/#include "stm32f10x.h"
#include "uart.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"uint8_t rf_data[4];
extern uint8_t decode_ok;    //解码成功标志位
extern uint8_t RF;int main(void)
{   LED_Init();Uart_Init();delay_init();   //延时初始化一定要加上!!!!!!EV1527_GPIO_Init();TIM6_NVIC_Init();TIM6_Mode_Init();while(1){if(decode_ok == 1)   //解码成功{switch(rf_data[2]){case 0xf8:   //解码为0xf8,点亮LED{LED1 = LED_ON;LED2 = LED_ON;LED3 = LED_ON;break;}case 0xf2:   //解码为0xf2,熄灭LED{LED1 = LED_OFF;LED2 = LED_OFF;LED3 = LED_OFF;break;}}}
/***调试用代码,查看接收到的编码***/
//      printf("\r\n EV1527 \r\n");
//      delay_ms(500);
//      printf("i get %x  ",rf_data[0]);
//      delay_ms(500);
//      printf("i get %x  ",rf_data[1]);
//      delay_ms(500);
//      printf("i get %x  ",rf_data[2]);
//      delay_ms(500);
//      printf("i get %x  ",rf_data[3]);
//      delay_ms(500);}
}
/************** END OF FILE *****************//*Timer.c*/#include "stm32f10x.h"                  // Device header#include "timer.h"
#include "led.h"
#include "uart.h"
#include "delay.h"void EV1527_GPIO_Init() //EV1527 IO口初始化
{GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // PB9 输入端GPIO_InitStruct.GPIO_Pin     = GPIO_Pin_9; GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);
}//中断函数使用定时器6void TIM6_NVIC_Init()   //中断分组初始化
{
NVIC_InitTypeDef NVIC_InitStructure;    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
//TIM6中断
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
//先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
//从优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//IRQ通道被使能
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
NVIC_Init(&NVIC_InitStructure);
}void TIM6_Mode_Init()
{    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//使能TIM6时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);    //初始化定时器6//设定计数器自动重装值     TIM_TimeBaseStructure.TIM_Period = 100; //时钟预分频系数 驱动计数器的时钟 CK_CNT=CK_INT/(71+1) = 1M//计数器计数1次时间等于1/CK_CNT = 1usTIM_TimeBaseStructure.TIM_Prescaler =71; //设置时钟分割:TDTS = Tck_tim                                                                                   TIM_TimeBaseStructure.TIM_ClockDivision =        TIM_CKD_DIV1; //TIM向上计数模式TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //根据指定的参数初始化TIMx的时间基数单位TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); //允许更新中断 TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);TIM_ClearFlag(TIM6,TIM_FLAG_Update);//使能定时器6TIM_Cmd(TIM6,ENABLE );
}uint8_t RF;
uint8_t decode_ok;            //解码成功
uint8_t  hh_w,ll_w;           //高,低电平宽度
uint8_t  ma_x;                //接收到第几位编码了
uint8_t  bma1,bma2,bma3,bma4; //用于接收过程存放遥控编码,编码比较两次,这是第一次
uint8_t  mma1,mma2,mma3,mma4;
uint8_t mmb1,mmb2,mmb3,mmb4; // 用于接收过程存放遥控编码,第二次
//extern uint8_t mmb1,mmb2,mmb3,mmb4;uint8_t rf_ok1,rf_ok2,rf_ok;         //解码过程中的临时接收成功标志,接收到一个完整的遥控命令后置1,通知解码程序可以解码了
uint8_t old_rc5;             //保存上一次查询到的电平状态
uint8_t tb_ok;               //接收到同步的马时置1
uint8_t D0,D1,D2,D3 ;
uint16_t s ,s1;
uint8_t bt_auto;     //自动设置遥控接收波特率标志
extern uint8_t rf_data[4];  void TIM6_IRQHandler()
{if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET){TIM_ClearITPendingBit(TIM6, TIM_IT_Update); //接收数据的电平 PB9RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9); if (!RF) { ll_w++;   // 检测到低电平 低电平时间加1,记录本 // 次电平状态old_rc5old_rc5=0; }               else         // 检测到高电平{ hh_w++;if (!old_rc5)  // 检测到从低到高的跳变,已检测// 到一个完整(高-低)电平周期{   //判同步码    2/5 100/130if (((hh_w>=2)&&(hh_w<=5))&&((ll_w>=100)&&(ll_w<=130))) { tb_ok = 1 ;ma_x = 0;bma1=0; bma2=0; bma3=0; bma4=0;    }else if ((tb_ok)&&((ll_w>=8)&&(ll_w<=13))) //8/13{   ma_x++; //已经接收到同步码,判0if(ma_x>23){if(!rf_ok1) //rf_ok1临时接收成功{   //将接收到的编码复制到解码寄存器中 mma1=bma1;mma2=bma2;mma3=bma3;mma4=bma4; // 通知解码子程序可以解码了                                                        rf_ok1=1;                    tb_ok=0;s=1000;                             }else{//将接收到的编码复制到解码寄存器中  mmb1=bma1;mmb2=bma2;mmb3=bma3;mmb4=bma4;  // 通知解码子程序可以解码了                                             rf_ok2=1;                     tb_ok=0;                                                                        }}}  else if ((tb_ok)&&((ll_w>=2)&&(ll_w<=7)))   // 2/7{ switch (ma_x){ case 0 : { bma1=bma1 | 0x80; break; }   //遥控编码第1位case 1 : { bma1=bma1 | 0x40;  break; }case 2 : { bma1=bma1 | 0x20; break; }case 3 : { bma1=bma1 | 0x10; break; }case 4 : { bma1=bma1 | 0x08; break; }case 5 : { bma1=bma1 | 0x04; break; }case 6 : { bma1=bma1 | 0x02; break; }case 7 : { bma1=bma1 | 0x01; break; }case 8 : { bma2=bma2 | 0x80; break; }case 9 : { bma2=bma2 | 0x40; break; }case 10: { bma2=bma2 | 0x20; break; }case 11: { bma2=bma2 | 0x10; break; }case 12: { bma2=bma2 | 0x08; break; }case 13: { bma2=bma2 | 0x04; break; }case 14: { bma2=bma2 | 0x02; break; }case 15: { bma2=bma2 | 0x01; break; }case 16: { bma3=bma3 | 0x80; break; }case 17: { bma3=bma3 | 0x40; break; }case 18: { bma3=bma3 | 0x20; break; }case 19: { bma3=bma3 | 0x10; break; }case 20: { bma3=bma3 | 0x08; break; }// 按键状态第1位case 21: { bma3=bma3 | 0x04; break; }case 22: { bma3=bma3 | 0x02; break; }case 23: { bma3=bma3 | 0x01;              if(!rf_ok1){mma1=bma1;mma2=bma2;mma3=bma3;// mma4=bma4;                                           // 将接收到的编码复制到解码寄存器中                             rf_ok1=1;         // 通知解码子程序可以解码了tb_ok=0;
//                                   bt_auto=0;s=1000;break;                                 }else{mmb1=bma1;mmb2=bma2;mmb3=bma3;//mmb4=bma4;               // 将再次接收到的编码复制到解码寄存器中,                             rf_ok2=1;                                      // 通知解码子程序可以解码了tb_ok=0;break;                                                                          }                                    }} ma_x++; }else{ma_x=0; tb_ok=0;bt_auto=0;bma1=0;bma2=0; bma3=0; hh_w=1;ll_w=0;}                                      //接收到不符合的高-低电平序列ll_w=0;hh_w=1; }          old_rc5=1;      // 记录本次电平状态}if(rf_ok1)  //规定时间内接受到2帧相同的编码数据才有效{s--;if(!s) rf_ok1=0;if(rf_ok2) {if((mma1==mmb1)&&(mma2==mmb2)&&(mma3==mmb3)){rf_ok=1;rf_ok1=0;rf_ok2=0;                    }else{rf_ok=0;rf_ok1=0;rf_ok2=0;}          }                   }if((rf_ok))      //判断是否接收成功{   TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE);rf_ok=0; rf_data[0]=mma1;rf_data[1]=mma2;rf_data[2]=mma3;decode_ok=1;TIM_ITConfig(TIM6  , TIM_IT_Update, ENABLE);}}
}

基于STM32和EV1527的无线接收解码程序相关推荐

  1. 基于STM32和hs1527、ev1527、rt1527、fp1527的无线接收解码程序

    1527的数据帧结构 无线遥控的编码,从编码类型上来说,分为2类,一类是固定码,也就是编码芯片的地址是不变的,芯片型号以 hs1527.ev1527.rt1527.fp1527.PT2262 为代表. ...

  2. STM32下315M模块的无线接收解码程序

    最近项目需要增加一个控制机器运行的紧急遥控,参考了一个大神的博客,然后我们选择了这样的遥控器和一个315M模块,实现遥控器的按键控制. 附上遥控器链接和315M 模块链接淘宝. 首先介绍一下315M模 ...

  3. stm32串口接收不定长数据_基于STM32之UART串口通信协议--接收

    一.前言 1.简介 回顾上一篇UART发送当中,已经讲解了如何实现UART的发送操作了,接下来这一篇将会继续讲解如何实现UART的接收操作. 2.UART简介 嵌入式开发中,UART串口通信协议是我们 ...

  4. STM32单片机(12) 红外信号接收解码(外部中断)

    [转载请注明出处:http://blog.csdn.net/leytton/article/details/38687537] 本程序主要利用外部中断,实现红外遥控器信号接收解码,并利用串口通信把编码 ...

  5. 基于STM32单片机的密码锁(Proteus仿真+程序+报告)

    3-基于STM32单片机的密码锁 功能描述如下: 由STM32F103单片机最小系统+ 4*4矩阵键盘+LCD1602液晶显示+蜂鸣器+继电器模块: 1.采用STM32F103为主控芯片. 2.通过4 ...

  6. 基于STM32单片机的电子钟(Proteus仿真+程序)

    编号:12 基于STM32单片机的电子钟 功能描述: 本设计由STM32单片机+液晶1602+按键+RTC时钟组成. 1.采用STM32F103最小系统板. 2.利用STM32内部自带RTC时钟提供时 ...

  7. MTK平台基于EV1527的无线接收和发射程序

    EV1527 功能描述 1:每一帧码有 25 位,同步位(syn)的高低电平宽度为 t:31t(先高后低),其余每一位码的码形有两种,称为"0"码和"1"码:& ...

  8. 基于stm32与NRF24L01的无线门禁系统

    首先,需要说明梁只是一个小本科生,水平不高,许多错误请大家指教(qq1257681989).所写的内容是我自己做的,写此博客仅在于让自己在完成之后有个回顾和总结. 进入正文,这个小制作是我选择的一个比 ...

  9. 基于STM32的电压采集(电压表)系统设计(程序)

    博主福利:100G+电子设计学习资源包! http://mp.weixin.qq.com/mp/homepage?__biz=MzU3OTczMzk5Mg==&hid=7&sn=ad5 ...

最新文章

  1. R语言将dataframe数据从宽表(wide)变为长表(long)实战:tidyr包的gather函数、cdata包的unpivot_to_blocks函数、data.table使用melt函数
  2. HTTP与服务器的四种交互方式
  3. 自动化运维——一键安装MySQL
  4. Android的自定义键盘颜色,android自定义键盘(解决弹出提示的字体颜色问题)
  5. docker修改容器名字
  6. 每个女孩子起床后做的第一件事......
  7. 【汇编语言】清华大学学堂在线《汇编语言程序设计》课程学习笔记
  8. opencv获取图片像素坐标_利用OpenCV从图片中提取矩形并标注坐标(室内平面地图)(一)
  9. Pytorch nn.DataParallel()的简单用法
  10. 常用的CSS Hack技术集锦
  11. pycharm 中Python 模板的自动生成
  12. php 松散耦合,PHP依赖注入和松散耦合
  13. 通力法评 | 《证券基金经营机构信息技术管理办法》解读
  14. SPSS学习 (一)概述
  15. 百度搜索关键词自动提交
  16. Python爬虫学习(六)selenium自动化测试登陆百度账号_滑动验证码问题
  17. 分布式理论(五)—— 一致性算法 Paxos
  18. 向日葵远程控制引起惠普战笔记本亮度无法调节问题
  19. @Transactional注解回滚(事物)
  20. 学生护眼台灯哪个牌子最好?高品质的护眼灯推荐

热门文章

  1. 一文看懂Java设计模式
  2. 7.16日 别问了稳定跑就完事~ ksjsb可用版 (日均10w)
  3. 读书札记:knowledge and Virtue
  4. BZOJ 1226 [SDOI2009] 学校食堂Dining
  5. TPM 2.0规范系列解读——Part 1体系结构第(四)读:TPM架构
  6. java集合list方法吗_关于集合:将List转换为Java集合的最简单方法
  7. 在Android开发当中如何在一个app中打开淘宝app
  8. AdaCliP: Adaptive Clipping for Private SGD
  9. 上海-苏州 100公里徒步旅行心情分享(一)
  10. DataBinding(一)