关于使用AVR mega64的中断方式对PT2262解码的疑惑?

2019-07-15 07:40发布

本人初次接触AVR,在使用MEGA64对无线编码器PT2262进行软件解码的时候,明明接收到字码了,但是解码时碰到几个问题,一是解码反应异常,按下遥控器的时候硬件有时反应有时不反应,有时没按下也出现反应。二是没法接收第二组字码,因为要保证安全性,项目要求接收到2组相同字码才进行处理,但是程序却总是跑不到!
单片机晶振频率:4Mhz。
编码器震荡电阻:3.3M欧。  
用示波器观察得到同步码起始高电平持续时间约为360us,低电平10500us.数据码“1”高电平持续为1ms,低电平持续为200us.“0”反之!
相关代码如下:(开发环境:IAR     (iar for avr))
1.寄存器设置:
  1.   EICRA=0x0E; //INT0为下降沿触发 ,INT1为上升沿触发 //CAN中断下降沿触发比较好用,无线呼叫由上升沿触发
  2.    EICRB=0x00;
  3.    EIMSK=0x03; //外部中断INT0,外部中断1使能
复制代码2.定时器中断为:
  1. #pragma vector=tiMER3_OVF_vect    //中断入口地址
  2. __interrupt void timer3_ovf_isr(void)
  3. {
  4. #if defined(main_can)  //主机用于对无线呼叫器的外来脉冲进行时长计数
  5.   
  6.    TCNT3H=0xFF;      //定时器值(100us)4M主时钟8分频后100us的定时初值
  7.    TCNT3L=0xCD;
  8.    
  9.    if((PIND&0x02)==0x02)         //如果引脚为高电平
  10.     Wireless_Rec.high_Counter++;
  11.    else if((PIND&0x02)==0)      //引脚低电平
  12.     Wireless_Rec.low_Counter++;
  13.    
  14.    if(Wireless_Rec.high_Counter>=240)   //万一计数溢出情况下
  15.     {
  16.       Wireless_Rec.high_Counter=0;        
  17.     }
  18.    else if(Wireless_Rec.low_Counter>=240)
  19.     {
  20.       Wireless_Rec.low_Counter=0;
  21.     }
  22.    
  23. #else                 //分机用于数码管显示
  24.    TCNT3H=Timer3ValueH;      //定时器值
  25.    TCNT3L=Timer3ValueL;
  26.    Smg.Display();            //数码管显示
  27. #endif
  28. }
复制代码

3.中断服务函数:
  1. // 外部中断1,设为无线呼叫接收中断
  2. #pragma vector=INT1_vect           //中断入口地址
  3. __interrupt void ext_int1_isr(void)
  4. {
  5. #if defined(main_can)   //主机
  6.   
  7.   static unsigned char i=0;
  8.   static unsigned char status = 0;         //接收状态
  9.   static char startflag=0;                //开始储存脉宽标志位
  10.   

  11.   if(startflag)                            //一开始有效时这是字码的第二个上升沿,这时计数得到的是同步码的电平脉宽。同理可得数据码!
  12.   {
  13.    switch(status)
  14.       {
  15.         case 0:
  16.                 if( ((Wireless_Rec.high_Counter>2)&&(Wireless_Rec.high_Counter<5))&&((Wireless_Rec.low_Counter>80)&&(Wireless_Rec.low_Counter<120)))
  17.                 {
  18.                   Wireless_Rec.high_Counter=0;
  19.                   status = 1;          //接收到同步码(高低电平约为400和1100us)
  20.                 }
  21.                 else
  22.                 {
  23.                   Wireless_Rec.high_Counter=0;             //高电平计数清零(每来一次上升沿清零一次)
  24.                   Wireless_Rec.low_Counter=0;              //低电平计数清零;       //防止杂乱电波高电平触发外部中断的影响
  25.                 //  startflag = 0;                           //清计数,继续接收!(防止杂乱电波高电平触发外部中断的影响)
  26.                   status = 0;                             //继续接收
  27.                 }
  28.                 break;

  29.         case 1:              
  30.                 Wireless_Rec.wireless_data[i] = Wireless_Rec.high_Counter;    //储存高电平
  31.                 Wireless_Rec.high_Counter=0;
  32.                 i++;
  33.                 if( i == 23 )      //已接受足够字节数(0-23,一共24 bit的数据)
  34.                 {
  35.                   Wireless_Rec.rec_flag = 1;            //接收成功
  36.                   status = 0;                      //回到初始接收状态                  
  37.                   startflag=0;                      //清零开始标志位
  38.                   i=0;
  39.                                    
  40.                   EIMSK=0x01;                    //屏蔽外部中断1
  41.                   TASK_EN(JIEMA);                  //开启解码任务
  42.                 }
  43.                 break;

  44.         default:  break;

  45.       }
  46.   }
  47.   else                                   //接收码的第一个上升沿作为开始接收脉宽检测的启动标志
  48.   {
  49.    Wireless_Rec.high_Counter=0;             //高电平计数清零(每来一次上升沿清零一次)
  50.    Wireless_Rec.low_Counter=0;              //低电平计数清零
  51.    startflag = 1;                         //开始处理标志位置1
  52.   }
  53.   
  54.   
  55. #else       //从机                       

  56. #endif
  57. }
