搜索
bottom↓
回复: 49

如何实现不用外部中断来红外解码?

[复制链接]

出0入0汤圆

发表于 2011-3-31 22:55:08 | 显示全部楼层 |阅读模式
要把红外接收头的引脚接在单片机(除了外部中断引脚)的任意IO口,该怎么实现解码啊?

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2011-3-31 23:27:55 | 显示全部楼层
不断的检测信号输入引脚,其他的什么都不能做,如果做其他事就有可能错过了红外信号接受时间;因为红外信号到来时是不定时的,随时都有可能出现,所以使用中断的目的就是为了在做其他事时产生中断来处理红外接受程序。

出0入0汤圆

 楼主| 发表于 2011-3-31 23:31:25 | 显示全部楼层
那样的话,不就是单独的红外的程序而已了吗?我的程序还要运行其他动作呢。 哎!现在不知道该怎么办?

出0入0汤圆

发表于 2011-3-31 23:38:47 | 显示全部楼层
那你的中断都干什么了?贴个图来帮你看看。

出0入0汤圆

发表于 2011-3-31 23:39:56 | 显示全部楼层
用输入捕获中断(ICP).

出0入0汤圆

 楼主| 发表于 2011-3-31 23:41:53 | 显示全部楼层
做板的时候没有注意这个问题。现在有没有办法改。所以就想用其他IO口来实现红外解码

出0入0汤圆

 楼主| 发表于 2011-3-31 23:42:57 | 显示全部楼层
回复【4楼】ykr1
-----------------------------------------------------------------------

怎么捕获法,也是一直在那里等待?

出0入0汤圆

发表于 2011-3-31 23:46:18 | 显示全部楼层
楼主用的什么型号单片机,有的单片机没有PCA捕获。

出0入0汤圆

 楼主| 发表于 2011-3-31 23:46:54 | 显示全部楼层
STC89C52

出0入0汤圆

发表于 2011-3-31 23:47:13 | 显示全部楼层
建议楼主飞根线,来的比较实际。

出0入0汤圆

发表于 2011-3-31 23:48:23 | 显示全部楼层
89C52没有PCA捕获 ,一般有PWM输出的单片机才有PCA捕获。

出0入0汤圆

发表于 2011-3-31 23:50:11 | 显示全部楼层
用定时中断,可以任一个IO口解码

出0入0汤圆

 楼主| 发表于 2011-3-31 23:51:58 | 显示全部楼层
回复【9楼】liuzhichengour
-----------------------------------------------------------------------

我也觉得,实在没有办法的话 只好是这样咯。其实我的模板上是接外部中断的。但当时修改电路板的时候不知道发什么神经,把管脚给改了,现在写程序才注意到。

出0入0汤圆

发表于 2011-3-31 23:52:11 | 显示全部楼层
回复【11楼】daicp
-----------------------------------------------------------------------

怎么实现,能说详细点吗?

出0入0汤圆

 楼主| 发表于 2011-3-31 23:53:41 | 显示全部楼层
回复【11楼】daicp
-----------------------------------------------------------------------

定时中断,那还是要等待电平的转换的,那样的话程序不就是一直在那里卡住?而且解码的准确程度还得值得思考

出0入0汤圆

发表于 2011-3-31 23:57:39 | 显示全部楼层
回复【14楼】cbmjd
-----------------------------------------------------------------------

不能满足楼主要求,意义不是很大。

出0入0汤圆

 楼主| 发表于 2011-4-1 00:02:23 | 显示全部楼层
回复【15楼】liuzhichengour
-----------------------------------------------------------------------

呵呵......我知道。

出0入0汤圆

 楼主| 发表于 2011-4-1 00:05:57 | 显示全部楼层
其实我是改了板,然后程序是按照中断的方式写的,但现在就是想知道能不能用别的IO口实现像中断那样的解码

出0入0汤圆

发表于 2011-4-1 00:11:09 | 显示全部楼层
回复【17楼】cbmjd
-----------------------------------------------------------------------

