gpt4 book ai didi

AVR 应用的 C - ISR 重复

转载 作者:行者123 更新时间:2023-11-30 14:45:19 25 4
gpt4 key购买 nike

我正在尝试让一个简单的中断例程在 ATMega328P 上工作。 PD6 上连接有一个 LED,PB7 上有一个内置按钮。 LED 应正常闪烁,直到按下按钮,然后常亮 1.5 秒,然后再恢复闪烁。代码如下:

#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int main(void)
{
// Enable pull-ups and set pin directions
MCUCR |= (1<<PUD);
PORTD &= ~(1<<PORTD6);
DDRD |= (1<<DDD6);
PORTB |= (1<<PORTB7);
DDRB &= ~(1<<DDB7);

// Enable pin change interrupt
PCICR = 0x01;
PCMSK0 = 0x80;
sei();

while (1)
{
// Blink LED at standard rate
_delay_ms(500);
PORTD ^= (1<<PORTD6);
_delay_ms(500);
PORTD ^= (1<<PORTD6);
}
}

ISR(PCINT0_vect,ISR_BLOCK)
{
PORTD &= ~(1<<PORTD6);
_delay_ms(500);
PORTD |= (1<<PORTD6);
_delay_ms(1500);
PORTD &= ~(1<<PORTD6);
}

中断正确触发,但 ISR 例程循环两次。我想这是某种按钮弹跳问题,但我不熟悉如何处理它。我尝试在开始时引入 500ms 延迟,并且还尝试清除 ISR 中的引脚更改中断标志,以便它不会再次触发,但它仍然会触发。预先感谢您的帮助!

最佳答案

让我们在 LED 亮起 1.5 秒时乐意忽略任何按钮按下的基础上进行工作。您可以像这样编写中断处理程序:

ISR(PCINT0_vect,ISR_BLOCK)
{
button_pressed = 1;
}

并将其放在代码顶部:

volatile int button_pressed = 0;

(请参阅 this page 以了解有关 volatile 的全部内容以及此处为何需要它的信息。)

然后你的主循环可以如下所示:

while (1) 
{
// Blink LED on and off

PORTD |= (1<<PORTD6); // Turn LED on.
if (button_pressed) {
_delay_ms(1500); // Long delay if button was pressed.
button_pressed = 0;
} else {
_delay_ms(500); // Regular delay otherwise.
}

PORTD &= ~(1<<PORTD6); // Turn LED off.
_delay_ms(500);
}
<小时/>

高级读者注意事项:

  1. volatile int Button_pressed = 0; 实际上可能只是 volatile int Button_pressed;,因为文件范围内的静态 int 是初始化为0,但显式初始化会更清晰。

  2. C 程序经常使用 for (;;) 作为“永远循环”的习惯用法,而不是 while (1)

    <

关于AVR 应用的 C - ISR 重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53125051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com