搜索
bottom↓
回复: 31

m8,Gcc的遥控器解码&发送程序

[复制链接]

出0入0汤圆

发表于 2005-12-23 13:20:56 | 显示全部楼层 |阅读模式
以经过调试可选8mhz/4mhz工作占用1timer,1interrupt

不足之处请指教

------------IR.H--------------------------

#ifndef IR

#define IR

#include <avr/io.h>

#include <avr/signal.h>

#include <avr/interrupt.h>

#define MockIR                                        //使用遥控模仿定义他



#define InceptCustomCode_IR                0        //接收用户码//DVD/VCD:00

#define SendtCustomCode_IR                0        //发送用户码//DVD/VCD:00

#define FirstKeyHoldEventCyc        15

#define SecondKeyHoldEventCyc        1



#define SendHighState_IR                0        //红外发射状态



//发送引脚定义

#define SendPinP_IR                PIND

#define SendPin_IR                PIND2

#define SendDDR_IR                DDRD

#define SendDDD_IR                DDD2

#define SendPORT_IR                PORTD

#define SendP_IR                PD2

//#define SendPin_IR                 PORTD&(1<<PIND2)        //发送引脚定义

#define InceptPin_IR         PIND&(1<<PIND2)        //接收引脚定义

#define IREXInterrupt         SIGNAL(SIG_INTERRUPT0)//定义使用的外部中断(与接收引脚相关)SIGNAL

#define IRTimerInterrupt         SIGNAL(SIG_OVERFLOW0)//定义使用定时器INTERRUPT



#ifndef InIRDevice



#ifdef MockIR

extern bool  volatile SendMode_IR;                        //true = 发送模式;当发送结束后自动清0。

extern uchar volatile SendKey_IR;                //须发送的码值

extern void SendKeyIR();                //开始发送



#endif



#define GetKey_IR DATA_IR[2]        //获取按键码

extern void IniIR();                        //初始化IR

//extern uchar GetKey_IR();                //获取按键码

extern bool  volatile KeyDown_IR;                        //分别表示按键的按下状态

extern bool  volatile KeyHoldEvent;                //当按键按住“KeyHoldEventCyc”个周期(110ms)后被置一,须手动清零;发生于FirstKeyHoldEvent后。

extern bool  volatile FirstKeyHoldEvent;        //KeyHoldEvent是表示当按键按住过程第一次发生,自动清零

extern bool  volatile KeyHold_IR;                        //当FirstKeyHoldEvent置一时置一,一直到下一次检测的新的按键码输入时自动清零

extern uchar volatile State_IR;

extern uchar volatile DATA_IR[4];                //接收数据储蓄区

#endif



#endif

-------------IR.C---------------

#include "global.h"

#include "display.h"

#include "ir.h"





#define CountSpeed                4        //4MHZ//64us每周期

#define DoubleSpeed                DF_CPU/4000000ul

#define CountStop                0

#define Idle_IR                        0        //空闲                 高电平

#define LeaderL_IR                1        //导入信号         低电平

#define LeaderH_IR                2        //导入信号         高电平

#define CustomCode_IR        3        //开始接收自定义字节

#define Incept_IR                4        //数据接收中

#define KeyDowning_IR        5        //检测到按键按住信号

#define CodeH_IR                6        //数据高电平期间//参照PT2222.pdf

#define CodeL_IR                7        //数据低电平期间



uchar volatile State_IR=Idle_IR;                        //当前接收状态

uchar volatile DATA_IR[4];                                        //接收数据储蓄区

uchar volatile KeyHoldEventCyc        = FirstKeyHoldEventCyc;

uchar volatile keyHoldCount                = 0;

bool  volatile KeyDown_IR;                                        //表示按键的按下状态

bool  volatile KeyHold_IR;                                        //当FirstKeyHoldEvent置一时置一,一直到下一次检测的新的按键码输入时自动清零

bool  volatile KeyHoldEvent;                                //当按键按住“KeyHoldEventCyc”个周期(110ms)后被置一,须手动清零

bool  volatile FirstKeyHoldEvent;                        //KeyHoldEvent是表示当按键按住过程第一次发生,自动清零



static uchar volatile InceptBitCount;                //已经收到的(以发送的)比特数

static uchar volatile hold_tmp;                                //临时数据用于解决timer无法计时超过110ms问题

