陶新成 发表于 2014-3-31 08:44:26

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

ATMEGA64同时打开INT4和INT5,单个测试两个中断没问题,但是两个一起打开就有一个很不灵敏,有没有熟悉AVR的朋友交流一下

LDMega 发表于 2014-3-31 08:51:05

真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。

陶新成 发表于 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 uintunsigned int

uchar IR_end      = 0;      //红外
uchar IR_count      = 0;
uchar IR_data= {0};
uchar IR_data_sp   = 0;
uchar IR_code   = {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 = {0};
uchar IR_int4_sp = 0;
uchar IR_code_int4 = {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_count;
                  IR_count = 0;
                  if(IR_data_sp >= 32)
                  {
                     
                     IR_data_sp = 0;
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);                       
                       
                        if(( IR_code == 137) && (IR_code == 54) && (IR_code == (~IR_code)) )
                       {       
                       //    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_count;
                  IR_count = 0;
                  if(IR_int4_sp >= 32)
                  {
                     
                     IR_int4_sp = 0;
                       IR_code_int4 = ir_to_char(&IR_data_int4);
                       IR_code_int4 = ir_to_char(&IR_data_int4);
                       IR_code_int4 = ir_to_char(&IR_data_int4);
                       IR_code_int4 = ir_to_char(&IR_data_int4);                       
                        if(( IR_code_int4 == 137) && (IR_code_int4 == 54) && (IR_code_int4 == (~IR_code_int4)) )
                       {       
                //             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;          
}

陶新成 发表于 2014-3-31 09:51:07

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

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

LDMega 发表于 2014-3-31 10:56:39

在上班,下班了看下。

alias 发表于 2014-3-31 11:23:53

IR_Data 与 IR_data_int4 不都是 array 吗,看不明白如何能这样清零?

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;
   }

}

陶新成 发表于 2014-3-31 13:35:09

alias 发表于 2014-3-31 11:23
IR_Data 与 IR_data_int4 不都是 array 吗,看不明白如何能这样清零?

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

alias 发表于 2014-3-31 17:50:20

我是指为什么用 IR_data=0,而不是写成 IR_data=0?

陶新成 发表于 2014-3-31 19:06:04

alias 发表于 2014-3-31 17:50
我是指为什么用 IR_data=0,而不是写成 IR_data=0?

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

LDMega 发表于 2014-3-31 21:42:08

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

陶新成 发表于 2014-4-1 11:26:17

LDMega 发表于 2014-3-31 21:42
看了下,没发现中断设置有什么问题,只是 //中断4 后背#pragma interrupt_handler int0_isr:6    void in ...

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

陶新成 发表于 2014-4-1 11:26:58


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

uchar IR_end      = 0;      //红外
uchar IR_count      = 0;
uchar IR_data= {0};
uchar IR_data_sp   = 0;
uchar IR_code   = {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 = {0};
uchar IR_int4_sp = 0;
uchar IR_code_int4 = {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 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_count;
                  IR_count = 0;
                  if(IR_data_sp >= 32)
                  {                     
                     IR_data_sp = 0;
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);                       
                       
                        if(( IR_code == 137) && (IR_code == 54) && (IR_code == (~IR_code)) )
                       {
                             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=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_count;
                  IR_count = 0;
                  if(IR_data_sp >= 32)
                  {
                     
                     IR_data_sp = 0;
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);
                       IR_code = ir_to_char(&IR_data);                       
                       
                        if(( IR_code == 137) && (IR_code == 54) && (IR_code == (~IR_code)) )
                       {
                               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=0x00;                                 
                       }                                      
              }
           }               
        }       
}



陶新成 发表于 2014-4-3 09:43:50

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

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

LDMega 发表于 2014-4-3 18:57:43

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

alias 发表于 2014-4-4 09:04:32

>>基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。

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

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

陶新成 发表于 2014-4-5 13:58:52

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

我解决了这个问题,确实是我的算法问题,两个中断会同时工作
页: [1]
查看完整版本: AVR同时开两个中断冲突问题