搜索
bottom↓
回复: 15

AVR同时开两个中断冲突问题

[复制链接]

出0入0汤圆

发表于 2014-3-31 08:44:26 | 显示全部楼层 |阅读模式
ATMEGA64同时打开INT4和INT5,单个测试两个中断没问题,但是两个一起打开就有一个很不灵敏,有没有熟悉AVR的朋友交流一下

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

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

出0入0汤圆

发表于 2014-3-31 08:51:05 来自手机 | 显示全部楼层
真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。

出0入0汤圆

 楼主| 发表于 2014-3-31 09:35:33 | 显示全部楼层
LDMega 发表于 2014-3-31 08:51
真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。 ...

看到救星了呵呵呵。我是用INT4和INT5用做两路红外接收,我写的程序比较简单,方便的话给看一下,或者我哪里做的不对给指点一下


#include"main.h"
#include "g_para.h"
#define uchar unsigned char
#define uint  unsigned int

uchar IR_end        = 0;        //红外
uchar IR_count      = 0;
uchar IR_data[40]  = {0};
uchar IR_data_sp   = 0;
uchar IR_code[5]   = {0};
uchar F_Front_Int5 = 0;
uchar F_Back_Int4  = 0;

uchar IR_Recive_int4 = 0;        //红外
uchar IR_count_int4 = 0;
uchar IR_data_int4[40] = {0};
uchar IR_int4_sp = 0;
uchar IR_code_int4[5] = {0};

//static uchar F_Front_Int5 = 0;
//static uchar F_Back_Int4  = 0;
//static uchar first=0;
// 解码函数
//先发低位
uchar ir_to_char(uchar *ptr)
{
   uchar i;
   uchar data = 0;
   for(i=0;i<8;i++)
   {
      if(ptr > 16)
             data |= (1<<(i));
      else
             data &= (~(1<<(i)));          
   }
   return data;         
}

void timer0(void)                 //定时器0初始化10K Hz
{
SREG   |=  0X80;
TCCR0   =  0x00;                 //stop
ASSR    =  0x00;                 //set async mode
TCNT0  |=  0x38;                 //set count
OCR0   |=  0xC8;
TCCR0  |=  0x02;                 //start timer
TIMSK  |=  BIT(TOIE0);           //溢出中断时能
}

#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{   
   TCNT0 = 0x3a; //reload counter value   
   IR_count++;  
   if(IR_count >= 0xfe)
   {
      IR_count = 0xfc;
   }        
  
}

void int4_init(void)                 //外部中断初始化
{
  DDRE  &= ~BIT(PE4);                //此处必须把int4引脚设置为输入带上拉
  PORTE |= BIT(PE4);  
  DDRE  &= ~BIT(PE5);                //此处必须把int5引脚设置为输入带上拉
  PORTE |= BIT(PE5);
  CLI();
  MCUCR  = 0x00;
  EICRA  = 0x00;    //extended ext ints
  EICRB  = 0x0a;   //extended ext ints
  EIMSK  =  0x30;
  TIMSK  = 0x00;   //timer interrupt sources
  ETIMSK = 0x00;   //extended timer interrupt sources  
  SEI();           //re-enable interrupts
}

void CLR_RX_int5(void)
{
   uchar i;
   for(i=0; i<40; i++)
   {
      IR_data = 0x00;
   }
  
}

void CLR_RX_int4(void)
{
   uchar i;
   for(i=0; i<40; i++)
   {
      IR_data_int4 = 0x00;
   }
  
}
//红外的解析 前胸接收
void ir_body_receive(void)
{
    uchar i;                                        //清空红外接收缓冲区
    if(IR_end == 1)
        {
           IR_end = 0;
           if((IR_count > 0xf0)&&(IR_count <= 0xff))    //重复吗
           {
              IR_count = 0;
                  IR_data_sp = 0;                           //数据开始               
           }
           else if((IR_count > 0x25)&&(IR_count < 0x35))//判断引导码
           {  
              IR_count = 0;
                  IR_data_sp = 0;
           }
           else
           {
              IR_data[IR_data_sp++] = IR_count;
                  IR_count = 0;
                  if(IR_data_sp >= 32)
                  {
                     
                     IR_data_sp = 0;
                         IR_code[0] = ir_to_char(&IR_data[0]);
                         IR_code[1] = ir_to_char(&IR_data[8]);
                         IR_code[2] = ir_to_char(&IR_data[16]);
                         IR_code[3] = ir_to_char(&IR_data[24]);                       
                       
                        if(( IR_code[0] == 137) && (IR_code[1] == 54) && (IR_code[2] == (~IR_code[3])) )
                         {         
                         //    EIMSK  =  0x30;                                                           
                                 
                                 setmotr_1;
                               system.FGmotor_cnts = 150;       //电机振动时间                                                                   
                         }                                        
              }
           }               
        }       
}