可以用定时器外部启动引脚来实现,就是用定时器模拟中断,把定时器赋值到最大值-1,然后使用外部引脚启动定时器,当有信号时定时器会溢出进入中断,实现中断功能,不过使用时注意中断前有点延时,做好补偿就可以。

出0入0汤圆

 楼主| 发表于 2011-4-1 00:16:56 | 显示全部楼层
回复【18楼】liuzhichengour
-----------------------------------------------------------------------

那应该怎么实现的?定时器赋值到最大值-1?

出0入0汤圆

发表于 2011-4-1 00:28:48 | 显示全部楼层
定时中断绝对准确灵敏,且多任务方式(也就是解码不会独点CPU),我们的程序已商用

出0入0汤圆

 楼主| 发表于 2011-4-1 00:30:29 | 显示全部楼层
回复【20楼】daicp
-----------------------------------------------------------------------

能不能给点提示啊?运用多任务?

出0入0汤圆

发表于 2011-4-1 00:32:57 | 显示全部楼层
就是做一个定时中断了,然后在定时中断检测电平高低,记数,识别码元这样了

出0入0汤圆

发表于 2011-4-1 00:35:38 | 显示全部楼层
红外信号的开头一般都有几个mS的前导信号,所以每隔1mS去检测一次这个引脚电平或许可行,没试过。

检测一次只占1mS里面的几个时钟周期,所以占CPU很少。

出0入0汤圆

 楼主| 发表于 2011-4-1 00:37:59 | 显示全部楼层
这是 搜来的 不知道行不行

//**********定时器一初始化**********
void timer1_init(void)
{
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x0E;
OCR1AL=0x10;
OCR1BH=0x00;
OCR1BL=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
}

SIGNAL(SIG_INTERRUPT0) //int0 interrupt
{
TCNT1=0;
if(CodeCnt==1)
{                // 收到第一个起始码, 准备状态转解码状态
  TCCR1B=0x01;    // 开定时器
  CodeCnt=2;
  IrTemp=0;
  MCUCR=0x03;    //第2个起始码的上升沿作为第一个同步信号
}
else
{
   if(CodeCnt>13)
    {      // 完成解码
     IrCode=IrTemp;
     while(TCNT1<889); // 延时889us
     MCUCR=0x02;   // 恢复下降沿中断
     CodeCnt=0;   // 转空闲状态
    }
    else
    {
     if(CodeCnt>1)
     {     // 解码中,共12次CodeCnt=2-13
      CodeCnt++;   // 转解码状态+1
      IrTemp<<=1;
      while(TCNT1<1320); // 延时1.33ms, 检测信号电平
      if(IrDat)
      {     // 1,下一次下降沿有效
        IrTemp|=1;
        MCUCR=0x02;
       }
    else
    {     // 0,下一次上升沿有效
     MCUCR=0x03;
    }
   }
  }
}
}

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
if(CodeCnt==0)
{             // 空闲状态转准备状态
  TCCR1B=0;    // 关定时器
  CodeCnt=1;
}
else
{              // 错误,转空闲状态
  MCUCR=0x02;   // 恢复下降沿中断
  CodeCnt=0;
  TCNT1=0;
}
}





volatile uint data0;           //前16个脉冲存放地址
volatile uint data1;           //后16个脉冲存放地址
volatile uint Flag=0;          //接收完成一帧标志位
volatile float oldFall=0,newFall=0;  //时间的先后纪录
volatile uintbitcnt=0;        //脉冲个数纪录
uchar    code;

//定时T1初始化
//系统时钟为7.3728M内频,64分频,最大定时时长483.184MS
void timer1_init(void)
{
        TCCR1B = 0x00;//停止定时器
        TIMSK |= 0x20;//中断允许
        ICR1H  = 0xFd;
        ICR1L  = 0xFd;//输入捕捉匹配值
        TCCR1A = 0x00;
        TCCR1B = 0x83;//启动定时器
}

