AVR同时开两个中断冲突问题
ATMEGA64同时打开INT4和INT5,单个测试两个中断没问题,但是两个一起打开就有一个很不灵敏,有没有熟悉AVR的朋友交流一下 真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。 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;
}
LDMega 发表于 2014-3-31 08:51
真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。 ...
能给帮帮忙指点一下吗,我弄的焦头烂额一直没解决这个问题 在上班,下班了看下。 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;
}
} alias 发表于 2014-3-31 11:23
IR_Data 与 IR_data_int4 不都是 array 吗,看不明白如何能这样清零?
我没细考虑怎么清零,给一下指点吧。此外我的程序没有用到这两个函数, 我是指为什么用 IR_data=0,而不是写成 IR_data=0? alias 发表于 2014-3-31 17:50
我是指为什么用 IR_data=0,而不是写成 IR_data=0?
哦,笔误写错了,但是我没使用 看了下,没发现中断设置有什么问题,只是 //中断4 后背#pragma interrupt_handler int0_isr:6 void int0_isr(void) 这里应该规范点吧。INT5就没这个问题。以我个人理解,应该和芯片没关系,最大可能跟你的程序结构有关系,就是算法问题了。我的应用里都是两个一组中断同时中断(当然不是绝对同时),只是不同组的优先顺序自己要先整理下,同组的就没关系了,那一点点时间差在我的项目里没影响。 LDMega 发表于 2014-3-31 21:42
看了下,没发现中断设置有什么问题,只是 //中断4 后背#pragma interrupt_handler int0_isr:6 void in ...
我测试了成,单独测试中断接收是没有问题的,但是两个中断同时开启红外接收就反应很慢,我进一个中断把另一个中断给关掉,发现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 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;
}
}
}
}
}
LDMega 发表于 2014-3-31 08:51
真巧,我现在手上的项目用的是ATMega64A,用完所有INTx中断,没碰到你说的问题。 ...
我查了atmega64的中断资料,中断优先级不可以设置是吧,中断号越低优先级越高对吧。我用的中断4和中断5同时接收红外,发现两个中断有干扰,优先级没有起作用,我想请教一下如果两个中断同时触发中断处理函数会同时执行吗, 基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。或者说你一定要这两个中断同时触发?不理解。即使是同时触发,肯定是先执行INT4中断,然后再执行INT5中断。即使是这样以几MHz速度运行的AVR也不会对红外解码产生多大的延时,可以说微乎其微。你所说的优先级没有起作用,应当是你程序结构产生了影响。 >>基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。
外来的中断讯号,不同的讯号当然有可能会同时出现,这和硬件设计一点关系都没有。
要小心分清中断触发和中断处理服务,前者是能同时出现,而后者只能单一进行。 LDMega 发表于 2014-4-3 18:57
基本上不存在同时触发这种状况吧,如果出现这种情况,那是你硬件设计不合理吧。或者说你一定要这两个中断同 ...
我解决了这个问题,确实是我的算法问题,两个中断会同时工作
页:
[1]