static bool  volatile DAT_bit_IR;                        //用于判断当前比特的0/1状态?





#ifdef MockIR

bool volatile SendMode_IR;                                //true = 发送模式;当发送结束后自动清0。

uchar volatile SendKey_IR;                                //须发送的码值

//static uchar SendBitCount;                //以发送的Bit数

static uchar volatile sendTmp;

void static reversalIRPIN()

{

        if(SendPORT_IR&(1<<SendP_IR))

                SendPORT_IR&= ~(1<<SendP_IR);//输出低电平

        else

                SendPORT_IR|= (1<<SendP_IR);//输出高电平

}

void SendKeyIR()                //开始发送

{

        if(SendMode_IR)

                return;

        SendMode_IR = true;

        GICR  &= ~(1<<INT0);//关外部中断0

        SendPORT_IR|= (1<<SendP_IR);//输出高电平

        SendDDR_IR |= (1<<SendDDD_IR);//配置为输出

        reversalIRPIN();//反转输出电平

        TCNT0 =256-35*DoubleSpeed;//延时9ms

        TCCR0  = 5;

        State_IR = LeaderL_IR;

}

#endif

/*uchar GetKey_IR()                                //获取按下按键的码值

{

//KeyDown_IR = false;

return        DATA_IR[2];

}*/

void IniIR()         //初始化接收

{

        DDRD  &=~(1<<DDD2);        //使能上拉电阻

        PORTD |= (1<<PD2);        //使能上拉电阻

        MCUCR |= (1<<ISC01);

        MCUCR &=~(1<<ISC00);//下降沿有效

        GICR  |= (1<<INT0);        //开外部中断0



        TIMSK |= (1<<TOIE0);//开定时器中断

        //TCCR0  = CountSpeed;//4MHZ//64us每周期

}

IRTimerInterrupt

{

uchar tmp;

        TCCR0  = CountStop;        //停计数

#ifdef MockIR

        if(SendMode_IR)

        {

                switch (State_IR)

                {

                case LeaderL_IR:

                        {

                                reversalIRPIN();//反转输出电平  //15周期

                                TCNT0 =256-70*DoubleSpeed;//延时4.5ms//64us

                                TCCR0  = CountSpeed;

                                State_IR        = LeaderH_IR;

                                break;

                        }

                case LeaderH_IR:

                        {

                                reversalIRPIN();//反转输出电平        //13周期

                                TCNT0 =256-9*DoubleSpeed;//延时0.56ms//64us//可能需用8

                                TCCR0  = CountSpeed;

                                State_IR        = CodeH_IR;

                                sendTmp                = SendtCustomCode_IR;

                                InceptBitCount = 0;

                                break;

                        }

                case CodeH_IR:

                        {

                                if(InceptBitCount==32)

                                {

                                        State_IR = Idle_IR;

                                        SendMode_IR = 0;

                                        SendPORT_IR|= (1<<SendP_IR);//输出高电平

                                        IniIR();                                         //初始化接收

                                        return;

                                }

                                reversalIRPIN();        //反转输出电平   //16周期

                                if(sendTmp&0x01)

                                {

                                        TCNT0 =256-26*DoubleSpeed;                                //延时1.69ms//64us

                                        TCCR0  = CountSpeed;

                                }

                                else

                                {

                                        TCNT0 =256-9*DoubleSpeed;                                //延时0.565ms//64us////可能需用8

                                        TCCR0  = CountSpeed;

                                }

                                InceptBitCount++;

                                sendTmp        = sendTmp>>1;

                                if(!(InceptBitCount%8))

                                {

                                        switch (InceptBitCount/8)

                                        {

                                        case 1:

                                                {

                                                        sendTmp = ~SendtCustomCode_IR;break;

                                                }

                                        case 2:

                                                {

                                                        sendTmp = SendKey_IR;break;

                                                }

                                        case 3:

                                                {

                                                        sendTmp = ~SendKey_IR;break;

                                                }

                                        }

                                }

                                State_IR        = CodeL_IR;

                                break;

                        }

                case CodeL_IR:

                        {



                                reversalIRPIN();        //反转输出电平         //12周期

                                TCNT0 =256-9*DoubleSpeed;                                        //延时0.56ms//64us//可能需用8

                                TCCR0  = CountSpeed;

                                State_IR        = CodeH_IR;

                                break;

                        }



                }

                return;

        }

#endif

        switch (State_IR)

        {

        case LeaderL_IR:

                {

                //PIND&(1<<PIND2)

                        tmp = PIND;

                        if(!(tmp&(1<<PIND2)))

                        {

                                State_IR =         LeaderH_IR;

                                TCNT0 =256-70*DoubleSpeed;                        //延时4.5ms//64us

                                TCCR0  = CountSpeed;

                        }

                        else

                        {

                                State_IR =         Idle_IR;

                        }

                        break;

                }

        case LeaderH_IR:

                {

                        tmp = PIND;

                        if(tmp&(1<<PIND2))

                        {

                                State_IR = CustomCode_IR;

                        }

                        else

                        {

                                State_IR =         Idle_IR;

                        }

                        KeyHold_IR = 0;

                        break;

                }

        case Incept_IR:

                {

                        if(DAT_bit_IR)                                //如果等待4.5ms后EX1仍未清'DAT_bit_IR',则退出接收状态

                        {

                                State_IR =         Idle_IR;

                                //ShowNumberEX2(0,GetKey_IR);        // 低位位置,数据

                                break;

                        }

                        TCNT0 =256-70*DoubleSpeed;                //延时4.5ms//64us

                        TCCR0  = CountSpeed;

                        DAT_bit_IR = 1;

                        break;

                }

        case KeyDowning_IR:

                {

                        if(hold_tmp>1+1*DoubleSpeed)

                                {

                                        KeyDown_IR = 0;

                                        //KeyHold_IR = 0;

                                        keyHoldCount = 0;

                                        State_IR = Idle_IR;

                                        break;

                                }

                                hold_tmp++;

                                TCNT0 =256-215;                        //延时55ms//256us//延时110ms清除'KeyDown_IR'

                                TCCR0  = 5;                                //1024

                                break;

                }

        }

}