//红外的解析 后背接收
void ir_receive_int4(void)
{
    uchar i;                                        //清空红外接收缓冲区
    if(IR_Recive_int4 == 1)
        {
           IR_Recive_int4 = 0;
           if((IR_count > 0xf0)&&(IR_count <= 0xff))    //重复吗
           {
              IR_count = 0;
                  IR_int4_sp = 0;                           //数据开始               
           }
           else if((IR_count > 0x25)&&(IR_count < 0x35))//判断引导码
           {  
              IR_count = 0;
                  IR_int4_sp = 0;
           }
           else
           {
              IR_data_int4[IR_int4_sp++] = IR_count;
                  IR_count = 0;
                  if(IR_int4_sp >= 32)
                  {
                     
                     IR_int4_sp = 0;
                         IR_code_int4[0] = ir_to_char(&IR_data_int4[0]);
                         IR_code_int4[1] = ir_to_char(&IR_data_int4[8]);
                         IR_code_int4[2] = ir_to_char(&IR_data_int4[16]);
                         IR_code_int4[3] = ir_to_char(&IR_data_int4[24]);                       
                        if(( IR_code_int4[0] == 137) && (IR_code_int4[1] == 54) && (IR_code_int4[2] == (~IR_code_int4[3])) )
                         {         
                //             EIMSK  =  0x30;       
                                 clpled;            
                                 setmotr_2;
                               system.FGmotor_cnts = 150;       //电机振动时间                                               
                         }                                                        
              }
           }               
    }       
}               
                                    //中断4 后背
#pragma interrupt_handler int0_isr:6  
void int0_isr(void)
{
   IR_Recive_int4 = 1;   
}

                                             //中断5 前胸
#pragma interrupt_handler int5_isr:7           
void int5_isr(void)
{   
   IR_end    = 1;          
}

出0入0汤圆

 楼主| 发表于 2014-3-31 09:51:07 | 显示全部楼层
LDMega 发表于 2014-3-31 08:51
真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。 ...

能给帮帮忙指点一下吗,我弄的焦头烂额一直没解决这个问题

出0入0汤圆

发表于 2014-3-31 10:56:39 来自手机 | 显示全部楼层
在上班,下班了看下。

出0入0汤圆

发表于 2014-3-31 11:23:53 | 显示全部楼层
IR_Data[40] 与 IR_data_int4[40] 不都是 array 吗,看不明白如何能这样清零?

  1. void CLR_RX_int5(void)
  2. {
  3.    uchar i;
  4.    for(i=0; i<40; i++)
  5.    {
  6.       IR_data = 0x00;
  7.    }
  8.   
  9. }

  10. void CLR_RX_int4(void)
  11. {
  12.    uchar i;
  13.    for(i=0; i<40; i++)
  14.    {
  15.       IR_data_int4 = 0x00;
  16.    }
  17.   
  18. }
复制代码

出0入0汤圆

 楼主| 发表于 2014-3-31 13:35:09 | 显示全部楼层
alias 发表于 2014-3-31 11:23
IR_Data[40] 与 IR_data_int4[40] 不都是 array 吗,看不明白如何能这样清零?

我没细考虑怎么清零,给一下指点吧。此外我的程序没有用到这两个函数,

出0入0汤圆

发表于 2014-3-31 17:50:20 | 显示全部楼层
我是指为什么用 IR_data=0,而不是写成 IR_data[i]=0?

出0入0汤圆

 楼主| 发表于 2014-3-31 19:06:04 | 显示全部楼层
alias 发表于 2014-3-31 17:50
我是指为什么用 IR_data=0,而不是写成 IR_data=0?

哦,笔误写错了,但是我没使用

出0入0汤圆

发表于 2014-3-31 21:42:08 | 显示全部楼层
看了下,没发现中断设置有什么问题,只是 //中断4 后背  #pragma interrupt_handler int0_isr:6    void int0_isr(void) 这里应该规范点吧。INT5就没这个问题。以我个人理解,应该和芯片没关系,最大可能跟你的程序结构有关系,就是算法问题了。我的应用里都是两个一组中断同时中断(当然不是绝对同时),只是不同组的优先顺序自己要先整理下,同组的就没关系了,那一点点时间差在我的项目里没影响。

