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 – 外部中断标志寄存器
阅读数据表总是有助于理解实现细节。
我有一个小任务要使用 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 – 外部中断标志寄存器
阅读数据表总是有助于理解实现细节。