PT2264解码心得

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  短492uS
111         {                                             //窄电平的误差范围为正(M+M/4)负(M-M/4)一个振荡周期a=M/4;
112             I++;
113             MA1 <<= 1;    //本位置0
114         }
115         /*以下语句即判断宽电平是否合格(4.7M的振荡电阻时宽电平时长为1488uS即12a)    */
116         else if(((L > (M * 3 - M / 2)) && (L < (M * 3 + M / 2))))////如果此时为12a则本位为1  长1488uS
117         {                                                          //宽电平的误差范围为正(M * 3 + M / 2)负(M * 3 - M / 2) 两个振荡周期2a=M/2;
118             I++;
119             MA1 <<= 1;
120             MA1++;                  //本位置1
121         }
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、TL0
165     EX1 = 1;       //开启外部中断1
166 }
167 
168 
169 //void timer0(void) interrupt 1  //***********定时器T0中断子函数************** 
170 //{
171 //TH0=(65536-5000)/256;
172 //TL0=(65536-5000)%256;
173 //   i++;
174 //}
原文地址:https://www.cnblogs.com/UPUPDay2152/p/9457430.html