出0入0汤圆

 楼主| 发表于 2014-4-1 11:26:17 | 显示全部楼层
LDMega 发表于 2014-3-31 21:42
看了下,没发现中断设置有什么问题,只是 //中断4 后背  #pragma interrupt_handler int0_isr:6    void in ...

我测试了成,单独测试中断接收是没有问题的,但是两个中断同时开启红外接收就反应很慢,我进一个中断把另一个中断给关掉,发现int4和int5交替接收,肯就像你说的我的算法有问题,不知道你用过红外解码程序没,给看看我算法的问题

出0入0汤圆

 楼主| 发表于 2014-4-1 11:26:58 | 显示全部楼层

#include"main.h"
#include "g_para.h"
#define uchar unsigned char
#define uint  unsigned int

uchar IR_end        = 0;        //红外
uchar IR_count      = 0;
uchar IR_data[40]  = {0};
uchar IR_data_sp   = 0;
uchar IR_code[5]   = {0};
uchar F_Front_Int5 = 0;
uchar F_Back_Int4  = 0;

uchar IR_Recive_int4 = 0;        //红外
uchar IR_count_int4 = 0;
uchar IR_data_int4[40] = {0};
uchar IR_int4_sp = 0;
uchar IR_code_int4[5] = {0};

//static uchar F_Front_Int5 = 0;
//static uchar F_Back_Int4  = 0;
//static uchar first=0;
// 解码函数
//先发低位
uchar ir_to_char(uchar *ptr)
{
   uchar i;                     
   uchar data = 0;
   for(i=0;i<8;i++)
   {
      if(ptr[i] > 16)
             data |= (1<<(i));
      else
             data &= (~(1<<(i)));          
   }
   return data;         
}

void timer0(void)                 //定时器0初始化10K Hz
{
SREG   |=  0X80;
TCCR0   =  0x00;                 //stop
ASSR    =  0x00;                 //set async mode
TCNT0  |=  0x38;                 //set count
OCR0   |=  0xC8;
TCCR0  |=  0x02;                 //start timer
TIMSK  |=  BIT(TOIE0);           //溢出中断时能
}

#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{   
   TCNT0 = 0x3a; //reload counter value   
   IR_count++;  
   if(IR_count >= 0xfe)
   {
      IR_count = 0xfc;
   }        
  
}

void int4_init(void)                 //外部中断初始化
{
  DDRE  &= ~BIT(PE4);                //此处必须把int4引脚设置为输入带上拉
  PORTE |= BIT(PE4);  
  DDRE  &= ~BIT(PE5);                //此处必须把int5引脚设置为输入带上拉
  PORTE |= BIT(PE5);
  CLI();
  MCUCR  = 0x00;
  EICRA  = 0x00;    //extended ext ints
  EICRB  = 0x0a;   //extended ext ints
  EIMSK  =  0x30;
  TIMSK  = 0x00;   //timer interrupt sources
  ETIMSK = 0x00;   //extended timer interrupt sources  
  SEI();           //re-enable interrupts
}


//红外的解析 前胸接收
void ir_body_receive(void)
{
    uchar i;                                        //清空红外接收缓冲区
    if(IR_end == 1)
        {
           IR_end = 0;
           if((IR_count > 0xf0)&&(IR_count <= 0xff))    //重复吗
           {
              IR_count = 0;
                  IR_data_sp = 0;                           //数据开始               
           }
           else if((IR_count > 0x25)&&(IR_count < 0x35))//判断引导码
           {  
              IR_count = 0;
                  IR_data_sp = 0;
           }
           else
           {
              IR_data[IR_data_sp++] = IR_count;
                  IR_count = 0;
                  if(IR_data_sp >= 32)
                  {                     
                     IR_data_sp = 0;
                         IR_code[0] = ir_to_char(&IR_data[0]);
                         IR_code[1] = ir_to_char(&IR_data[8]);
                         IR_code[2] = ir_to_char(&IR_data[16]);
                         IR_code[3] = ir_to_char(&IR_data[24]);                       
                       
                        if(( IR_code[0] == 137) && (IR_code[1] == 54) && (IR_code[2] == (~IR_code[3])) )
                         {
                             if(F_Front_Int5 == 1)
                                 {
                                    F_Front_Int5 = 0;
                                        F_Back_Int4  = 0;
                                    setmotr_2;
                 }
                                 if(F_Back_Int4  == 1 )
                                 {
                                    setmotr_1;
                                  F_Back_Int4  = 0;
                                        F_Front_Int5 = 0;
                                 }
                                 system.FGmotor_cnts = 150;       //电机振动时间       
                                 EIMSK  =  0x30;       
                                 for(i=0; i<40; i++)IR_data[i]=0x00;                                           
                         }                                        
              }
           }               
        }       
}


