1527的数据帧结构
无线遥控的编码,从编码类型上来说,分为2类,一类是固定码,也就是编码芯片的地址是不变的,芯片型号以 hs1527、ev1527、rt1527、fp1527、PT2262 为代表。另一种是滚动码,芯片的地址码是变化的,芯片以HS300、HS301为代表。
1 1527 数据帧结构
1527 是一片由 CMOS 设计制造的可预烧内码的学习码编码IC ,由软件解码;内码共有 20 个位元可预烧 1048576 组内码组合,降低使用上编码重复的机率。
1527 每帧数据由 24 个数据位组成,前 20 位为地址码,对于一个芯片来说,地址位的内容是固定的,是出厂前就预制好的,并且理论上每个芯片的地址码是唯一的。后面 4 位为按键码,对应芯片上的K0-K3 4 根数据线,数据线的状态不同,按键码就不同。
在数据位之前,还有一个同步脉冲,也就是每帧数据都是从同步
脉冲开始的。数据位的“1”和“0”是由高低电平宽度(脉冲宽度)的比例决定的。如果高电平宽度为低电平宽度的 3 倍,就表示逻辑“1”,反过来如果低电平为高电平宽度的 3 倍,就表示逻辑“0”。同步脉冲高电平和低电平的比例固定为 4:124.
二、中断方式的解码
把串行输入的编码数据帧,还原成编码之前的状态,读取其中
的地址码和按键码,称之为解码。
数据帧都是由同步头开始,然后是 24位的数据码,并且此数据帧在遥控器按键的过程中是重复出现的,我们首先要判断同步码,判断出了同步码,就知道数据码是从那一位开始了。对于一款量产的无线遥控器来说,他的编码芯片匹配的电阻是一个固定值,也就是说它发射的数据帧的脉冲宽度是不变的,所以我们可以通过测量高低脉冲宽度的方式来分辨同步码、逻辑“1”、逻辑“0”。
具体的方法是这样的,首先启用定时器,装入一个初值,打开
定时器中断,让其以固定的间隔进入中断程序。在中断程序中,我们查询数据输入管脚的状态,如果为高电平,就在高电平状态累加计数,反之就在低电平状态计数,当电平发生上升沿变化的时候,判断接收到的高低电平宽度的值是否符合同步信号的要求,如果符合就进入数据位的接收,以同样的方式判断逻辑“1”或逻辑“0”。如果接受过程中出现不符合要求的电平状态,就退出接收,为了增加可靠性,我们一般要求规定时间内,成功接收到完全相同的 2 帧数据才算有效。
接收完成后,24 个数据位被放入 3 个字节中。下一步我们要对接收到的数据进行处理,判断编码的类型,分离地址码和按键码。
代码如下
- #include "1527.h"
- /**
- * [url=home.php?mod=space&uid=2666770]@Brief[/url] 初始化控制LED的IO
- * [url=home.php?mod=space&uid=3142012]@param[/url] 无
- * @retval 无
- */
- 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 1527_Init() //1527 IO口初始化
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- NVIC_InitTypeDef NVIC_InitStructure;
- tiM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
- 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);
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
- NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- TIM_TimeBaseStructure.TIM_Period = 100;
- TIM_TimeBaseStructure.TIM_Prescaler =7;
- TIM_TimeBaseStructure.TIM_ClockDivision =
- TIM_CKD_DIV1;
- TIM_TimeBaseStructure.TIM_CounterMode =
- TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
- TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
- TIM_ClearFlag(TIM4,TIM_FLAG_Update);
- TIM_Cmd(TIM4,ENABLE );
- }
- void TIM4_IRQHandler()
- {
- if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
- {
- TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
-
- //接收数据的电平 PB9
- RF = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9);
- if (!RF)
- {
- ll_w++; // 检测到低电平 低电平时间加1,记录本次电平状态old_rc5
- old_rc5=0;
- }
- else // 检测到高电平
- {
- hh_w++;
- if (!old_rc5) // 检测到从低到高的跳变,已检测到一个完整(高-低)电平周期 判同步码 2/5 100/130
- {
- if (((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++; //已经接收到同步码,判0
- if(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(TIM4, TIM_IT_Update, DISABLE);
- rf_ok=0;
- rf_data[0]=mma1;
- rf_data[1]=mma2;
- rf_data[2]=mma3;
-
- decode_ok=1;
-
- //TIM_ITConfig(TIM4 , TIM_IT_Update, ENABLE);
- }
- }
- }
复制代码
|