zetgun
10.07.2010, 15:23
Hi,
ich habe erst neu mit Microcontroller / Robotik angefangen und arbeite mich nun langsam durch den Stoff und hier durchs Forum :).
Nun hatte ich ein Problem, konnte dieses zwar Lösen, verstehe aber nicht warum nicht beides funktioniert.
Funktion:
Es soll LED3 (PB3) blinken. Nach ca. einer Minute soll die LED0 (PB0) leuchten, nach einer weiteren Minute dann LED0 aus und LED1 (PB1) an usw.
Ergebnis Code1:
LED3 blinkt wie gewünscht, aber die andere LEDs blinken von Anfang an auch ganz wild und unvorhersehbar.
Ergebnis Code2:
Nach etwas probieren (Interrupts während den IF-Anweisungen ausschalten usw.) hab ichs dann wie in Code2 geändert und nun tut es.
Nun hoffe ich, dass mir jemand von euch sagen kann warum. Es müsste doch egal sein, ob ich die Sekunden in der Hauptschleife oder dem Interrupt hochzähl, hauptsache ich deklariere die Variable als volatile, damit der Compiler das richtig umsetzt.
Wenn es jemand Testen will, ich arbeite mit einem NiboBee.
(Die stellen, welche sich unterscheiden sind mit " // <<----- Unterschied" markiert)
Code1 (funktioniert nicht):
#include <avr/io.h> // allgemeine Headerdatei
#include <stdint.h> // für standardisierten Typen z.B. int8_t
#include <avr/interrupt.h> // fuer sei() => Aktivieren, cli() => ausschalten und ISR():
// Prototypen
void Timer0_init(void);
// Globale Variable
volatile uint16_t blink_hz = 0;
volatile uint8_t blink = 0;
// <<----- Unterschied
int main(void)
{
// IO's init
Timer0_init();
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3); // LED's
// Variable
volatile uint8_t sek = 0; // <<----- Unterschied
// Globale Interrupts erlauben
sei();
while(1)
{
if(blink)
{
PORTB |= (1<<PB3);
sek++; // <<----- Unterschied
}
else PORTB &= ~(1<<PB3);
if (sek > 59 && sek < 119) PORTB |= (1<<PB0);
else PORTB &= ~(1<<PB0);
}
return 0;
}
/*************
Funktionen
**************/
// Timer 1ms
void Timer0_init(void)
{
TCCR0 = (1<<WGM01); // Timer im CTC-Modus
TCCR0 |= (1<<CS00) | (1<<CS01); // Prescaler auf 64
OCR0 = 234; // um ca. 1ms zu erreichen
TIMSK |= (1<<OCIE0); // Interrupt "TIMER0_COMP_vect" aktivieren
}
/*************
Interrupts
**************/
ISR (TIMER0_COMP_vect)
{
blink_hz++;
switch (blink_hz)
{
case 499: blink = 1; break; // <<----- Unterschied
case 999: blink = 0; blink_hz = 0; break;
default: break;
}
}
Code2 (funktioniert):
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
// Prototypen
void Timer0_init(void);
// Globale Variable
volatile uint16_t blink_hz = 0;
volatile uint8_t blink = 0;
volatile uint8_t sek = 0; // <<----- Unterschied
int main(void)
{
// IO's init
Timer0_init();
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3); // LED's
// Globale Interrupts erlauben
sei();
while(1)
{
if(blink)
{
PORTB |= (1<<PB3);
// <<----- Unterschied
}
else PORTB &= ~(1<<PB3);
if (sek > 59 && sek < 119) PORTB |= (1<<PB0);
else PORTB &= ~(1<<PB0);
}
return 0;
}
/*************
Funktionen
**************/
// Timer 1ms
void Timer0_init(void)
{
TCCR0 = (1<<WGM01); // Timer im CTC-Modus
TCCR0 |= (1<<CS00) | (1<<CS01); // Prescaler auf 64
OCR0 = 234; // um ca. 1ms zu erreichen
TIMSK |= (1<<OCIE0); // Interrupt "TIMER0_COMP_vect" aktivieren
}
/*************
Interrupts
**************/
ISR (TIMER0_COMP_vect)
{
blink_hz++;
switch (blink_hz)
{
case 499: blink = 1; sek++; break; // <<----- Unterschied
case 999: blink = 0; blink_hz = 0; break;
default: break;
}
}
greez
ich habe erst neu mit Microcontroller / Robotik angefangen und arbeite mich nun langsam durch den Stoff und hier durchs Forum :).
Nun hatte ich ein Problem, konnte dieses zwar Lösen, verstehe aber nicht warum nicht beides funktioniert.
Funktion:
Es soll LED3 (PB3) blinken. Nach ca. einer Minute soll die LED0 (PB0) leuchten, nach einer weiteren Minute dann LED0 aus und LED1 (PB1) an usw.
Ergebnis Code1:
LED3 blinkt wie gewünscht, aber die andere LEDs blinken von Anfang an auch ganz wild und unvorhersehbar.
Ergebnis Code2:
Nach etwas probieren (Interrupts während den IF-Anweisungen ausschalten usw.) hab ichs dann wie in Code2 geändert und nun tut es.
Nun hoffe ich, dass mir jemand von euch sagen kann warum. Es müsste doch egal sein, ob ich die Sekunden in der Hauptschleife oder dem Interrupt hochzähl, hauptsache ich deklariere die Variable als volatile, damit der Compiler das richtig umsetzt.
Wenn es jemand Testen will, ich arbeite mit einem NiboBee.
(Die stellen, welche sich unterscheiden sind mit " // <<----- Unterschied" markiert)
Code1 (funktioniert nicht):
#include <avr/io.h> // allgemeine Headerdatei
#include <stdint.h> // für standardisierten Typen z.B. int8_t
#include <avr/interrupt.h> // fuer sei() => Aktivieren, cli() => ausschalten und ISR():
// Prototypen
void Timer0_init(void);
// Globale Variable
volatile uint16_t blink_hz = 0;
volatile uint8_t blink = 0;
// <<----- Unterschied
int main(void)
{
// IO's init
Timer0_init();
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3); // LED's
// Variable
volatile uint8_t sek = 0; // <<----- Unterschied
// Globale Interrupts erlauben
sei();
while(1)
{
if(blink)
{
PORTB |= (1<<PB3);
sek++; // <<----- Unterschied
}
else PORTB &= ~(1<<PB3);
if (sek > 59 && sek < 119) PORTB |= (1<<PB0);
else PORTB &= ~(1<<PB0);
}
return 0;
}
/*************
Funktionen
**************/
// Timer 1ms
void Timer0_init(void)
{
TCCR0 = (1<<WGM01); // Timer im CTC-Modus
TCCR0 |= (1<<CS00) | (1<<CS01); // Prescaler auf 64
OCR0 = 234; // um ca. 1ms zu erreichen
TIMSK |= (1<<OCIE0); // Interrupt "TIMER0_COMP_vect" aktivieren
}
/*************
Interrupts
**************/
ISR (TIMER0_COMP_vect)
{
blink_hz++;
switch (blink_hz)
{
case 499: blink = 1; break; // <<----- Unterschied
case 999: blink = 0; blink_hz = 0; break;
default: break;
}
}
Code2 (funktioniert):
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
// Prototypen
void Timer0_init(void);
// Globale Variable
volatile uint16_t blink_hz = 0;
volatile uint8_t blink = 0;
volatile uint8_t sek = 0; // <<----- Unterschied
int main(void)
{
// IO's init
Timer0_init();
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3); // LED's
// Globale Interrupts erlauben
sei();
while(1)
{
if(blink)
{
PORTB |= (1<<PB3);
// <<----- Unterschied
}
else PORTB &= ~(1<<PB3);
if (sek > 59 && sek < 119) PORTB |= (1<<PB0);
else PORTB &= ~(1<<PB0);
}
return 0;
}
/*************
Funktionen
**************/
// Timer 1ms
void Timer0_init(void)
{
TCCR0 = (1<<WGM01); // Timer im CTC-Modus
TCCR0 |= (1<<CS00) | (1<<CS01); // Prescaler auf 64
OCR0 = 234; // um ca. 1ms zu erreichen
TIMSK |= (1<<OCIE0); // Interrupt "TIMER0_COMP_vect" aktivieren
}
/*************
Interrupts
**************/
ISR (TIMER0_COMP_vect)
{
blink_hz++;
switch (blink_hz)
{
case 499: blink = 1; sek++; break; // <<----- Unterschied
case 999: blink = 0; blink_hz = 0; break;
default: break;
}
}
greez