PT2264解码心得
最近闲暇时间在琢磨无线RF解码程序,正好在数码之家论坛中翻出大佬的解码程序(http://bbs.mydigit.cn/read.php?tid=245739),于是乎,慢慢学习2264解码程序,正好用上之前买的逻辑分析仪,带看波形,带看程序,琢磨了两天,程序已可完美解码,在此来总结下心得。
一、管脚如下图所示:
OSC1和OSC2为振荡电阻管脚,常用有4.7M、3.3M等,A0-A7位2264地址位管脚,可设置为悬空(F)、高(1)、低(0)三态;D0-D3为四位数据位;
振荡频率 f=2x1000x16/Rosc(KΩ) ,Rosc为振荡电阻阻值,单位为KΩ;例:Rosc=4.7MΩ;则,f=6.8KHz,则振荡周期为Trosc=1/f=147us;
二、PT2264编码格式如下:
1.位值格式(1、0、F)(长脉冲(3A)是短脉冲(A)的3倍)
窄高+宽低+窄高+宽低=0 宽高+窄低+宽高+窄低=1 窄高+宽低+宽高+窄低=F
2.时序图
同步码低电平(L)是窄脉冲(A)的31倍,即,A=L/31
上图中OSC表示振荡电阻周期 Trosc,则上图时序T=2XTrosc
3.数据结构
三、解码思路
1、首先识别出帧与帧,依据同步码区分开来,同步码低电平时长为31T;
2、再依据识别出的同步码,判断计算出窄电平时间T,则宽电平时间为3T;(判断窄电平思路,窄电平的误差范围为正(T+T/4)负(T-T/4)一个振荡周期A=T/4;宽电平的误差范围为正(T * 3 + T / 2)负(T * 3 - T / 2) 两个振荡周期2A=T/2)
3.依据宽窄电平组合即可解出遥控器码值。
四、程序如下所示,借鉴数码之家各位大佬程序再结合自己理解
1 //自适应频率的2262解码代码 晶振11.0592 2 #include <STC15F2K60S2.H> //STC15F104W头文件 3 #include <intrins.h> //左移右移函数头文件 4 #define uchar unsigned char 5 #define uint unsigned int 6 sbit WuXian_IN =P3^3; //外部中断1,RF模块DATA信号输入管脚 7 sbit OK_LED =P3^0; //解码成功 8 sbit D0=P3^1; //数据位1000 9 sbit D1=P3^2; //数据位0100 10 sbit D2=P3^4; //数据位0010 11 sbit D3=P3^5; //数据位0001 12 void Init() 13 { 14 TMOD = 0x01; //定时器T0,工作模式1,16位定时,不自动重装,TL0、TH0全用 15 TR0=0; //(可位寻址)关闭定时器T0运行 16 // ET0=0; //(可位寻址)T0的溢出中断允许控制位,ET0=1允许T0中断; ET0=0禁止T0中断; 17 18 EX1 =1; //允许外部中断1中断 19 IT1=0; //IT1=0 --上升沿和下降沿均可触发中断; IT1=1 ----下降沿触发 20 EA=1; //(可位寻址)开启总中断 21 22 } 23 24 void main() 25 { 26 Init(); 27 OK_LED=0; 28 D0=0; 29 D1=0; 30 D2=0; 31 D3=0; 32 while(1); 33 } 34 35 void ex0(void) interrupt 2 //外部中断1入口函数 36 { 37 38 39 40 //PT2262发码为窄高+宽低+窄高+宽低=0 /宽高+窄低+宽高+窄低=1 /窄高+宽低+宽高+窄低=F 41 //数值表示: 00 = 0 / 11 = 1 / 01 = F 42 //反码表示: 11 = 0 / 00 = 1 / 10 = F(本例所用) 43 bit err = 0; 44 uchar I = 0; //用来记录位数,正常会收到24位 45 uchar TL,TH; //用来记录每位的低电平总时长 46 uchar MA1,MA2,MA3; //用来记录地址码(占16位)和键码(占8位)(MA1、MA2、MA3各8个bit位) 47 uchar TimeCount; 48 uint L,M; 49 50 51 EX1 = 0; //暂停外部中断 52 TR0 = 1; //启动定时器计数器0 53 if(TimeCount > 0) //当按键按下释放后该值不在赋值就同通过递减直到该值等于0 54 { 55 TimeCount--; //等于0后表示按键释放 56 } 57 while(WuXian_IN == 0); //如果为0一直等待,等待高电平出现 58 while(I < 24) //共接收24位 59 { 60 while(WuXian_IN == 0); //等待高电平到来 61 TL = TL0; 62 TH = TH0; 63 TH0 = TL0 = 0; //记录低电平长度 64 L = TH; 65 L = ((L << 8) + TL); //将计时器的高低8位合并 66 if(I == 0) //处理同步位 67 { 68 if(L > 2360) //确认是引导头(判断同步位低电平时长31a) 69 { 70 M = L / 31; //M即4a亦即是窄电平的时长 71 } 72 else //不符合规则(出错) 73 { 74 I = TR0 = TH0 = TL0 = 0; 75 err = 1; 76 break; 77 } 78 } 79 else 80 { 81 //短555 长1666 82 //4.7M的振荡电阻时同步位的低电平时长为L=15378uS;即31a 83 //4.7M的振荡电阻时窄电平时长为M=492uS;即4a 84 //4.7M的振荡电阻时宽电平时长为1488uS即12a 85 //以下语句即判断窄电平与宽电平的宽度是否合格 86 /* 87 窄电平时长为M即 M=4a;a为一个振荡频率, fosc=(2x1000x16/Rosc(KΩ))KHz,fosc单位为KHz, (Rosc为振荡电阻,单位为KΩ),则一个振荡周期T=1/fosc 88 89 例如常用振荡电阻为4.7M;则振荡频率a=fosc=1/(2x1000x16/4700)=6.8KHz ,则振荡周期T=1/6.8K=147uS,即窄电平M=a=4T=588us;则宽电平3xM=3a=1764us; 90 91 程序中窄电平的误差范围为正(M+M/4)负(M-M/4)一个振荡周期a=M/4; 92 93 程序中宽电平的误差范围为正(M * 3 + M / 2)负(M * 3 - M / 2) 两个振荡周期2a=M/2; 94 95 */ 96 if(((L < M - M / 4) && (L > M + M / 4)) || ((L < M * 3 - M / 2) && (L > M * 3 + M / 2))) //如果窄电平小于4a与大小4a或宽电平小于12a与大小12a则表示出错 97 { //窄电平的误差范围为正(M+M/4)负(M-M/4)一个振荡周期a=M/4; 98 I = TR0 = TH0 = TL0 = 0; //宽电平的误差范围为正(M * 3 + M / 2)负(M * 3 - M / 2) 两个振荡周期2a=M/2; 99 err = 1;100 break;101 } 102 }103 while(WuXian_IN == 1); //等待低电平到来104 TH = TH0;105 TL = TL0;106 TH0 = TL0 = 0;107 L = TH;108 L = ((L << 8) + TL); //将计时器的高低8位合并109 /*以下语句即判断是窄电平是否合格(4.7M的振荡电阻时窄电平时长为492uS即4a) */110 if(((L > (M - M / 4)) && (L < (M + M / 4))))//如果此时为4a则本位为0 短492uS111 { //窄电平的误差范围为正(M+M/4)负(M-M/4)一个振荡周期a=M/4;112 I++;113 MA1 <<= 1; //本位置0114 }115 /*以下语句即判断宽电平是否合格(4.7M的振荡电阻时宽电平时长为1488uS即12a) */116 else if(((L > (M * 3 - M / 2)) && (L < (M * 3 + M / 2))))////如果此时为12a则本位为1 长1488uS117 { //宽电平的误差范围为正(M * 3 + M / 2)负(M * 3 - M / 2) 两个振荡周期2a=M/2;118 I++;119 MA1 <<= 1;120 MA1++; //本位置1121 }122 else //已不是4a也不是12a则不符合规表示出错123 {124 I = 0;125 TR0 = TH0 = TL0 = 0;126 err = 1;127 break;128 }129 if(I == 8)130 {131 MA3 = MA1; //每二位对应PT2262的一个引脚,bit7/bit6二位对应PT2262的1脚,类推对应PT2262的1~4脚 / 11 = 接+ / 00 = 接地 / 01 = 悬空132 //P1 = MA3; //送P1口显示方便调试133 }134 if(I == 16)135 {136 MA2 = MA1; //每二位对应PT2262的一个引脚,bit7/bit6二位对应PT2262的5脚,类推137 //对应PT2262的5~8脚 / 11 = 接+ / 00 = 接地 / 01 = 悬空138 //P0 = MA2; //送P1口显示方便调试139 }140 if(I == 24) //24位已收完则解码结束141 { 142 if(TimeCount == 0) //为0表示是新的一次按下对其进行处理,如过该值大于0表示已经按下不在处理143 { 144 switch(MA1)145 {146 case 0xC0: //PT2262的10脚按键按下时147 D0 = ~D0;148 break;149 case 0x30: //PT2262的11脚按键按下时150 D1 = ~D1;151 break; 152 case 0x0C: //PT2262的12脚按键按下时153 D2 = ~D2;154 break; 155 case 0x03: //PT2262的13脚按键按下时156 D3 = ~D3;157 break; 158 }159 }160 OK_LED = !OK_LED; //解码正确后取反一次161 TimeCount =20000; //PT2262每按一次会发出4组相同的编码防止按键没放开直在取反,保证按1次只做1次处理162 }163 }164 TR0 = TH0 = TL0 = 0; //关闭定时器T0,并重置TH0、TL0165 EX1 = 1; //开启外部中断1166 }167 168 169 //void timer0(void) interrupt 1 //***********定时器T0中断子函数************** 170 //{171 //TH0=(65536-5000)/256;172 //TL0=(65536-5000)%256;173 // i++;174 //}