//数据头的时间:Th=9+4.5=13.5ms
//数据“0”的时间:T0=0.565+0.56=1.125ms
//数据“1”的时间:T1=1.685+0.56=2.245ms
//定时器T1输入捕捉中断服务程序
SIGNAL(SIG_INPUT_CAPTURE1)
{
        float time=0;
        unsigned int temp=0;
        newFall=ICR1;         //读取当前时间
        time=newFall-oldFall; //计算脉冲加间隔的时间
        oldFall=newFall;      //存放上一次的时间
        if(time<0)  time=newFall-oldFall+0xffff;//定时周期交叉的情况
         temp=(unsigned int)time; //取整
        //T0的8分频,即(1.125*7372.800)/64 = 129.6us ;正负20宽范围判断
        if((temp>119) && (temp<149)) // "0"信号
        {
            temp=0;
        }
        //T1的8分频为258.624us
        else if((temp>238) && (temp<278)) //“1”信号
        {
            temp=1;
        }
        //Th的8分频为1555.2us
        else if((temp>1535) && (temp<1575)) //header头信号
        {
                bitcnt=0;
                data0=0;
                data1=0;
   
                return; //返回,等待下次开始接收
        }
        else //干扰信号
        {
            bitcnt=0;
            data0=0;
            data1=0;
            return;
        }
  
        bitcnt++;
  
        if(bitcnt<16) //开始接收前16位
        {
            data0=data0|temp;
                data0=data0<<1;
   
   
        }
        else if(bitcnt==16)
        {
            data0=data0|temp;
   
   
        }
        else if(bitcnt<32) //开始接收后16位
        {
            data1=data1|temp;
            data1=data1<<1;
   
        }
        else if(bitcnt==32) //接收完最后一位
        {
           data1=data1|temp;
           Flag=1;       //接收完一帧,标志位置1
        }
}

出0入0汤圆

发表于 2011-4-1 00:38:06 | 显示全部楼层
回复【23楼】hsztc
红外信号的开头一般都有几个ms的前导信号,所以每隔1ms去检测一次这个引脚电平或许可行,没试过。
检测一次只占1ms里面的几个时钟周期,所以占cpu很少。
-----------------------------------------------------------------------

大约是这个意思了

出0入0汤圆

发表于 2011-4-1 00:43:44 | 显示全部楼层
回复【24楼】cbmjd
-----------------------------------------------------------------------

这个单任务的,因为里面有死等的语句

程序一定不能在某个地方等待,否则这个单片机只解码不能做其他事了

出0入0汤圆

 楼主| 发表于 2011-4-1 00:44:59 | 显示全部楼层
回复【23楼】hsztc
-----------------------------------------------------------------------

回复【25楼】daicp
-----------------------------------------------------------------------

应该可以吧 但那样也要不断的检测吧,程序会不会一直卡在 定时检测上?

出0入0汤圆

 楼主| 发表于 2011-4-1 00:47:30 | 显示全部楼层
哎!困了 回去休息先,明天再想。谢谢你们啊!

出0入0汤圆

发表于 2011-4-1 02:53:58 | 显示全部楼层
先说说 接在哪个脚上把

出0入0汤圆

 楼主| 发表于 2011-4-1 16:24:25 | 显示全部楼层
回复【29楼】jrcsh 邪恶的小会会
-----------------------------------------------------------------------
不好意思啊!昨晚还要走半个小时才能回到宿舍 所以.......
那个是接到P1^7脚上的

出0入0汤圆

发表于 2011-4-1 16:29:13 | 显示全部楼层
用中断做是正确的 你的编码格式怎样的 常用红外遥控器对时序的要求并不是特别严格

出0入0汤圆

发表于 2011-4-1 16:30:18 | 显示全部楼层
用io口做查询就需要单片机速度快些

出0入0汤圆

 楼主| 发表于 2011-4-1 16:51:01 | 显示全部楼层
回复【32楼】pang7
-----------------------------------------------------------------------

我用的单片机是89C52 你说的查询是不是也是一直在那里等待电平的转换?

