打印

遥控解码大家谈,内有精美遥控器图片

[复制链接]
10273|46
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
古道热肠|  楼主 | 2008-9-9 13:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
自开展DIY优盘与PC电脑遥控器活动以来,得到了广大网友的关注和支持,更有热心网友提供了样品和及解码源程序,在此非常感谢.
 遥控解码说起来简单,实现的方法也很多,但也很有技巧性艺术性,比如可以用最简单的方式即查询管脚并用CPU空指令延时来实现解码,也可用中断触发+定时器延时来译码,还有用定时器捕获功能来实现边沿触发中断来处理等多种方式
  软件驱动的设计也很有学问,可以采用if else构成的条件判断,也可采用状态机的状态转移.
  发此贴与大家沟通一下.希望能找到一个比较好的驱动程序来作为范例,具体遥控发射芯片定为upD1621G.

相关帖子

沙发
古道热肠|  楼主 | 2008-9-9 14:02 | 只看该作者

由网友程工提供的遥控器照片

大家看看喜欢吗?小巧玲珑.用的是CR2025钮扣电池.

使用特权

评论回复
板凳
古道热肠|  楼主 | 2008-9-9 14:07 | 只看该作者

贴上电路原理图

遥控器原理图,采用的是upD6121G

使用特权

评论回复
地板
原野之狼| | 2008-9-9 14:08 | 只看该作者

赶紧占座~

使用特权

评论回复
5
古道热肠|  楼主 | 2008-9-9 14:11 | 只看该作者

<转贴>该芯片编码原理

   红外线遥控是目前使用最广泛的一种通信和遥控手段。由于红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。工业设备中,在高压、辐射、有毒气体、粉尘等环境下,采用红外线遥控不仅完全可靠而且能有效地隔离电气干扰。

1 红外遥控系统

通用红外遥控系统由发射和接收两大部分组成,应用编/解码专用集成电路芯片来进行控制操作,如图1所示。发射部分包括键盘矩阵、编码调制、LED红外发送器;接收部分包括光、电转换放大器、解调、解码电路。



2 遥控发射器及其编码

遥控发射器专用芯片很多,根据编码格式可以分成两大类,这里我们以运用比较广泛,解码比较容易的一类来加以说明,现以日本NEC的uPD6121G组成发射电路为例说明编码原理。当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。这种遥控码具有以下特征:

采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如图2所示。



上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。然后再通过红外发射二极管产生红外线向空间发射,如图3所示。



UPD6121G产生的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干扰。该芯片的用户识别码固定为十六进制01H;后16位为8位操作码(功能码)及其反码。UPD6121G最多额128种不同组合的编码。

遥控器在按键按下后,周期性地发出同一种32位二进制码,周期约为108ms。一组码本身的持续时间随它包含的二进制“0”和“1”的个数不同而不同,大约在45~63ms之间,图4为发射波形图。

当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms),一个结果码(4.5ms),低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms)和结束码(2.5ms)组成。

代码格式(以接收代码为准,接收代码与发射代码反向) 
①位定义 
              
②单发代码格式 
           
③连发代码格式 


注:代码宽度算法:

16位地址码的最短宽度:1.12×16=18ms 16位地址码的最长宽度:2.24ms×16=36ms 


易知8位数据代码及其8位反代码的宽度和不变:(1.12ms+2.24ms)×8=27ms 

∴32位代码的宽度为(18ms+27ms)~(36ms+27ms) 

1. 解码的关键是如何识别“0”和“1”,从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可。

2. 根据码的格式,应该等待9ms的起始码和4.5ms的结果码完成后才能读码。

使用特权

评论回复
6
古道热肠|  楼主 | 2008-9-9 14:15 | 只看该作者

贴图说明

使用特权

评论回复
7
古道热肠|  楼主 | 2008-9-9 14:16 | 只看该作者

再来一幅

使用特权

评论回复
8
古道热肠|  楼主 | 2008-9-9 14:21 | 只看该作者

网上找到解码原程序,对理解工作原理还是有用的

