Archiv verlassen und diese Seite im Standarddesign anzeigen : Interruptbehandlung bei ATMega8
Hi,
ich bau mir gerade einen "Rhythmusrobotter" :)
aus dem Rhythmusteil einer alten Elektroorgel
und 'nem ATMega8 mit 16MHz.
Dazu brauche ich an den Pins PC0 -PC3 je einen Impuls
von ca 10- 40mSek. Mit aktivem Warten hab ich's nun schon
hingekriegt, wuerd's aber lieber mit 'nem Timer Overflow Interrupt
machen.
Ich habe nun den Prescaler von Timer 0 auf 1/1024
bei einer Quarzfrequenz von 16MHz gestellt:
int Timer_Inits(void)
{
//Timer Interrupt=(Quarzfreq 16000000/8Bit-Ueberlauf 256)/ Prescaler 1024= 16mS
//letzte 3 Bit von Timer Clock Control: Prescaler = Quarz/1024:
TCCR0 = (TCCR0 | (1 << CS00) | (1 << CS02)) & (~(1 << CS01));
//Timer Interrupt Mask Register Bit 1 setzen fuer Timer Overflow Interrupt enable:
TIMSK |=(1<<TOIE0);
return 0;
}
Das sollten dann ca. 16mSek für einen Überlauf sein.
(16M / 256) / 1024.
Meine Frage ist nun, kommt das hin mit der Initialisierungsroutine?
Mit der Interruptbehandlung komme ich noch nicht so klar,
welcher Vektor ist das nun: SIGNAL (SIG_OVERFLOW0) ?
und wie bekomme ich das in meinen Code rein?
Wann muß ich die Interrupts global enabeln?
int Bass_Drum(void)
{
PORTC |= (1<<PC1); //PC1=Port fuer Bass Drum
//hier muesste dann nach einem Timer 0 Overflow
//der Pin PC1 wieder ausgeschaltet werden.
return 0;
}
Danke schonmal,
tholan
Das schaut recht vernünftig aus.
Enablen sei() an besten bevor du in die Hauptschleife kommst
while (ewig)
{
}
SIGNAL (SIG_OVERFLOW0) wird vom Timer angesprungen, die kannst du wie jede andere Funktion hinschreiben, wo du willst.
EDIT: keep rockin' !
SprinterSB
27.06.2006, 12:23
Die Initialisierung ist soweit ok. Es ist allerdings u.U. besser, TCCR0 wirklich zu setzen, damit alle Bits den gewünschten Wert haben. Sollte bei dir aber egal sein.
void Timer_Inits(void)
{
//Timer Interrupt=(Quarzfreq 16000000/8Bit-Ueberlauf 256)/ Prescaler 1024= 16mS
//letzte 3 Bit von Timer Clock Control: Prescaler = Quarz/1024:
TCCR0 = (1 << CS00) | (1 << CS02);
//Timer Interrupt Mask Register Bit 1 setzen fuer Timer Overflow Interrupt enable:
TIMSK |=(1<<TOIE0);
}
Wenn ich's recht sehe, willst du so was wie Timeouts machen: Nen Port an und nach ner bestimmten Zeit wieder aus, wahrscheinlich unterschiedliche Zeiten für die verschiedenen Ports...
Du könntest dir eine Struktur machen mit Countdown-Werten, die du setzt und die in der ISR bis aus 0 zurückgezählt werden, eine Einheit pro Tick (16ms):
typedef struct
{
uint8_t takt;
uint8_t bass;
...
} countdown_t;
volatile countdown_t countdown;
SIGNAL (SIG_OVERFLOW0)
{
uint8_t i = sizeof (countdown_t);
uint8_t * cd = (uint8_t *) &countdown;
cd += i;
do
{
uint8_t wert = *(--cd);
if (wert)
*cd = wert-1;
} while (--i);
}
Dadurch werden in jedem Tick die Elemente von countdown, die nicht 0 sind, um 1 erniedrigt.
int main()
{
ioinit();
Timer_Inits();
sei();
// Hauptschleife
while (1)
{
if (countdown.takt == 0)
{
countdown.takt = 200;
countdown.bass = 20;
PORTC |= (1 << 1);
}
if (countdown.bass == 0)
{
PORTC &= ~(1 << 1);
}
}
Hi und danke,
habe zur Veranschaulichung noch 'ne LED an PD5
gehängt und folgenden Testcode eingegeben:
#include<avr/io.h>
#include<avr/signal.h>
#define LED PD5 //Port fuer gruene LED
int Timer_Inits(void)
{
//Timer Interrupt=(Quarzfreq 16000000/8Bit Ueberlauf 256)/ Prescaler 1024= 16mS
//letzte 3 Bit von Timer Clock Control: Prescaler = Quarz/1024:
TCCR0 = (1 << CS00) | (1 << CS02);
//Timer Interrupt Mask Register Bit 1 setzen fuer Timer Overflow Interrupt enable:
TIMSK |=(1<<TOIE0);
return 0;
}
int Port_Inits(void)
{
DDRD |=(1<<LED); //Datenrichtungsregister fuer Pin5, PortD auf Ausgang
return 0;
}
SIGNAL (SIGOVERFLOW0)
{
PORTD |=(1<<LED);
}
int main(void)
{
Timer_Inits();
Port_Inits();
sei();
for(;;) //Warten auf Godot...
;
return 0;
}
Da sollte die LED doch angehen?
Der Compiler gibt keine Warnung,
aber bei der LED tut sich nix..
Hab ich noch irgendwas vergessen?
SprinterSB
27.06.2006, 15:43
Der ISR-Name muss genau stimmen, also SIG_OVERFLOW0.
Uups...
irgendwie hatte auf einmal nix mehr geklappt.
#include<avr/interrupt.h> hatte ich auch vergessen.
Weiß nur noch nicht, warum der Compiler nicht gemeckert hat,
aber egal: jetzt pfundst es.
Nu werd ich mich mal den Sternchen und Brezeln aus Deinem Beispiel
widmen, da ich noch längere Pausen für die Noten brauche.
Vielen Dank für den Code.
@tholan: sag' nicht "sternchen und Brezeln" wenn der SprinterSb in der Nähe ist.
Das ist, als wenn du einem Tischtennis Champion sagst, er spiele Ping-Pong. :mrgreen:
SprinterSB
27.06.2006, 16:26
*lach* Jepp, es gibt nix schlimmeres als in Gegenwart eines Badminton-Spielers das Wort "Fedderball" zu sagen.
Ich sach aber auch immer "Brezel" und "Teppich" und "Schniedel" oder "Schlangilon".
"Schneckennudel" SprinterSB:
Na, wenn du es so siehst, is ja nix passiert. Ich wollt halt nicht, daß er in Ungnade fällt.
SprinterSB
27.06.2006, 16:40
Nö, da braucht's schon viel schlimmeres wie Rosinen in den Apfelkuchen oder Sahne auf nen "Cappucino" oder Speck im Salat *ÖRGX*
Ähh Schneckennudel???
is das die Brezel??
...
"Schneckennudel" = Klammeraffe = "@" :-)
Is schon schlimm mit diesen Fachtermini,
aber hier werden sie jedenfalls geholfen!
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.