用纯 C 在 atmega328 上设置中断
Setting up Interrupts on atmega328 in pure C
我目前正在开发 Arduino Uno 开发板,我正尝试在不使用 Arduino 库的情况下用纯 C
编写它。
我正在工作的项目应该像这样工作:
将 LED PB0
设置为 BP7
ON
和 OFF
。
在连接到按钮的 PD2 上设置中断。
按下按钮时,LED 应停止(暂停)。
再次按下按钮时,LED 应再次 ON
从最后一个 LED 开始,它是 OFF
.
更准确地说:
- 函数
play()
被调用
- LED 开始一个接一个地闪烁
- 如果我按下按钮,
play()
功能应该停止
这意味着如果连接到 PB3
的 LED 是最后一个 LED 点亮,当我再次按下按钮时,功能 play()
应该从 PB4
.
继续
这是我目前的情况:
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void play( void );
volatile uint8_t buttonWasPressed = 0;
const unsigned char LEDS[] = { PB0, PB1, PB2, PB3, PB4, PB5 };
int main(void)
{
DDRB = 0xFF; /// Set PORTB as OUTPUT
DDRD |= ( 1 << PD7 ); /// Set PIN7 IN DDRD as INPUT
PORTD &= ~( 1 << PD7 ); /// Set PIN7 on PORTD to LOW
DDRD &= ~( 1 << PD2 ); // Clear the PD2 pin and set PD2 (PCINT0 pin) now as input
PORTD |= (1 << PD2); // Set PIN PD2 as INPUT with pull-up enabled
EICRA |= (1 << ISC00); // set INT0 to trigger on ANY logic change
EIMSK |= (1 << INT0); // Turns on INT0
sei(); // turn on interrupts
while(1)
{
play();
}
}
ISR (INT0_vect)
{
uint8_t buttonState = PIND & ( 1 << PD2 );
if ( buttonState )
{
if ( buttonWasPressed == 0 )
{
PORTD ^= ( 1 << PD7 ); /// SET PIN 4 IN PORT B TO LOW
_delay_ms( 200 );
buttonWasPressed = 1; /// update button state
}
}
else /// The button is not pressed
{
buttonWasPressed = 0; /// Update the button state
}
}
void play( void )
{
for ( uint8_t i = 0 ; i < 6 ; i++ )
{
PORTB |= ( 1 << LEDS[i] ); ///Turn LED ON
_delay_ms( 250 );
PORTB &= ~( 1 << LEDS[i] ); ///Turn LED OFF
_delay_ms( 250 );
}
}
此时函数 play()
将永远运行,如果我按下按钮,连接到 PD7
的 LED 变为 ON
和 OFF
.
尝试这样的事情。
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void play( unsigned int a );
ISR (INT0_vect);
volatile uint8_t buttonWasPressed = 0;
const unsigned char LEDS[] = { PB0, PB1, PB2, PB3, PB4, PB5 };
unsigned int ledNum = 0;
int main(void)
{
DDRB = 0xFF; /// Set PORTD as OUTPUT
DDRD |= ( 1 << PD7 ); /// Set PIN7 IN DDRD as INPUT
PORTD &= ~( 1 << PD7 ); /// Set PIN7 on PORTD to LOW
DDRD &= ~( 1 << PD2 ); // Clear the PD2 pin and set PD2 (PCINT0 pin) now as input
PORTD |= (1 << PD2); // Set PIN PD2 as INPUT with pull-up enabled
EICRA |= (1 << ISC00); // set INT0 to trigger on ANY logic change
EIMSK |= (1 << INT0); // Turns on INT0
sei(); // turn on interrupts
while(1)
{
if(buttonWasPressed == 1)
play(ledNum);
}
}
ISR (INT0_vect)
{
uint8_t buttonState = PIND & ( 1 << PD2 );
if ( buttonState )
{
if ( buttonWasPressed == 0 )
{
PORTD ^= ( 1 << PD7 ); /// SET PIN 4 IN PORT B TO LOW
_delay_ms( 200 );
buttonWasPressed = 1; /// update button state
}
}
else /// The button is not pressed
{
buttonWasPressed = 0; /// Update the button state
}
}
void play( unsigned int a )
{
for ( uint8_t i = a ; i < 6 ; i++ )
{
PORTB |= ( 1 << LEDS[i] ); ///Turn LED ON
_delay_ms( 250 );
PORTB &= ~( 1 << LEDS[i] ); ///Turn LED OFF
_delay_ms( 250 );
ledNum=i;
}
}
通过定义一个变量来保存它点亮的 LED,然后无论何时恢复它都会从最后一个点亮的 LED 开始。看看这个。有什么就改。我只是提出了这个想法。希望对您有所帮助:)
我在@Althaf1467 的帮助下成功修复了它。
工作代码是:
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define LEDS_LENGTH 6
void play( void );
volatile uint8_t state = 0 ;
const unsigned char LEDS[] = { PB0, PB1, PB2, PB3, PB4, PB5 };
int main( void )
{
DDRB = 0xFF; /// Set PORTD as OUTPUT
DDRD |= ( 1UL << PD7 ); /// Set PIN7 IN DDRD as INPUT
PORTD &= ~( 1UL << PD7 ); /// Set PIN7 on PORTD to LOW
DDRD &= ~( 1UL << PD2 ); /// Clear the PD2 pin and set PD2 (PCINT0 pin) now as input
PORTD |= ( 1UL << PD2 ); /// Set PIN PD2 as INPUT with pull-up enabled
EICRA |= ( 1UL << ISC00 ); /// set INT0 to trigger on ANY logic change
EIMSK |= ( 1UL << INT0 ); /// Turns on INT0
sei(); /// turn on interrupts
while(1)
{
play();
}
}
ISR ( INT0_vect )
{
if ( PIND & ( 1UL << PD2 ) )
{
PORTD ^= ( 1UL << PD7 ); /// SET PIN 4 IN PORT B TO LOW
state ^= ( 1 << 0 ); /// Swap the Buton State from 0 to 1 and back to 0 ...
_delay_ms( 500 );
}
}
void play( void )
{
static uint8_t step = 0;
while( step < LEDS_LENGTH )
{
if ( state == 1 )
{
break;
}
PORTB |= ( 1UL << LEDS[ step ] ); /// Turn LED ON
_delay_ms( 250 );
PORTB &= ~( 1UL << LEDS[ step ] ); /// Turn LED OFF
_delay_ms( 250 );
step++;
}
if ( step == LEDS_LENGTH )
{
step = 0;
}
}
我目前正在开发 Arduino Uno 开发板,我正尝试在不使用 Arduino 库的情况下用纯 C
编写它。
我正在工作的项目应该像这样工作:
将 LED
PB0
设置为BP7
ON
和OFF
。在连接到按钮的 PD2 上设置中断。
按下按钮时,LED 应停止(暂停)。
再次按下按钮时,LED 应再次
ON
从最后一个 LED 开始,它是OFF
.
更准确地说:
- 函数
play()
被调用 - LED 开始一个接一个地闪烁
- 如果我按下按钮,
play()
功能应该停止
这意味着如果连接到 PB3
的 LED 是最后一个 LED 点亮,当我再次按下按钮时,功能 play()
应该从 PB4
.
这是我目前的情况:
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void play( void );
volatile uint8_t buttonWasPressed = 0;
const unsigned char LEDS[] = { PB0, PB1, PB2, PB3, PB4, PB5 };
int main(void)
{
DDRB = 0xFF; /// Set PORTB as OUTPUT
DDRD |= ( 1 << PD7 ); /// Set PIN7 IN DDRD as INPUT
PORTD &= ~( 1 << PD7 ); /// Set PIN7 on PORTD to LOW
DDRD &= ~( 1 << PD2 ); // Clear the PD2 pin and set PD2 (PCINT0 pin) now as input
PORTD |= (1 << PD2); // Set PIN PD2 as INPUT with pull-up enabled
EICRA |= (1 << ISC00); // set INT0 to trigger on ANY logic change
EIMSK |= (1 << INT0); // Turns on INT0
sei(); // turn on interrupts
while(1)
{
play();
}
}
ISR (INT0_vect)
{
uint8_t buttonState = PIND & ( 1 << PD2 );
if ( buttonState )
{
if ( buttonWasPressed == 0 )
{
PORTD ^= ( 1 << PD7 ); /// SET PIN 4 IN PORT B TO LOW
_delay_ms( 200 );
buttonWasPressed = 1; /// update button state
}
}
else /// The button is not pressed
{
buttonWasPressed = 0; /// Update the button state
}
}
void play( void )
{
for ( uint8_t i = 0 ; i < 6 ; i++ )
{
PORTB |= ( 1 << LEDS[i] ); ///Turn LED ON
_delay_ms( 250 );
PORTB &= ~( 1 << LEDS[i] ); ///Turn LED OFF
_delay_ms( 250 );
}
}
此时函数 play()
将永远运行,如果我按下按钮,连接到 PD7
的 LED 变为 ON
和 OFF
.
尝试这样的事情。
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void play( unsigned int a );
ISR (INT0_vect);
volatile uint8_t buttonWasPressed = 0;
const unsigned char LEDS[] = { PB0, PB1, PB2, PB3, PB4, PB5 };
unsigned int ledNum = 0;
int main(void)
{
DDRB = 0xFF; /// Set PORTD as OUTPUT
DDRD |= ( 1 << PD7 ); /// Set PIN7 IN DDRD as INPUT
PORTD &= ~( 1 << PD7 ); /// Set PIN7 on PORTD to LOW
DDRD &= ~( 1 << PD2 ); // Clear the PD2 pin and set PD2 (PCINT0 pin) now as input
PORTD |= (1 << PD2); // Set PIN PD2 as INPUT with pull-up enabled
EICRA |= (1 << ISC00); // set INT0 to trigger on ANY logic change
EIMSK |= (1 << INT0); // Turns on INT0
sei(); // turn on interrupts
while(1)
{
if(buttonWasPressed == 1)
play(ledNum);
}
}
ISR (INT0_vect)
{
uint8_t buttonState = PIND & ( 1 << PD2 );
if ( buttonState )
{
if ( buttonWasPressed == 0 )
{
PORTD ^= ( 1 << PD7 ); /// SET PIN 4 IN PORT B TO LOW
_delay_ms( 200 );
buttonWasPressed = 1; /// update button state
}
}
else /// The button is not pressed
{
buttonWasPressed = 0; /// Update the button state
}
}
void play( unsigned int a )
{
for ( uint8_t i = a ; i < 6 ; i++ )
{
PORTB |= ( 1 << LEDS[i] ); ///Turn LED ON
_delay_ms( 250 );
PORTB &= ~( 1 << LEDS[i] ); ///Turn LED OFF
_delay_ms( 250 );
ledNum=i;
}
}
通过定义一个变量来保存它点亮的 LED,然后无论何时恢复它都会从最后一个点亮的 LED 开始。看看这个。有什么就改。我只是提出了这个想法。希望对您有所帮助:)
我在@Althaf1467 的帮助下成功修复了它。
工作代码是:
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define LEDS_LENGTH 6
void play( void );
volatile uint8_t state = 0 ;
const unsigned char LEDS[] = { PB0, PB1, PB2, PB3, PB4, PB5 };
int main( void )
{
DDRB = 0xFF; /// Set PORTD as OUTPUT
DDRD |= ( 1UL << PD7 ); /// Set PIN7 IN DDRD as INPUT
PORTD &= ~( 1UL << PD7 ); /// Set PIN7 on PORTD to LOW
DDRD &= ~( 1UL << PD2 ); /// Clear the PD2 pin and set PD2 (PCINT0 pin) now as input
PORTD |= ( 1UL << PD2 ); /// Set PIN PD2 as INPUT with pull-up enabled
EICRA |= ( 1UL << ISC00 ); /// set INT0 to trigger on ANY logic change
EIMSK |= ( 1UL << INT0 ); /// Turns on INT0
sei(); /// turn on interrupts
while(1)
{
play();
}
}
ISR ( INT0_vect )
{
if ( PIND & ( 1UL << PD2 ) )
{
PORTD ^= ( 1UL << PD7 ); /// SET PIN 4 IN PORT B TO LOW
state ^= ( 1 << 0 ); /// Swap the Buton State from 0 to 1 and back to 0 ...
_delay_ms( 500 );
}
}
void play( void )
{
static uint8_t step = 0;
while( step < LEDS_LENGTH )
{
if ( state == 1 )
{
break;
}
PORTB |= ( 1UL << LEDS[ step ] ); /// Turn LED ON
_delay_ms( 250 );
PORTB &= ~( 1UL << LEDS[ step ] ); /// Turn LED OFF
_delay_ms( 250 );
step++;
}
if ( step == LEDS_LENGTH )
{
step = 0;
}
}