ORG 0000H 
START:MOV P0,#0FFH
MOV P1,#0FFH
MOV P2,#0FFH
MOV P3,#0FFH
JNB P3.2,$;等待遥控信号出现
MOV R6,#10
SB: ACALL YS1;调用882微秒延时子程序
JB P3.2,START;延时882微秒后判断P3.2脚是否出现高电平如果有就退出解码程序
DJNZ R6, SB;重复10次,目的是检测在8820微秒内如果出现高电平就退出解码程序
;以上完成对遥控信号的9000微秒的初始低电平信号的识别。
JNB P3.2, $ ;等待高电平避开9毫秒低电平引导脉冲
ACALL YS2 ;延时4.74毫秒避开4.5毫秒的结果码
MOV R1,#1AH ;设定1AH为起始RAM区
MOV R2,#4 
PP: MOV R3,#8
JJJJ: JNB P3.2,$;等待地址码第一位的高电平信号
LCALL YS1;高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态
MOV C,P3.2;将P3.2引脚此时的电平状态0或1存入C中
JNC UUU;如果为0就跳转到UUU
JB P3.2,$;如果为1就等待高电平信号结束
UUU: MOV A,@R1;将R1中地址的给A
RRC A;将C中的值0或1移入A中的最低位
MOV @R1,A;将A中的数暂时存放在R1中
DJNZ R3,JJJJ;接收地址码的高8位
INC R1;对R1中的值加1,换成下一个RAM
DJNZ R2,PP ;接收完16位地址码和8位数据码和8位数据反码,存放在1AH/1BH/1CH/1DH的RAM中
;以下对代码是否正确和定义进行识别
MOV A,1AH;比较高8位地址码
XRL A,#00000000B ;判断1AH的值是否等于00000000,相等的话A为0
JNZ EXIT;如果不相等说明解码失败退出解码程序
MOV A,1BH;比较低8位地址
XRL A,#11111111B ;再判断高8位地址是否正确
JNZ EXIT;如果不相等说明解码失败退出解码程序
MOV A,1CH;比较数据码和数据反码是否正确?
CPL A
XRL A,1DH ;将1CH的值取反后和1DH比较 不同则无效丢弃,核对数据是否准确
JNZ EXIT;如果不相等说明解码失败退出解码程序
CLR P2.7;解码成功发光二极管点亮指示!
AJMP BIJIAO

;判断在118毫秒内是否有连发码
AA:MOV R1,#25
XX:ACALL YS2
JNB P3.2,HH;跳转到判断连发代码是否正确的程序段
DJNZ R1,XX
EXIT: MOV P0,#0FFH;对所有端口清零
MOV P1,#0FFH
MOV P2,#0FFH
MOV P3,#0FFH
AJMP START

;连发码判断程序段-----------
HH:MOV R6,#4
S: ACALL YS1;调用882微秒延时子程序
JB P3.2,EXIT;延时882微秒后判断P3.2脚是否出现高电平如果有就退出解码程序
DJNZ R6, S;重复4次,目的是确认连发码的低电平信号波形
JNB P3.2, $ ;等待高电平
AJMP AA

BIJIAO:MOV A,1CH;按键数值判断执行
CJNE A,#00000101B,TT1 
CPL P0.0
TT1: CJNE A,#00000100B,TT2
CPL P0.1
TT2: CJNE A,#00010000B,T3
CPL P0.2
T3: CJNE A,#01001101B,T5
CPL P0.3
T5: CJNE A,#01001110B,T6
CPL P0.4
T6: CJNE A,#01001100B,T7
CPL P0.5
T7: CJNE A,#00001001B,T8
CPL P0.6
T8: CJNE A,#00011101B,T9
CPL P0.7
T9: CJNE A,#00011111B,T10
CPL P2.6
T10: CJNE A,#00001101B,T11
CPL P2.5
T11: CJNE A,#00011001B,T12
CPL P2.4
T12: CJNE A,#00011011B,T13
CPL P2.3
T13: CJNE A,#00010001B,T14
CPL P2.2
T14: CJNE A,#00010101B,T15
CPL P2.1
T15: CJNE A,#00010111B,T16
CPL P2.0
T16: CJNE A,#00010010B,T17
CPL P1.0
T17: CJNE A,#00010110B,T18
CPL P1.1
T18: CJNE A,#01011110B,T19
CPL P1.2
T19: CJNE A,#01011101B,T20
CPL P1.3
T20: CJNE A,#01011100B,T21
CPL P1.4
T21: CJNE A,#01001111B,T22
CPL P1.5
T22: CJNE A,#00000001B,T23
CPL P1.6
T23: CJNE A,#00000011B,T24
CPL P1.7
T24: CJNE A,#00000000B,T25
CPL P3.0
T25: CJNE A,#00010100B,T26
CPL P3.1
T26: CJNE A,#00011110B,T27
CPL P3.3
T27: CJNE A,#00011010B,T28
CPL P3.4
T28: CJNE A,#00001111B,T29
CPL P3.5
T29: CJNE A,#00001010B,T30
CPL P3.6
T30: CJNE A,#00001110B,OK
CPL P3.7
OK:AJMP AA
YS1: MOV R4,#20 ;延时子程序1,精确延时882微秒
D1: MOV R5,#20
DJNZ R5,$
DJNZ R4,D1 
RET
YS2: MOV R4,#10 ;延时子程序2,精确延时4740微秒
D2: MOV R5,#235
DJNZ R5,$
DJNZ R4,D2 
RET
END