IREXInterrupt

{

        uchar bytec,tmp;

        switch (State_IR)

        {

        case KeyDowning_IR:

                {}

        case Idle_IR:

                {

                        State_IR = LeaderL_IR;

                        TCNT0 =256-117*DoubleSpeed;                //延时7.5ms//64us

                        TCCR0  = CountSpeed;

                        return;

                }

        case LeaderH_IR:                        //按住信号(9ms导入脉冲后4.5ms内再次发生中断)

                {



                        keyHoldCount++;

                        if(keyHoldCount>KeyHoldEventCyc)

                        {

                                keyHoldCount = 0;

                                KeyHoldEvent = 1;

                                if(KeyHoldEventCyc ==  FirstKeyHoldEventCyc)

                                {

                                        KeyHold_IR        =        1;

                                        FirstKeyHoldEvent = 1;

                                        KeyHoldEventCyc = SecondKeyHoldEventCyc;

                                }

                                else

                                {

                                        FirstKeyHoldEvent = 0;

                                }

                        }

                        State_IR        =        KeyDowning_IR;

                        hold_tmp        =        0;

                        TCNT0 =256-215;                //延时55ms//256us//延时110ms清除'KeyDown_IR'

                        TCCR0  = 5;                        //1024

                        break;

                }

        case CustomCode_IR:

                {

                        DAT_bit_IR = 0;

                        InceptBitCount        =        0;

                        State_IR = Incept_IR;

                        TCNT0 =256-23*DoubleSpeed;                //延时1.5ms//64us

                        TCCR0  = CountSpeed;

                        break;

                }

        case Incept_IR:

                {

                        TCNT0 =256-23*DoubleSpeed;                //延时1.5ms//64us

                        TCCR0  = CountSpeed;

                        bytec = InceptBitCount/8;

                        tmp          = DATA_IR[bytec]>>1;

                        if(DAT_bit_IR)

                                tmp  |= 0x80;

                        DAT_bit_IR = 0;                        //清零等待如果是'1'timer1将会将其置位

                        DATA_IR[bytec]        =        tmp;



                        if(InceptBitCount==31)

                        {

                        uchar aa = DATA_IR[0];

                        uchar bb = ~DATA_IR[1];

                        uchar cc = DATA_IR[2];

                        uchar dd = ~DATA_IR[3];

                                if((aa == bb)&&(cc == dd)&&(aa==InceptCustomCode_IR))

                                {

                                        State_IR = KeyDowning_IR;

                                        KeyDown_IR = true;



                                        //ShowNumberEX2(0,GetKey_IR);        // 低位位置,数据]

                                }

                                else

                                {

                                        State_IR = Idle_IR;

                                        break;

                                }

                                keyHoldCount = 0;

                                hold_tmp        =        0;

                                KeyHoldEventCyc = FirstKeyHoldEventCyc;

                                TCNT0 =256-215;                //延时55ms//256us//延时110ms清除'KeyDown_IR'

                                TCCR0  = 5;                        //1024

                        }

                        InceptBitCount++;

                        break;



                }

        }

}

