我的中断没有将我的值更新为我的主值,我应该如何设置我的中断?
My Interrupt is not updating my value to my main, how should i set up my Interrupt?
我正在尝试构建一个程序,该程序的扫描灯至少有 5 个 LED 和一个连接到外部中断引脚的按钮。按下(并松开)一个按钮即可启动扫描灯。按下(然后松开)再次停止扫描灯(依此类推...)。
- 我在 PD2 上有一个接地侧开关
- 我在 PD3、PD4、PD5、PD6 和 PD7 引脚上安装了 LED。
- 我正在使用 ATMega328P
我知道我的高耸灯在按下按钮时亮起,高耸灯停止但当我再次按下时感觉它没有 return 值变为 1。
我的代码:
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit)))
volatile int value = 1;
int main(void)
{
DDRD = 0b111110000;
DDRD &= ~(1 << PD2); // clear DDRD bit 2, sets PD2 (pin 4) for input
PORTD |= (1 << PD2); // set PD2/INT0 (pin 4) internal pull-up resistor
PCICR = 0b00000100;
PCMSK2 = 0b00000100;
sei();
while (value==1) //when value is 1 it should start having a towerlight
{
PORTD= 0x80;
_delay_ms(15000);
PORTD= 0x40;
_delay_ms(15000);
PORTD= 0x20;
_delay_ms(15000);
PORTD= 0x10;
_delay_ms(15000);
PORTD= 0x08;
_delay_ms(15000);
}
}
ISR(PCINT2_vect)
{
if(BIT_IS_CLEAR(PIND, PD2) & value==1) { // if switch is pressed (logic low)
value=0;
} else if(value == 0) {
value=1;
} else {
// ideally should never get here, but may occasionally due to timing
}
}```
您正在使用按位 AND,而它应该是逻辑 AND。改变这个
if(BIT_IS_CLEAR(PIND, PD2) & value==1)
至此
if(BIT_IS_CLEAR(PIND, PD2) && (0 != value))
比较 non-zero 而不是等于 1 防止 value
被破坏;因为你想要一个零或 non-zero 条件。添加括号使意图非常明确。 Yoda 比较(将常量放在左侧)可防止意外赋值。
另一件要考虑的事情是你正在做什么来消除开关的抖动——以模拟方式使用 R-C+施密特或单稳态,或者以数字方式,你有一个定时器程序来采样每隔一段时间输入并计算“最后有多少个 1 或 0,比如 16 个样本”?
我发现边沿触发中断对手动开关输入的效果不是特别好。
关于:
while (value==1)
{
....
}
当value
为0时退出循环,执行退出程序。这是程序中严重的逻辑缺陷
我正在尝试构建一个程序,该程序的扫描灯至少有 5 个 LED 和一个连接到外部中断引脚的按钮。按下(并松开)一个按钮即可启动扫描灯。按下(然后松开)再次停止扫描灯(依此类推...)。
- 我在 PD2 上有一个接地侧开关
- 我在 PD3、PD4、PD5、PD6 和 PD7 引脚上安装了 LED。
- 我正在使用 ATMega328P
我知道我的高耸灯在按下按钮时亮起,高耸灯停止但当我再次按下时感觉它没有 return 值变为 1。
我的代码:
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit)))
volatile int value = 1;
int main(void)
{
DDRD = 0b111110000;
DDRD &= ~(1 << PD2); // clear DDRD bit 2, sets PD2 (pin 4) for input
PORTD |= (1 << PD2); // set PD2/INT0 (pin 4) internal pull-up resistor
PCICR = 0b00000100;
PCMSK2 = 0b00000100;
sei();
while (value==1) //when value is 1 it should start having a towerlight
{
PORTD= 0x80;
_delay_ms(15000);
PORTD= 0x40;
_delay_ms(15000);
PORTD= 0x20;
_delay_ms(15000);
PORTD= 0x10;
_delay_ms(15000);
PORTD= 0x08;
_delay_ms(15000);
}
}
ISR(PCINT2_vect)
{
if(BIT_IS_CLEAR(PIND, PD2) & value==1) { // if switch is pressed (logic low)
value=0;
} else if(value == 0) {
value=1;
} else {
// ideally should never get here, but may occasionally due to timing
}
}```
您正在使用按位 AND,而它应该是逻辑 AND。改变这个
if(BIT_IS_CLEAR(PIND, PD2) & value==1)
至此
if(BIT_IS_CLEAR(PIND, PD2) && (0 != value))
比较 non-zero 而不是等于 1 防止 value
被破坏;因为你想要一个零或 non-zero 条件。添加括号使意图非常明确。 Yoda 比较(将常量放在左侧)可防止意外赋值。
另一件要考虑的事情是你正在做什么来消除开关的抖动——以模拟方式使用 R-C+施密特或单稳态,或者以数字方式,你有一个定时器程序来采样每隔一段时间输入并计算“最后有多少个 1 或 0,比如 16 个样本”?
我发现边沿触发中断对手动开关输入的效果不是特别好。
关于:
while (value==1)
{
....
}
当value
为0时退出循环,执行退出程序。这是程序中严重的逻辑缺陷