使用特权

评论回复
9
古道热肠|  楼主 | 2008-9-9 14:28 | 只看该作者

8楼的解码程序做了个项目,打包上传,便于查看

使用特权

评论回复
10
古道热肠|  楼主 | 2008-9-9 14:31 | 只看该作者

好的,下面是大家各显身手了.

俺在淘宝上找了个徐姓卖家想要一份源码参考,卖家开口说您买开发板就送,哈哈,就这东西还当个宝,有意思.

使用特权

评论回复
11
awey| | 2008-9-9 14:51 | 只看该作者

不知道红外接收的输出脉冲是否稳定

曾经用MCU做过简易ASK无线遥控的接收,ASK解码电路输出的脉冲宽度随信号的强度变化相当的大,常常出现误解码的情况。

当初用3个1,1个0表示0,1个1,三个0,表示0的编码方式。

使用特权

评论回复
12
yewuyi| | 2008-9-9 15:36 | 只看该作者

这个东西洗碗机比较喜欢玩。。。

古道热肠 发表于 2008-9-9 14:31 侃单片机 ←返回版面    

10楼: 好的,下面是大家各显身手了. 

俺在淘宝上找了个徐姓卖家想要一份源码参考,卖家开口说您买开发板就送,哈哈,就这东西还当个宝,有意思.

 
 
这个徐姓卖家不是洗碗机把???


如果你的芯片跑得飞快,能够100uS/200uS产生一个定时中断,那么即使用查询边沿的方式也完全可以解码,否则就用IO的下降沿中断+一个定时器计算两次下降沿的时间间隔,捕获方式到没尝试过,估计原理差不多把。。。

哈哈,找XWJ估计没错,XWJ那解码程序写的多牛叉。。。

使用特权

评论回复
13
xwj| | 2008-9-9 16:06 | 只看该作者

呵呵,在网上买了N多东西,还从没卖过什么呢...

所以不是我啊~~~~~~
而且这么简单的东西,我会要钱吗???

8楼那程序写的真差劲,
用延时等待的方式,那接收时的36mS就什么都别干了,
遥控器每按一下,系统就卡一下吧:-)
(可能卡吧斯基就是这么来的,卡吧,死机啊...)

要是我把程序写成那样的话,甭说要钱呢,不要钱我都得一头撞死算了,没脸见人啊...



还是来看看偶在很久以前写的实验学习程序吧:
(思路绝对值得学习,效率却需要优化;-) 用汇编可以显著减少中断时间哦~~~  )


/*************************************************************
红外线遥控器按键检测程序.
通过检测两次下降沿之间的时间差判断接受到的数据位.
已经通过了测试,能够正确区分出32bit数据的遥控器按键键值.
具有数据重发功能,但是数据的重发有点频繁.
使用晶震频率为11.0592MHz,所有定时值都是基于这个频率计算.
占用很少量的CPU时间,使用了外部中断0接受数据,定时器0进行计数,
定时器1作为串口的波特率发生器(Band = 9600).
主函数数会使MCU进入低功耗模式,如需加入自己的代码需要屏蔽此功能.
状态机:
1.如果时间差=0,由空闲态进入接受态
2.如果时间差>1ms and <1.3ms,收到数据0
3.如果时间差>2ms and <2.5ms,收到数据1
4.如果时间差>10.0ms and <13.8ms,收到开始位或连发代码的开始位
5.如果时间差>12.2ms and <12.8ms,收到停止位(没有用到)
6.如果时间定时器溢出(时间差>20ms),进入空闲状态
*************************************************************/

