我正在摆弄我的MEGA-1284p套件和avr工作室,我需要一些帮助解决问题。我需要它按下按钮SW0上的LED3。
这是AVR C代码:
#define F_CPU 11059200UL // The Xplained kit runs at 11.0592 MHz
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int ex37() {
DDRB = 0x04;// LED3 as output
PORTB = 0x04; //LED3 off
EIMSK |= (1<<INT0) | (0<<INT1) | (0<<INT2); // Enable external interrupt 0 (SW0)
MCUCR |= (1<<ISC01) | (1<<ISC00); // INT0 on rising edge.
sei(); // Start interrupts
_delay_ms(1000); //wait 1000 ms = 1 sec
PORTB = 0x00; //LED3 on
_delay_ms(1000); //wait 1000 ms = 1 sec
PORTB = 0x04; //LED3 off
while(1) {
};
return 0;
}
ISR(INT0_vect) {
_delay_ms(1000); //wait 1000 ms = 1 sec
if (PORTB == 0x04){
PORTB = 0x00;
} else {
PORTB = 0x04;
}
}
但据我所知,改变LED3的功能永远不会被召唤。
答案 0 :(得分:2)
SW0
连接到PB0
,这不是任何外部中断处于活动状态的引脚。
相反,您需要使用引脚更改中断PCIE1
并正确配置它。有关寄存器说明,请参阅datasheet。
答案 1 :(得分:0)
您需要禁用看门狗定时器或定期执行看门狗定时器复位(WDR)指令。如果您没有,控制器将在到期时重置。数据表给出了这样的代码来禁用它:
void WDT_off(void)
{
__disable_interrupt();
__watchdog_reset();
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional
time-out */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Turn off WDT */
WDTCSR = 0x00;
__enable_interrupt();
}
答案 2 :(得分:0)
这可能不是您代码中的主要问题,但首先突然出现的是您在中断服务程序中遇到的大量延迟:
ISR(INT0_vect) {
_delay_ms(1000); //wait 1000 ms = 1 sec
if (PORTB == 0x04){
PORTB = 0x00;
} else {
PORTB = 0x04;
}
}
一整秒钟是微控制器等待的非常非常的时间。正如有人提到的那样,你的看门狗定时器可能会超时。而不是摆弄看门狗启用/禁用,考虑首先重写您的ISR,看看是否能解决您的问题。
编写具有最短ISR的代码通常是一种好习惯。我建议使用您的ISR来创建一个标志,并在while(1)
循环中对其进行响应。 ISR延迟1秒可能不会引起问题,但是一旦事情开始累加,它可能会让你的MCU陷入困境。
我希望这会有所帮助。
答案 3 :(得分:0)
而不是:
if (PORTB == 0x04){
PORTB = 0x00;
} else {
PORTB = 0x04;
}
你只能写: PORTB ^ = 0x04;