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

2020-02-04 09:12发布

要把红外接收头的引脚接在单片机(除了外部中断引脚)的任意IO口,该怎么实现解码啊?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
cbmjd
1楼-- · 2020-02-06 21:54
回复【18楼】liuzhichengour
-----------------------------------------------------------------------

那应该怎么实现的?定时器赋值到最大值-1?
daicp
2楼-- · 2020-02-07 02:56
 精彩回答 2  元偷偷看……
cbmjd
3楼-- · 2020-02-07 06:16
回复【20楼】daicp
-----------------------------------------------------------------------

能不能给点提示啊?运用多任务?
daicp
4楼-- · 2020-02-07 07:49
就是做一个定时中断了,然后在定时中断检测电平高低,记数,识别码元这样了
hsztc
5楼-- · 2020-02-07 13:44
红外信号的开头一般都有几个mS的前导信号,所以每隔1mS去检测一次这个引脚电平或许可行,没试过。

检测一次只占1mS里面的几个时钟周期,所以占CPU很少。
cbmjd
6楼-- · 2020-02-07 19:43
这是 搜来的 不知道行不行

//**********定时器一初始化**********
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
        }
}

一周热门 更多>