复制代码4.解码函数:
  1. //PT2262解码
  2. void data_decode(void)            //无线数据解码
  3. {
  4. unsigned char i,cord;
  5. unsigned long value;
  6. unsigned long lastvalue=0x00201314;      //设置比较值
  7. if(Wireless_Rec.rec_flag)     //接收完毕
  8. {
  9. // Relay2_closure;           //测试用,有反应,但是不灵敏。
  10.   for(i=0;i<24;i++)
  11.   {
  12.    cord=Wireless_Rec.wireless_data[i];
  13.    if(cord>8)  value|=0x00800000;               //脉宽大于100us*8=800us,加上堆栈出栈时间,能够大于这个时间说明是逻辑电平“1”。
  14.    value>>=1;
  15.   }
  16.   if(i>=24)
  17.   {   
  18.    if(value==lastvalue)                       //确保接收到2次同样的字码
  19.     {
  20.      //  Relay1_closure;        //继电器闭合(test)  程序跑不到这里
  21.        Wireless_Rec.Success=1;                             //接收成功
  22.        PT2262Code=value;                      //保存最新数据,解码成功
  23.        Wireless_Rec.rec_flag=0;               //清除接收成功标志位
  24.     }
  25.    else
  26.    {
  27.      Relay1_closure;        //继电器闭合(test)  //有反应,但是不灵敏
  28.      lastvalue=value;                          //否则保存最新的一组数据,继续解码
  29.      Wireless_Rec.rec_flag=0;                    //清除标志位,继续接收
  30.      EIFR=(1<<INTF1);                           //在重新使能外部中断1之前要先清标志位     
  31.      EIMSK=0x03;                        //重新开启外部中断1屏蔽位,继续接收下一组字码。
  32.    }
  33.   }
  34. }
  35. if(Wireless_Rec.Success)                              
  36. {
  37. // deal_data( );                               //转到函数处理
  38. }
  39. else
  40. {
  41.   Wireless_Rec.rec_flag=0;                    //清除标志位,继续接收
  42.   EIFR=(1<<INTF1);                        //在重新使能外部中断1之前要先清标志位  
  43.   EIMSK=0x03;                        //打开屏蔽位,继续接收下一组字码。
  44. }
  45. TASK_DISEN(JIEMA);                         //关闭自己
  46. }
复制代码因为接收都无法得到两次相同的字码,所以一直都没法转到处理函数。但我觉得程序没问题了呀,为什么效果总是不理想?(本人编程水平不怎样,万望海涵)








0条回答

一周热门 更多>