中易网

avr单片机 在中断函数了改变全局变变量的值,发生很奇怪的事情,在这里向各位高手请教了,谢谢,源程序如

答案:6  悬赏:70  
解决时间 2021-02-21 04:49
avr单片机 在中断函数了改变全局变变量的值,发生很奇怪的事情,在这里向各位高手请教了,谢谢,源程序如
最佳答案
以下是我使用WINAVR+AVR Studio编译,程序如下:

#include
#include
#include

#defineF_CPU 16000000UL
#include

volatile unsigned int i=0;

void port_init(void)
{
PORTA = 0xF0;

DDRA= 0xFF;
PORTB = 0x00;
DDRB= 0x00;
PORTC = 0x00;
DDRC= 0x00;
PORTD = 0x04;
DDRD= 0x00;
}

SIGNAL(SIG_INTERRUPT0)
{
i++;

switch(i%2)
{
case 1:PORTA=0x0F;break;
case 0:PORTA=0xF0;break;
}

_delay_ms(200);
}

void init_devices(void)
{
//stop errant interrupts until set up
cli(); //disable all interrupts
port_init();

MCUCR = 0x00;
GICR= 0x40;
TIMSK = 0x00; //timer interrupt sources
sei(); //re-enable interrupts
//all peripherals are now initialized
}

int main()
{
init_devices();

while(1)
{
sei();
}
return 0;
}

我使用这个程序没有你所说的问题。
1.INT0引脚一起接地:1-4和5-8是交替亮的。改变延时时间,则交替的频率也改变。说明延时是有效的。

2.手动触发中断,1-4和5-8是也交替亮。

3.不会的,因为在中断中有200ms的延时,这个时间足够去除抖动。

补充:
这个是我使用ICCV7.14版本的软件,由于没有delay.h和UseAVRPortBit.h,这里将其注释了,自己写了个延时函数,但时间不是很准,不影响测试。
#include
#include
//#include
//#include
volatile unsigned int i=0;

void Delay_ms(unsigned char ucData)
{
unsigned int j;

while(--ucData)
{
for(j = 0;j < 3000; j++);
}
}

void port_init(void)
{PORTA=0xF0;

DDRA= 0xFF;
PORTB = 0x00;
DDRB= 0x00;
PORTC = 0x00; //m103 output only
DDRC= 0x00;
PORTD = 0x00;
DDRD= 0x00;
}

#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//external interupt on INT0
i++;
switch(i%2)
{
case 1:PORTA=0x0F;break;
case 0:PORTA=0xF0;
}

Delay_ms(200);
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();

MCUCR = 0x00;
GICR= 0x40;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{

init_devices();
while(1)
{
SEI();
}
}

我使用以上软件进行测试,还是没有发现楼主所说的问题,楼主把delay.h和UseAVRPortBit.h也帖出来。

测试过程如下:
1.采用按键触发外部中断,都是交替变化的。
2.通过改变for(j = 0;j < 3000; j++);中的值,交替变化速度也随着变化,说明中断中使用延时函数还是有效的。
3.中断是不会发生重入的,对于AVR单片机,进入中断后,系统已经将全局中断屏蔽了,即使再次发生中断,也不会响应,除非在中断函数中将全局中断打开。这里还要说明的是,中断嵌套也只能嵌套优先级高的中断,除非进行特殊处理。

如果改成如下:
i++;
switch(i%8)
{
case 7:PORTA=0xFE;break;
case 6:PORTA=0xFD;break;
case 5:PORTA=0xFB;break;
case 4:PORTA=0xF7;break;
case 3:PORTA=0xEF;break;
case 2:PORTA=0xDF;break;
case 1:PORTA=0xBF;break;
case 0:PORTA=0x7F;break;
}
可实现更多的功能。

如果还是有问题,可以将你的硬件情况和整个软件发上来。
全部回答
在中断的全局变量前须加volatile
你只要改下面的就行了。
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//external interupt on INT0
多定义char k;
i++;
k=i%2;
switch(i)
{
case 1:PORTA=0x0F;
case 0:PORTA=0xF0;
}
Delay_ms(200);
}
switch(i%2)
{
case 1:PORTA=0x0F;
case 0:PORTA=0xF0;
}
这里面应该加上break语句,加上去再试试!
一个变量如果要在中断中改变它,且在主函数中用到,在它的定义前加个volatile
void port_init(void)的函数中,一定要先DDRA= 0xFF;后PORTA=0xF0;。
再就是中断函数中尽量不要写占用cpu的语句。delay函数就更别提了。
可能有2点原因:
1. 中断服务中switch语句中没有break语句, 导致PORTA=0x0F;接着设定了PORTA=0xF0; 可能case 1时会出现闪或看不到效果.
2. 中断产生了重入. 导致中断服务再次打断,后果无法预知,建议修改如下(含第1点)
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//external interupt on INT0
//stop errant interrupts
CLI(); //disable all interrupts
i++;
switch(i%2)
{
case 1:PORTA=0x0F;break;
case 0:PORTA=0xF0;break;
}
SEI(); //re-enable interrupts
Delay_ms(200);
}
另外还有1点最好检查下: 在中断中使用Delay_ms好用么?
补充:
因为在中断中延时函数是无效的.建议你修改下整个代码的机制:
中断中设定全局变量或发送消息,并禁止中断,在main()判断全局变量或接收消息,判断中断产生后设定PORTA,并延时200ms,延时时间到后再中断使能.
volatile BOOL intr_flag = FALSE;
void int0_isr(void)
{
//external interupt on INT0
//stop errant interrupts
CLI(); //disable all interrupts
intr_flag = TRUE;
}
...
void main(void)
{
init_devices();
while(1)
{
if (intr_flag == TRUE) {
i++;
switch(i%2)
{
case 1:PORTA=0x0F;break;
case 0:PORTA=0xF0;break;
}
Delay_ms(200);
intr_flag = FALSE;
SEI(); //re-enable interrupts
}
}
}
我要举报
如以上问答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
彩虹岛暴风追魂为什么不加百万富翁梦和财迷术
亚洲汽车配件大全这个地址在什么地方,我要处
安琪拉的灰烬读后感450 字.
顺义租车在哪里啊,我有事要去这个地方
我和女朋友每次前戏都做的很久,她下面都很湿
求街拍图片打包下载(高分求)
新华联超市长山店这个地址在什么地方,我要处
华硕飞马10到底怎么样?希望大家能介绍。
佳信手机怎么去啊,有知道地址的么
追书神器书荒区收藏的帖子在哪?
明相塆地址在什么地方,想过去办事
我的世界开服务器
大运高速公路/平南路(路口)我想知道这个在什
求男主是明星而且很温柔。女主是他的粉丝的小
下沙高沙到下城区石桥路北永华街81号(浙江印
推荐资讯
舰队collection摩耶装备怎样搭配
我想求姻缘今天到北帝古庙求了只签,求解望哪
小手画室地址在什么地方,想过去办事
世界上智商最高的人
求近两天kdj金叉选股公式,即昨天或今天kdj金
找一位分界洲岛的潜水教练
常州谷丰绣品厂地址有知道的么?有点事想过去
阿宝外送怎么去啊,有知道地址的么
查旧幼儿园地址有知道的么?有点事想过去
在古代有姓于的太监吗
电脑桌面时间如何卸掉删除
各位亲对现在的房价有什么看法?认为未来几年
手机登qq时,显示手机磁盘不足,清理后重新登
刺客的套装怎么选啊?