//        本程序 可以说是状态机的典范                                       //
//        参照了网友高伟能gwnpeter@21cn.com的代码和思路,仅供学习参考       //
//        如有问题请mailto xuwenjun@21cn.com    欢迎与我交流!               //
//--------------------------------------------------------------------------//
//                                                                          //
//                    (c) Copyright 2001-2003 xuwenjun                     //
//                            All Rights Reserved                           //
//                                    V1.00                                 //
//--------------------------------------------------------------------------//
//标 题: Ir_6222遥控芯片接收程序                                           //
//文件名: ir_6222.c                                                         //
//版 本: V1.00                                                             //
//修改人: 徐文军                         E-mail:xuwenjun@21cn.com           //
//日 期: 03-06-14                                                          //
//描 述: Ir_6222遥控芯片接收程序                                           //
//--------------------------------------------------------------------------//
//老版本: 无                             老版本文件名:                      //
//创建人: 徐文军                         E-mail:xuwenjun@21cn.com           //
//日 期: 03-06-14                                                          //
//描 述: Ir_6222遥控芯片接收程序                                           //
//        当ykok=1时,ykcode中的数据就是接收到的遥控码(32位的第3字节)          //
//--------------------------------------------------------------------------//
//占用以下资源:                                                             //
//        1. 遥控使用外部中断0,接P3.2口                                     //
//        2. 遥控使用定时计数器1                                            //
//        3. 4.2字节data RAM                                                //
//        4. 293字节 code ROM                                               //
//--------------------------------------------------------------------------//
//声 明:
//
//        以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处. //
//        如用于商业用途请与作者联系.    E-mail:xuwenjun@21cn.com           //
//        本程序参照了网友高伟能gwnpeter@21cn.com的代码,仅供学习参考       //
//        如有问题请mailto xuwenjun@21cn.com    欢迎与我交流!               //
//--------------------------------------------------------------------------//

#include <REG52.H>
//#include "Ir_6222.h"                  //  ht6222函数数原型: 公用函数
//#include "xwj_4led.h"                 //  四位LED显示模块  //
//#include <stdio.h>
//--------------------------------------------------------------------------//


#define TIME_0_00MS        0x0000
#define TIME_1_00MS        0x039a
#define TIME_1_13MS        0x0480
#define TIME_2_00MS        0x0733
#define TIME_2_50MS        0x0900
#define TIME_10_0MS        0x23ff
#define TIME_13_2MS        0x2ecd
#define TIME_20_0MS        0x47ff
#define TIME1_LOAD        (0xffff - TIME_20_0MS)

long Irbuf;
unsigned char Irdat;
bit Irok;
bit running;
unsigned char Irwait;

void IrInit(void)                       //遥控接收初始化
{
    //-----init TIME1----
    TMOD |= 0x10;                       //TMOD T0,T1均选用方式1(16位定时)
    TH1    = TIME1_LOAD >> 8;
    TL1    = TIME1_LOAD & 0xff;
    //        SCON=0x00;
    IP|=0x01;                           //SETB  int0 中断优先
    TCON |= 0x41;                       //TCON  EX0下降沿触发,启动T1 //
    TR1    = 1;
    IE|=0x89;                                        
            //SETB        EX0 0x1  外部中断 0 允许
            //SETB        ET0 0x8  定时器 1 中断允许
            //SETB        EA  0x80 开中断
}

unsigned char IrGetcode(void)                        //返回遥控码
{
    Irok=0;
    return(Irdat);
}

bit IrTest(void)                                     //检查有无遥控信号
{
    return(Irok);
}