#pragma interrupt_handler int4_isr:iv_INT4
void int4_isr(void)
{
//external interupt on INT4
EIMSK        = 0x10;
F_Back_Int4  = 1;
F_Front_Int5 = 0;
//IR_end       = 1;
IR_Recive_int4 = 1;
}


#pragma interrupt_handler int5_isr:iv_INT5
void int5_isr(void)
{
  //external interupt on INT5
  EIMSK          = 0x20;
  F_Front_Int5   = 1;
  F_Back_Int4    = 0;
// IR_end         = 1;
  IR_Recive_int4 = 1;  
}



//红外的解析 前胸接收
void ir_receive_int4(void)
{
    uchar i;                                        //清空红外接收缓冲区
    if(IR_Recive_int4 == 1)
        {
           IR_Recive_int4 = 0;
           if((IR_count > 0xf0)&&(IR_count <= 0xff))    //重复吗
           {
              IR_count = 0;
                  IR_data_sp = 0;                           //数据开始               
           }
           else if((IR_count > 0x25)&&(IR_count < 0x35))//判断引导码
           {  
              IR_count = 0;
                  IR_data_sp = 0;
           }
           else
           {
              IR_data[IR_data_sp++] = IR_count;
                  IR_count = 0;
                  if(IR_data_sp >= 32)
                  {
                     
                     IR_data_sp = 0;
                         IR_code[0] = ir_to_char(&IR_data[0]);
                         IR_code[1] = ir_to_char(&IR_data[8]);
                         IR_code[2] = ir_to_char(&IR_data[16]);
                         IR_code[3] = ir_to_char(&IR_data[24]);                       
                       
                        if(( IR_code[0] == 137) && (IR_code[1] == 54) && (IR_code[2] == (~IR_code[3])) )
                         {
                                 if(F_Front_Int5 == 1)
                                 {
                                    F_Front_Int5 = 0;
                                        F_Back_Int4  = 0;
                                    setmotr_2;
                 }
                                 if(F_Back_Int4  == 1 )
                                 {
                                    setmotr_1;
                                  F_Back_Int4  = 0;
                                        F_Front_Int5 = 0;
                                 }
                                 system.FGmotor_cnts = 150;       //电机振动时间       
                                 EIMSK  =  0x30;       
                                 for(i=0; i<40; i++)IR_data[i]=0x00;                                   
                         }                                        
              }
           }               
        }       
}



出0入0汤圆

 楼主| 发表于 2014-4-3 09:43:50 | 显示全部楼层
LDMega 发表于 2014-3-31 08:51
真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。 ...

我查了atmega64的中断资料,中断优先级不可以设置是吧,中断号越低优先级越高对吧。我用的中断4和中断5同时接收红外,发现两个中断有干扰,优先级没有起作用,我想请教一下如果两个中断同时触发中断处理函数会同时执行吗,

出0入0汤圆

发表于 2014-4-3 18:57:43 | 显示全部楼层
基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。或者说你一定要这两个中断同时触发?不理解。即使是同时触发,肯定是先执行INT4中断,然后再执行INT5中断。即使是这样以几MHz速度运行的AVR也不会对红外解码产生多大的延时,可以说微乎其微。你所说的优先级没有起作用,应当是你程序结构产生了影响。

出0入0汤圆

发表于 2014-4-4 09:04:32 | 显示全部楼层
>>基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。

外来的中断讯号,不同的讯号当然有可能会同时出现,这和硬件设计一点关系都没有。

要小心分清中断触发和中断处理服务,前者是能同时出现,而后者只能单一进行。

出0入0汤圆

 楼主| 发表于 2014-4-5 13:58:52 | 显示全部楼层
LDMega 发表于 2014-4-3 18:57
基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。或者说你一定要这两个中断同 ...

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

本版积分规则

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

GMT+8, 2024-8-26 13:16

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

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