AVR ATmega48的中断编程

Interrupt programming for AVR ATmega48

我有一个小任务要使用 C 为 ATmega48 控制器编写以下程序:

一开始,所有 (6) 个 LED 都打开。 当按下按钮 SW1 时,仅允许使用相应的按钮 关闭 LED。 当按下按钮 SW2 时,仅允许使用相应的按钮 打开

这是我想出的:

#define F_CPU 1000000UL
#include <asf.h>
#include <util/delay.h>

volatile unsigned char r,d;
ISR(INT0_vect)
{
    if (d = 0)
    {
        PORTB = PORTB | 1<<1;
        d = 1;
    }
    else
    {
        PORTB = PORTB | 0<<2;
        d = 0;         
    }
}
int main (void)
{
    d = 0;
    DDRC = 0x00;
    PORTC = 0xFF;
    DDRB= 0xFF;
    PORTB = 0x00;
    PCICR = 0b00000001;
    sei();
    while(1)
    {
        PCMSK0 = 0b00000100;
        while (d == 0) 
        {
            for (int i=0; i<6; i++)
            {
                if(!(PINC & (1<<i)))
                    PORTB = PORTB | i<<1;
            }
        }
        PCMSK0 = 0b00000010;
        while (d == 1)
        {
            for (int i=0; i<6; i++)
            {
                if(!(PINC & (1<<i)))
                    PORTB = PORTB | i<<0;
                r = r<<1;
            }
        }
    }
}

当我尝试在 Atmel AVR Studio 中进行仿真时,当我按下相应的按钮(例如 SW4 的 LED2)时,错误的 LED 亮起,并且从未发生中断。

请解释我做错了什么,因为我已经搜索了几个资源,每个资源都给出了不同的方法,我无法理解。

虽然您没有以正确的方式初始化中断,但这里根本没有执行的这些代码行有两个问题。

if (d = 0)
{
    PORTB = PORTB | 1<<1;
    d = 1;
}
else
{
    PORTB = PORTB | 0<<2;
    d = 0;         
}

一个明显的问题是:if (d = 0) 不检查 d 是否等于 0,而是将 0 分配给 d每一次。

您是否要设置和清除引脚? 如果是,这不是应该的方式。 通常在嵌入式中我们这样设置引脚:PORTB |= (1<<1); //you have got this right
并通过 PORTB &= ~(1<<1);

清除引脚

您说 从未发生过中断 。这是一个有效的结论,即 d 一直保持 0 而你一直循环 while (d == 0) {} 。因此 r 永远不会被修改,除非来自您显示的代码中的 elsewhere/apart 。这个 r 有任何与 LED 的 GPIO 相关的实现吗?如果是,那么你必须先解决中断中的问题。


从未发生中断的原因是您根本没有初始化外部中断。

需要配置EICRA – 外部中断控制寄存器A寄存器

然后需要配置EIMSK – 外部中断屏蔽寄存器

然后需要配置EIFR – 外部中断标志寄存器


阅读数据表总是有助于理解实现细节。