在该程序中,AM使用计时器中断在LED中骑自行车,如果有人按下开关,则应阻止第一个中断和触发第二个,第二个应该根据按下的开关来点亮LED。在这里,有点困惑的是什么中断。我推荐了一些用于PIN CHANGE中断的书,并写了一些用于设置PCMSK2的行。输出获得的是“最初,当按下开关时,所有LED都是循环的... 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)
    {

    }
}

感谢您的支持。

有帮助吗?

解决方案

AVR体系结构中的外部中断令人困惑,但并非不可能。我发现最好的资源是 AVR libc页面中断. 。我认为您的代码太复杂了,您想做什么。让我们从头开始:

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

这应该闪烁LED PORTB 每次计时器中断发生时。请注意,应设置的方式是使用 ISR(...) 宏;这 __vector_... 您正在使用的电话被弃用,更令人困惑。

最后,如果我正确理解您的问题,您想使用一组开关来固定LED点亮。实际上,我不会为此使用外部中断,只需使用使用 PINK 期间 ISR(TIMER0_COMP_vect), ,但是如果您愿意,我们可以使用它。我们需要添加以下代码:

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过渡上进行此设置)。剩下的就是使LED输出取决于 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;
}

这应该使程序变得更简单。

其他提示

无论如何,每次你 __vector_23 执行您正在骑自行车在分配给的LED中 PORTB 通过增加 i. 。如果我明白您要做什么,您应该做的是递增 i 只有在 __vector_25, ,当按下开关时。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top