void int0_isr(voidinterrupt 0        //遥控使用外部中断0,接P3.2?
{
    unsigned int timer;

    TR1 = 0;
    timer = ((TH1 << 8) | TL1) - TIME1_LOAD;
    TH1 = TIME1_LOAD >> 8;
    TL1 = TIME1_LOAD & 0xff;
    TR1 = 1;

    if        (timer > TIME_1_00MS && timer < TIME_1_13MS)    //data 0
        Irbuf = (Irbuf << 1) & 0xfffffffe;
    else if    (timer > TIME_2_00MS && timer < TIME_2_50MS)   //data 1
        Irbuf = (Irbuf << 1) | 0x00000001;
    else if    (timer == TIME_0_00MS || timer > TIME_10_0MS)
        Irbuf = 0x0000;
    running = 1;
}

void time1_isr(voidinterrupt 3        //遥控使用定时计数器1
{
    //    EA = 0;
    //    TR1 = 0;
    TH1 = TIME1_LOAD >> 8;
    TL1 = TIME1_LOAD & 0xff;
    if    ((((Irbuf >> 24) & 0xff) == (~((Irbuf >> 16)) & 0xff)) &&(((Irbuf >> 8) & 0xff) == (~((Irbuf >> 0)) & 0xff)))
//  if    (((Irbuf >> 8) & 0xff) == ((~(Irbuf >> 0)) & 0xff))
    {       //满足编码检验规律,接收有效     (上面是UPD6121G的格式,下面是ht6222的格式)
        Irdat = (Irbuf>>8) & 0xff;
        Irok = 1;                   //收到单发代码
        Irwait = 6;         //6个20mS,用来等待可能的连发代码
    }
    else if((Irwait == 1) || (Irwait == 2))     //限定连发代码的时间位置
    {
        Irok = 1;                   //收到连发代码
        Irwait = 6;         //6个20mS,用来等待下一个连发代码
    }
    else if(Irwait != 0)
    {
        Irwait--;
        running = 0;
    }
    //    IE0 = 0;
    //    EA = 1;
}

/*************************************** /
//  HT6222测试主函数
void main(void)                             //主程序
{
    IrInit();
    led_test();                             //4LED测试函数
    while(1)     
    {
        if (IrTest())
            led_showhh(IrGetcode());
//      IrGetcode();
//      led_delay(10);
    }
}
/***************************************/

[#007f00]//本程序由xwj设计的UltraEdit脚本加亮显示,如需要脚本访问我的Blog 或发送邮件至:xwjfile@21cn.com

使用特权

评论回复
14
yewuyi| | 2008-9-9 16:22 | 只看该作者

洗碗机忽悠大家。。。

占用很少量的CPU时间,使用了外部中断0接受数据,定时器0进行计数,
定时器1作为串口的波特率发生器(Band = 9600).
主函数数会使MCU进入低功耗模式,如需加入自己的代码需要屏蔽此功能.


void int0_isr(void) interrupt 0        //遥控使用外部中断0,接P3.2?
{
。。。
}

void time1_isr(void) interrupt 3        //遥控使用定时计数器1
{
。。。
}


呵呵,你的定时器0跑哪儿去了啊?!

使用特权

评论回复
15
xwj| | 2008-9-9 16:40 | 只看该作者

定时器0休假了,换定时器1顶班...

使用特权

评论回复
16
古道热肠|  楼主 | 2008-9-9 17:17 | 只看该作者

贴上网友"芯行天下"提供的红外解码程序,采用边沿捕获中断

用来解析TC9012芯片码的ARM程序,唯一不足的是没有采用状态机,理解和维护起来有些困难,这种处理比较适合于ARM环境.
/****************************************Copyright (c)**************************************************
**                                 http://magicchip.21ic.org
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: config.h
** Last modified Date:  2008-08-27
** Last Version: 1.0
** Descriptions: main function
** osc     = 14.7456
** Fsclk = 4*osc;
** Fpclk = Fsclk/4;
** P0.28 CAP0.2捕获输入.
**------------------------------------------------------------------------------------------------------
** Modified by:          magicchip
** Modified date:    20080901
** Version:            V1.0
** Descriptions:    TC9012型芯片红外发射解码,本程序只适用于TC9012。
** QQ:              372288147
** BLOG:            http://magicchip.21ic.org
** Email:           magicchip@163.com
********************************************************************************************************/

/******************************************程序说明************************************************
** 编码芯片说明:编码芯片的数据发送格式为1)引导码,2)用户码,3)数据码及其反码,4)同步码
** 编码格式说明:1)由4.5ms的高电平和4.5ms的低电平组合而成。
**             2,3)    以脉宽为0.565ms高电平、0.56ms低电平、周期为1.125ms的组合表示二进制的“0”;
**                  以脉宽为0.565ms高电平、1.685ms低电平、周期为2.25ms的组合表示二进制的“1”;
**               4) 同步位(SY)是标志最后一位编码是“0”或“1”的标识位,它只有0.56ms
                    的有载波信号构成
** 接收头输出说明:接收头输出为编码格式的反向输出。即当编码格式为高电平时,接收头输出低电平。

** 程序说明:leadcodeflag全局变量作为红外解码进度的一个标志,用到三个标志位。位一用来表示数据全部
**           接收完成,当数据接收完成并正确时置位,该标志位只有当用户使用了接收到的数据或者接收错
**           误时清除;位二表示接收到引导码高电平标志;位三表示引接收到引导码低电平标志。这三位标
**              志只有标志1对用户开放,用户根据该标志位来判断是否有新的红外数据接收到。
**           raydata为接收到的红外编码数据,该变量为32位,根据接收的情况它的格式为最高8位为数据码
**           的反码,次高8位为数据码,其次8位为用户码,最低8位为用户码。

** 占用硬件资源:占用了定时器0的一个捕获功能,占用一个引脚用于捕获,占用一个引脚用于接收观察。

** 编译环境:RealView MDK-ARM version:3.21
*************************************************************************************************/

#include "config.h"


/*
*********************************************************************************************************
** 函数名称 :Timer1_CapInt()
** 函数功能 :定时器0捕获中断服务程序
** 入口参数 :无
** 出口参数 :无
*********************************************************************************************************
*/
uint8  leadcodeflag;          //红个接收标志
uint32 capdata;                //上次捕获定时器的值
uint32 raydata;                 //红外接收到的数据
uint8  raybits;                //接收数据的位数。

void __irq Timer0_CapInt (void)
{
    uint32 crtemp;
    uint32 temp;
    T0IR = 1 << 6;                                            // 清除CAP0.2中断标志

    crtemp = T0CR2;                                            // 取得捕获的值.
    if ((leadcodeflag & leadcodeh) == leadcodeh)            //引导码完整,接收数据。
    {
        if (!raypin())                                        //当红外检测引脚为低时
        {
             temp = ((crtemp - capdata)*1000*10)/Fpclk;
            if (temp > 20)                                    //判断数据的高低电平组合是否大于2MS
            {
                capdata = crtemp;                            //检测数据为1
                raydata |= (1<<raybits);
                raybits++; 
            }
            else if (temp > 10)                                //判断数据的高低电平组合是否大于1MS
            {
                capdata = crtemp;                            //检测数据为0
                   raydata &= (~(1<<raybits));
                raybits++;
            }
            else                                            //接收数据出错.
            {
                leadcodeflag &= (~(leadcodeh | leadcodel));    //清除引导码高低电平接收标志.
                raybits = 0;
            }

            if (raybits >= 32)                              //32位数据接收完成
            {
                leadcodeflag |= leadcodef;                  //数据接收完全标位
                leadcodeflag &= (~(leadcodeh | leadcodel));    //清除引导码高低电平接收标志.
                raybits = 0;                
            }
        }
    }
    else                                                    //引导码不完整,接收引导码.
    {
        if ((leadcodeflag & leadcodel) == leadcodel)        //引导码低电平已检测
        {
            if (!raypin())                                    //当红外检测引脚为低时
            {
                temp = (((crtemp - capdata)*1000*10)/Fpclk);// 为了调试方便
                if (temp >= 40)                                 //判断高电平时间4.5MS
                {
                    capdata = crtemp;
                    leadcodeflag |= leadcodeh;              //高电平检测完成.
                    leadcodeflag &= (~leadcodef);            //清除32位数据接收完成标志.
                    raybits = 0;
                }
                else                                        //接收引导码出错
                {                                            //古道热肠补充一下,应该回到起始态较为合理,将ledcodel也清零
                    leadcodeflag &= ~leadcodel;    
                }
            }
            else                                            //接收引导码出错
            {
                leadcodeflag &= ~leadcodel;    
            }
        }
        else                                                //检测引导码低电平部分
        {
             if (!raypin())                                    //当红外检测引脚为低时
                capdata = crtemp;
            else                                            //当红外检测引脚为高时,判断低电平时间.
            {
                temp = ((crtemp - capdata)*1000*10)/Fpclk;    //为了调试方便。
                if (temp >= 40)                                //判断低电平时间4.5MS
                {
                    capdata = crtemp;
                    leadcodeflag |= leadcodel;              //低电平检测完成.
                }
            }
        }
    }    
    
    if (ledstate())                                            //为了便于观察用了一个LED灯闪烁
        clrled();
     else
        setled();
    VICVectAddr = 0x00;                                        // 向量中断处理结束
}

// cap 定时器初始化。
void capinit(void)         
{
    T0PR  = 0;                                              // 分频系数    ,不分频,相当于14.745600M
    T0CCR = (1 << 7)|(1 << 6)|                                // 设置CAP0.2双沿捕获
            (1 << 8);                                        // 允许产生中断
            
    T0TC  = 0;
    T0TCR = 0x01;                                            // 启动定时器
}                            

// 中断向量的初始化
void irqinit(void)
{
    VICIntSelect = 0x00000000;                                // 设置所有的通道为IRQ中断
    VICVectCntl0 = 0x20 | 4;                                // Timer0分配到IRQ slot0,即最高优先级
    VICVectAddr0 = (uint32)Timer0_CapInt;                    // 设置Timer0向量地址
    VICIntEnable = 1 << 4;                                    // 使能Timer0中断
}
/*
*********************************************************************************************************
** 函数名称 :main()
** 函数功能 :测试定时器捕获中断
** 入口参数 :无
** 出口参数 :无
** 调试说明 :
*********************************************************************************************************
*/
int main(void)
{

    setcappin();                                           //定义捕获引脚 P0.28连接CAP0.2

    IO0DIR = LED;                                           // LED灯用于观察接收信号的情况
    IO0SET = LED;
    
    capinit();
    irqinit();
    
    while (1);

}

使用特权

评论回复
17
dcp| | 2008-9-10 01:11 | 只看该作者

比比谁的最精简最稳定最可靠

//在133US中断里调用

unsigned char Rxi133us(void)
{     
    //RFBit = RF_DATA;
    
    if (RFFull)                 // avoid overrun
    {
        return;
    }
    
    //if (RFBit)
    if (RF_DATA)
    {
        if (( RFcount > SHORT_HEAD) && ( RFcount < LONG_HEAD))
        {    
            RFcount = 0;
            Bptr = 0;
            BitCount = 0;
            return;
        }        
        else if ((RFcount > 0) && (RFcount < 5))        
        {
            RfData = 0;    
        }
        else if ((RFcount > 4) && (RFcount < 15))
        {
            RfData = 1;                
        }        
        else
        {
            RFcount = 0;
            //Bptr = 0;
            //BitCount = 0;            
            return;
        }
        
        RFcount = 0;    
        
        B[Bptr] >>= 1;              // rotate 
        
        if (RfData == 1)
        {
            B[Bptr] += 0x80;          // shift in bit
        }
        
        if ((++BitCount & 7) == 0)
        {
            Bptr++;                 // advance one byte        
        }
        
        if (BitCount == NBIT)
        {             
            RFFull = TRUE;
        } 
    }
    else
    {
        RFcount++;
    }
   
}

使用特权

评论回复
18
yewuyi| | 2008-9-10 08:39 | 只看该作者

LS的代码少,但133US的定时中断也太频繁了把。。。

使用特权

评论回复
19
huangqi412| | 2008-9-10 08:47 | 只看该作者

这个徐姓卖家不是洗碗机把??? 这句有意思.

使用特权

评论回复
20
xwj| | 2008-9-10 08:54 | 只看该作者

就这东西还要钱,真是徐姓家的耻辱、败类

不过可以肯定:那人不知道“古道热肠”,更没吃过...


古道热肠也真是的,就这玩意还要找人要代码,自讨没趣了吧?
还不买东西光要好处,你以为人人都是洗碗机啊?
你要不买东西去找ZLG要代码看看?看不噎死你...

^_^

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

284

主题

6411

帖子

16

粉丝