在程序中,我使用定时器中断在led之间循环&如果有人按下开关,它应该停止第一个中断,并触发第二个中断,根据按下的开关点亮led。在这里,我有点困惑哪个中断是被调用的。我参考了一些关于引脚更改中断的书籍,并编写了几行代码来设置PCMSK2。我得到的输出是“最初所有的led都在循环,当一个开关被pressed...cycling of led停止并重新开始时(这意味着程序正在读取输入,只是没有触发第二个中断)。它不会停止或暂停,也不会点亮后续的led。”有人能帮帮忙吗?
#include <avr/io.h>
#include <avr/interrupt.h>
#define PINK_MASK \
((1<<PINK0)|(1<<PINK1)|(1<<PINK2)|(1<<PINK3)|(1<<PINK4)|(1<<PINK5)|(1<<PINK6)|(1<<PINK7))
volatile unsigned int intrs, i=1;
void enable_ports(void);
void delay(void);
extern void __vector_23 (void) __attribute__ ((interrupt));
extern void __vector_25 (void) __attribute__ ((signal));
void enable_ports()
{
DDRB = 0xff; //PORTB as output for leds
PORTB = 0xff;
DDRK = 0x00; //PORTK as input from switches
PORTK |= PINK_MASK;
PCMSK2 = PINK_MASK; //ENABLE PCMSK2, Setting interrupts
PCICR = 0x04;
PCIFR = 0x04;
TCCR0B = 0x03; //Setting TIMER
TIMSK0 = 0x01;
TCNT0 = 0x00;
intrs = 0;
}
void __vector_23 (void)
{
intrs++;
if(intrs > 60)
{
intrs = 0;
PORTB = (0xff<<i);
i++ ;
if(i == 10 )
{
PORTB = 0xff;
i = 1 ;
}
}
}
void __vector_25 (void)
{
unsigned char switches;
switches = ((~PINK) & (PINK_MASK)); //Reading from switches
if(switches & (1<<PINK0))
PORTB = (PORTB<<PINK0);
else if (switches & (1<<PINK1))
PORTB = (PORTB<<PINK1);
else if (switches & (1<<PINK2))
PORTB = (PORTB<<PINK2);
else if (switches & (1<<PINK3))
PORTB = (PORTB<<PINK3);
else if (switches & (1<<PINK4))
PORTB = (PORTB<<PINK4);
else if (switches & (1<<PINK5))
PORTB = (PORTB<<PINK5);
else if (switches & (1<<PINK6))
PORTB = (PORTB<<PINK6);
else if (switches & (1<<PINK7))
PORTB = (PORTB<<PINK7);
}
int main(void)
{
enable_ports();
sei();
while(1)
{
}
}感谢您的所有支持。
发布于 2011-02-01 22:10:08
AVR架构中的外部中断令人困惑,但并非不可能。我发现对我来说最好的资源是AVR libc page on interrupts。我认为你把代码弄得太复杂了,不能让它实现你想要的功能。让我们从头开始:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
void main() {
sei();
while(1) {};
}AVR libc实际上使处理中断变得非常轻松。在上面我链接的页面中,列出了每个AVR芯片上支持的所有中断向量。让我们假设您正在使用Mega32,并且您现在希望使用计时器中断让LED闪烁。让我们添加到程序中:
uint8_t led_state;
ISR(TIMER0_COMP_vect) {
led_state = ~led_state;
PORTB = led_state;
}
void setup_timer_interrupt() {
TCCR0B = 0x03;
TIMSK0 = 0x01;
TCNT0 = 0x00;
}每次定时器中断发生时,PORTB上的LED应会闪烁。注意,设置它的方法应该是使用ISR(...)宏;您正在使用的__vector_...调用已被弃用,并且更加令人困惑。
最后,如果我正确理解了您的问题,您希望使用一组开关来保持LED亮起。我实际上不会为此使用外部中断,只需在ISR(TIMER0_COMP_vect)期间使用PINK读取开关的值,但如果您愿意,我们可以使用它。我们需要添加以下代码:
uint8_t switch_state;
void setup_switch_interrupt() {
// I'm assuming this code to enable external interrupts works.
DDRK = 0x00;
PORTK = 0xff;
PCMSK2 = 0xff; // set to all 1s
PCICR = 0x04;
PCIFR = 0x04;
}
ISR(INT0_vect) {
switch_state = PINK;
}这是做什么的?我们将开关的状态保存在switch_state中,每次外部中断触发时读取(我猜您在0->1和1->0转换时都设置了此设置)。剩下的就是让发光二极管的输出依赖于switch_state的值。我们将在计时器中断中执行此操作,因为到目前为止,这是我们切换LED的地方。新版本如下所示:
ISR(TIMER0_COMP_vect) {
led_state = ~led_state | switch_state;
PORTB = led_state;
}这应该就行了!
脚注:我之前说过,没有必要使用外部中断来读取开关。这是因为您只能在定时器中断期间使用PINK读取开关值。您可以去掉switch_state、setup_switch_interrupt()和ISR(INT0_vect),只需将计时器中断修改为:
ISR(TIMER0_COMP_vect) {
led_state = ~led_state | PINK;
PORTB = led_state;
}这应该会使程序变得更简单。
发布于 2010-11-10 08:17:37
因此,不管怎样,每次执行__vector_23时,您都会通过递增i来遍历分配给PORTB的LED。如果我理解你想做什么,你应该做的是,当开关被按下时,只在__vector_25中递增i。
https://stackoverflow.com/questions/4137771
复制相似问题