出0入0汤圆

发表于 2005-12-23 13:51:23 | 显示全部楼层
先收藏看先

出0入0汤圆

发表于 2005-12-23 14:35:05 | 显示全部楼层
請說明是什麼格式的編碼啊..

出0入0汤圆

发表于 2005-12-24 09:39:00 | 显示全部楼层
电路图在何方?

出0入0汤圆

发表于 2005-12-26 18:08:53 | 显示全部楼层
没有其他的资料 要这个程序又有多少价值呢

出0入0汤圆

发表于 2005-12-27 09:37:32 | 显示全部楼层
完來是PT2222的.

出0入0汤圆

 楼主| 发表于 2005-12-29 16:34:13 | 显示全部楼层
此软件用于红外遥控器的解码与模仿,现在大多数的DVD都使用此编码方式。

出0入0汤圆

发表于 2005-12-30 11:59:33 | 显示全部楼层
问一下,解码的时候怎么区分0和1的??谢谢,如果在线的话可以加我qq31656931

出0入0汤圆

发表于 2005-12-30 12:46:13 | 显示全部楼层
去找份PT2222的編碼協義看.

出0入0汤圆

 楼主| 发表于 2005-12-31 09:29:20 | 显示全部楼层
为1两次中断时间间隔为2.25ms

为0两次中断时间间隔为1.125ms

因此可以设一变量第一次中断时将其置0

并在让timer在1.125ms~2.25ms时间段内将此变量置1,

第二次中断发生时变量的值就是你需要的

出0入0汤圆

发表于 2006-9-27 21:43:17 | 显示全部楼层
有实物图么?

出50入0汤圆

发表于 2006-9-27 22:59:16 | 显示全部楼层
我在51上用中断解过,全中断过程,是NEC的协议,

但程序一直有点问题,可以解码,但解了几次就好像死机了,但程序没跑飞,

而且有时又莫名其妙好了,百思不得其解~~

出0入0汤圆

发表于 2006-9-30 23:21:22 | 显示全部楼层
这个也太长了吧

出0入0汤圆

发表于 2007-3-19 10:12:39 | 显示全部楼层
你这个解码还是有问题的吧!

出0入0汤圆

发表于 2009-4-1 16:26:48 | 显示全部楼层
老大,程序是不是有点太冗长了????

出0入0汤圆

发表于 2009-4-1 17:11:39 | 显示全部楼层
jh

出0入0汤圆

发表于 2009-6-7 12:03:44 | 显示全部楼层
留个记号

出0入0汤圆

发表于 2009-9-9 08:09:19 | 显示全部楼层
这个东西值得学习......好好踩下.

出0入0汤圆

发表于 2010-3-19 19:42:13 | 显示全部楼层
这个程序怎么这么长啊 头疼

出0入0汤圆

发表于 2010-3-19 21:52:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-22 18:01:17 | 显示全部楼层
mark..

出0入0汤圆

发表于 2010-3-22 19:51:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-5 01:28:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-5 02:40:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-5 17:35:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-10 20:18:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-31 14:42:54 | 显示全部楼层
先做个记号,以后借用。

出0入0汤圆

发表于 2012-2-2 16:35:08 | 显示全部楼层
回复【4楼】AVR-MEGA128
-----------------------------------------------------------------------

先下了看看

出0入0汤圆

发表于 2012-2-13 17:12:38 | 显示全部楼层
希望能用得到。虽然是坟贴还是要感谢一下兰州

出0入0汤圆

发表于 2012-2-14 04:38:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-18 11:58:35 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-21 13:36:06 | 显示全部楼层
看看先啦
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 22:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表