在纯C语言中的atmega328上设置中断 [英] Setting up Interrupts on atmega328 in pure C
问题描述
我目前正在使用Arduino Uno开发板,并且尝试使用纯C
编写它而不使用Arduino的库.
I am currently working on an Arduino Uno Board and I am trying to write it in pure C
without the use of Arduino's Libraries.
我正在工作的项目应该像这样工作:
My project which I am working should work like this:
-
将LEDs
PB0
设置为BP7
ON
和OFF
.
在连接到Button的PD2上设置中断.
Set interrupt on PD2 connected to a Button.
按下按钮时,LED应当停止(暂停).
When the Button is pressed the LEDs should STOP (pause).
再次按下按钮时,LED应当再次转动ON
从最后一个LED开始,它是OFF
.
When the Button is pressed Again the LEDs should turn ON
again
starting from the last LED which was OFF
.
更准确地说:
- 函数
play()
被调用 - LED开始互相闪烁
- 如果按下按钮,
play()
功能应停止
- The function
play()
is called - LEDs are starting to blink one after other
- If I press the BUTTON the
play()
function should STOP
这意味着,如果连接到PB3
的LED最后一个LED点亮,则当我再次按下按钮时,功能play()
应该从PB4
继续.
This means that if the LED connected to PB3
was last LED ON, when I press the Button again the function play()
should continue from PB4
.
这是我到目前为止所拥有的:
Here is what I have so far:
#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
.
At this point the function play()
runs forever and if I press the Button the LED connected to PD7
goes ON
and 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开始.一探究竟.如有任何更改.我只是提出了这个主意.希望对您有所帮助:)
by defining a variable to save which LED it was on then whenever it is resumed it will start from the last lit LED. check it out. Change if there is anything. I just gave the idea. hope it helps :)
这篇关于在纯C语言中的atmega328上设置中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!