出0入0汤圆

 楼主| 发表于 2011-4-1 16:54:40 | 显示全部楼层
回复【31楼】pang7
-----------------------------------------------------------------------

编码时主要判断电平有没有达到9+4.5ms 如果是,则在那里等待,但问题就出现在这里了,这样单片机就一直在等待,别的功能完全没有用

出0入0汤圆

发表于 2011-4-1 17:50:45 | 显示全部楼层
除用中断还没有更好的办法。
刚做完,试过定时中断,理论讲没问题。实测不可用。
还是外触发中断。上沿触发。效果很好。
我想外中断加定时中断效率会很高。
我只用外中断,效率不是特高,但效果不错。20us测一次,0的时候是24-25次。1的时候是77-78。前导高电平108-110。
总体用时应该是20-30ms完成一次解码。整个周整期是108ms.

出0入0汤圆

发表于 2011-4-1 17:53:19 | 显示全部楼层
上面的代码看了一下没明白。捕获是如何工作没搞明白。哪位大侠能讲讲吗?
应该用定时器效率会更高。

出0入0汤圆

发表于 2011-4-1 17:53:31 | 显示全部楼层
不需要完全等待 比方说100us查询一次 对于ms级别来说 差100us无所谓的

出0入0汤圆

发表于 2011-4-1 18:20:06 | 显示全部楼层
我也考虑过用任意脚 做红外脚,思路就是用定时器定时的检测IO口的电平,记录高低电平的时差
在解码。不过一直没有试验。
类似从异步串口的数据接收。

出0入0汤圆

 楼主| 发表于 2011-4-1 20:52:44 | 显示全部楼层
是用中断加定时器比较好 我之前也是这样写的 但是现在就想弄一下其他口的方法 比如查询法什么的 但一直没有调出来

出0入0汤圆

发表于 2011-4-1 22:28:38 | 显示全部楼层
用心看下我下面所说的你就知道怎么用普通IO做红外了

定时器做个100us的中断,有中断就去查下IO的状态,记录高低电平(一般记录信号的电平)用寄存器来记。找出同步头

出0入0汤圆

发表于 2012-4-13 11:10:45 | 显示全部楼层
本帖最后由 hpdell 于 2012-4-13 11:11 编辑

看看这个地址的博客,应该可以的
http://hi.baidu.com/%BD%AD%BA%FE ... dc77d851da4b98.html

出0入0汤圆

发表于 2012-4-13 21:34:48 | 显示全部楼层
不建议这样做
否则单片机再做别的就没时间了
如果还有动态扫描显示的话
那就更玄乎啦

出0入0汤圆

发表于 2012-4-13 22:15:42 | 显示全部楼层
用定时器采生一个125US的中断。煞后计算遥控码的时间,最后才解码,这样不会影响了

出0入0汤圆

发表于 2012-4-14 10:52:02 | 显示全部楼层
定时250us或者100us,去扫描IO口计数即可

出0入0汤圆

发表于 2012-4-14 12:18:22 | 显示全部楼层
mark  cool

出0入0汤圆

发表于 2012-4-14 12:42:54 | 显示全部楼层
用定时器对IO采样

出0入0汤圆

发表于 2012-4-14 14:20:30 | 显示全部楼层
不用外部的话,我觉得是不是单片机可累的啊。

出0入0汤圆

发表于 2012-4-16 17:24:08 | 显示全部楼层
duxingkei 发表于 2011-4-1 18:20
我也考虑过用任意脚 做红外脚,思路就是用定时器定时的检测IO口的电平,记录高低电平的时差
在解码。不过一 ...

这个可以的,我一直都这样用,不过红外还是无线

出0入0汤圆

发表于 2012-4-16 17:57:21 | 显示全部楼层
configure one of the timers as a counter (to count input pulse) and set the counter to -1.

so the counter overflows on the very next input pulse -> you got an external interrupt.

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

本版积分规则

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

GMT+8, 2024-8-27 01:15

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

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