Hallo,
ich möchte auf einem Evaluation Board LEDs blinken lassen. Die LEDs
sollen in der ISR ein- und ausgeschaltet werden. Dazu benutze ich einen
Timer, der alle 0,5s einen Interrupt auslöst. Bei jedem Interrupt soll
sich der LED-Zustand ändern.
Das Problem ist, dass die LEDs immer eingeschaltet sind.
Da mir diese Lösung nahegelegt wurde und ich selbst nicht unbeding eine
Ahnung von Zustandsmaschinen habe, bitte ich euch um Hilfestellung.
Im Anhang habe ich die ISR-Routine beigefügt.
Gruß Jens
Jens K. schrieb:
> Das Problem ist, dass die LEDs immer eingeschaltet sind.
Logisch, das erste, was du in der ISR auch machst, ist "Zustand" auf
"LED_Ein" zu setzen.
Ersetze
sind korrekt?
Die ISR wird regelmässig aufgerufen?
Wie schnell wird die eigentlich aufgerufen? (*)
Wenn die mehr als, sagen wir mal 30 mal in der Sekunde aufgerufen wird,
wirstdu das Blinken nicht mehr sehen.
(*) Ich zieh die Frage zurück und stelle eine Neue
> Dazu benutze ich einen Timer, der alle 0,5s einen Interrupt auslöst.
Hast du das kontrolliert?
Karl heinz Buchegger schrieb:
> Diese Dinge hier> AT91C_BASE_PIOA->PIO_CODR = LED_AUSGABE; // LED on>> AT91C_BASE_PIOA->PIO_SODR = LED_AUSGABE; // LED off> sind korrekt?
das ist korrekt.
Der Timer ist so eingestellt, dass die ISR-Routine alle 0,5s aufgerufen
werden sollte.
Wie kann ich denn überprüfen, wie oft uns schnell sie aufgerufen wird?
Jens K. schrieb:
> Karl heinz Buchegger schrieb:>> Diese Dinge hier>> AT91C_BASE_PIOA->PIO_CODR = LED_AUSGABE; // LED on>>>> AT91C_BASE_PIOA->PIO_SODR = LED_AUSGABE; // LED off>> sind korrekt?>> das ist korrekt.> Der Timer ist so eingestellt, dass die ISR-Routine alle 0,5s aufgerufen> werden sollte.> Wie kann ich denn überprüfen, wie oft uns schnell sie aufgerufen wird?
Led blinken lassen :-)
(Jetzt haben wir ein Henne/Ei Problem)
Probier mal sowas
1
enum{LED_Ein,LED_Aus};
2
3
__ramfuncvoidISR_Clock_Ausgabe(void)
4
{
5
staticU8Zustand=LED_Ein;
6
staticU8Counter=0;
7
8
Counter++;
9
if(Counter==10){
10
Counter=0;
11
12
switch(Zustand)
13
{
14
caseLED_Ein:
15
AT91C_BASE_PIOA->PIO_CODR=LED_AUSGABE;// LED on
16
Zustand=LED_Aus;
17
break;
18
19
caseLED_Aus:
20
AT91C_BASE_PIOA->PIO_SODR=LED_AUSGABE;// LED off
21
Zustand=LED_Ein;
22
break;
23
24
default:
25
break;
26
}
27
}
28
}
und dann schraubst du die 10 hoch, bis
* du bei einer sehr großen Zahl angelangt bist
* oder die LED irgendwann zu flimmern und dann zu blinken anfängt
In deinem Code ist jedenfalls nichts zu entdecken, warum das kein
Blinken stattfinden sollte.
Hast du vielleicht noch eine 2-te LED zur Verfügung?
Wenn ja, dann schalte die mal hier
1
if(Counter==10){
2
Counter=0;
3
4
....hierLEDeinschalten
zusätzlich ein und sieh nach, ob das passiert (dann weist du, dass die
ISR aufgerufen wird.
Auch den Gegentest machen: dort die LED ausschalten
Ich habe deinen Vorschlag ausprobiert Karl Heinz.
Die zweite LED leuchtet, also die ISR wird aufgerufen
Nachdem ich den Counter-Wert bis auf 300.000 hochgeschraubt habe, blinkt
die LED nunannäherng mit 1 Hz.
Es scheint also an der Timereinstellung zu liegen!?
Jens K. schrieb:
> Nachdem ich den Counter-Wert bis auf 300.000 hochgeschraubt habe
Ich hoffe du hast auch berücksichtigt, dass ein U8 (8 Bit Datentyp?) von
Haus aus nur bis 255 zählen kann :-)
> Es scheint also an der Timereinstellung zu liegen!?
Sieht wohl so aus :-)
Kann es sein, dass deine 0.5 sich nicht auf Sekunden sondern auf
Millisekunden bezieht?
Karl heinz Buchegger schrieb:
> Ich hoffe du hast auch berücksichtigt, dass ein U8 (8 Bit Datentyp?) von> Haus aus nur bis 255 zählen kann :-)
Natürlich (habe auf 32 Bit angepasst)!
Ich habe was Lustiges festgestellt. Ändere ich die Timereinstellungen,
dann ändert sich nichts an dem Takt; das heißt, die LED blinkt mit dem
gleichen Takt weiter. Wie kann das denn sein???
Jens K. schrieb:
> Karl heinz Buchegger schrieb:>> Ich hoffe du hast auch berücksichtigt, dass ein U8 (8 Bit Datentyp?) von>> Haus aus nur bis 255 zählen kann :-)>> Natürlich (habe auf 32 Bit angepasst)!
Brav.
War nur so, dass mir 300000 ein wenig hoch vorgekommen ist.
> Ich habe was Lustiges festgestellt. Ändere ich die Timereinstellungen,> dann ändert sich nichts an dem Takt; das heißt, die LED blinkt mit dem> gleichen Takt weiter. Wie kann das denn sein???
Richtiger Timer benutzt?
(Keine Ahnung. Ich hab ja noch nicht einmal rausgefunden welchen µC du
benutzt. Ein AVR-Mega oder Tiny ist es nicht. Und von anderen µC versteh
ich nichts)
Ich benutze den AT91SAM7S256 - µC.
Das komische ist, dass ich vorher was Anderes programmiert hatte mit
genau denselben Timereinstellungen, allerdings wurde dort der Takt in
der ISR ausgegeben, ohne zwischendurch daraus zu gehen.
Noch eine Frage Karl Heinz:
Könnte es sein, dass die ISR nach dem ersten Durchlauf sofort wieder
aufgerufen wird, weil der Interrupt nicht zurückgesetzt wurde?
Stefan Ernst schrieb:
> Logisch, das erste, was du in der ISR auch machst, ist "Zustand" auf> "LED_Ein" zu setzen.
hier stehts geschrieben !!!!
nimm die definition der Variable "Zustand" aus der Interrupt Routine
raus !!!
du initialisierts sie bei jedem Aufruf von neuem und zwar immer gleich
!!!
und vergiss nicht die geschichte mit dem volatile ...
gruss Claudio
ps: die Variable Counter sollte auch nicht in der ISR definiert und
initialisiert werden.
Karl heinz Buchegger schrieb:
> In deinem Code ist jedenfalls nichts zu entdecken, warum das kein> Blinken stattfinden sollte.
sorry da kann ich nicht schweigen ....
natürlich ist da was faul ...
probier mal das :
varliablen die in ISR verändert werden müssen als volatile declariert
werden, ansonsten könnte der Compiler die Zugriffe wegoptimieren.
Da diese Variablen aber asynchron (zufällig) von der ISR verändert
werden können dürfen Lesezugriffe nicht wegoptimiert werden...
das sieht dann in etwa so aus :
Hasst du einen Debugger, mit dem du übeprüfen kannst ob du in die
Routine Springst ? und kanns du damit feststellen ob das Interruptbit
wieder Gelöscht wird? allefalls musst du das Timerinterruptbit wieder
löschen.
gastlich schrieb:
> Stefan Ernst schrieb:>> Logisch, das erste, was du in der ISR auch machst, ist "Zustand" auf>> "LED_Ein" zu setzen.>> hier stehts geschrieben !!!!>> nimm die definition der Variable "Zustand" aus der Interrupt Routine> raus !!!
Nö.
Dieser Punkt ist schon längst abgehakt.
Die Variable ist static und anstatt der Zuweisung hat er jetzt eine
Initialisierung.
Das ist soweit alles korrekt.
gastlich schrieb:
> Karl heinz Buchegger schrieb:>> In deinem Code ist jedenfalls nichts zu entdecken, warum das kein>> Blinken stattfinden sollte.>> sorry da kann ich nicht schweigen ....>> natürlich ist da was faul ...
Jungs.
Lernt C!
Ich weiß, das static immer wieder für Verwirrungen sorgt. Aber das ist
alles korrekt, so wie er das macht.
> varliablen die in ISR verändert werden müssen als volatile declariert
Und wenn du schon dabei bist, lies auch noch mal über volatile nach und
wann man diesen Modifier tatsächlich benötigt und warum.
Jens K. schrieb:
> Noch eine Frage Karl Heinz:>> Könnte es sein, dass die ISR nach dem ersten Durchlauf sofort wieder> aufgerufen wird, weil der Interrupt nicht zurückgesetzt wurde?
Hmm.
Kann ich dir nicht sagen. Da musst du das Datenblatt zum Prozessor
befragen. Es wär zwar unüblich, aber möglich wärs.
soll ichs noch ausführen ?
ISR {
//initialisierung der varibale Zustand
//verwender der varibale zustand
//verändern der variable zustand
}
meiner meinung nach wir beim verwenden der varibale immer der gleiche
wert drin stehen ... es sei denn der compiler verschiebt wie durch ein
wunder die intialisierung aus der isr raus .....
und komm jetzt nicht mit static und so ... die initialisierung findet in
der isr statt ...
sorry geb mich geschlagen, static macht tasächlich, das die
intialisierung nur einmal stattfindet ...
sehr verwirrend ...
aber das mit dem isr-flag könnte das problem sein ...
gastlich schrieb:
> soll ichs noch ausführen ?>> ISR {>> //initialisierung der varibale Zustand>> //verwender der varibale zustand>> //verändern der variable zustand>> }>> meiner meinung nach wir beim verwenden der varibale immer der gleiche> wert drin stehen ...
Deine Meinung steht in starkem Kontrast zu dem was die ISO-Norm für C
dem Compiler vorschreibt was zu passieren hat.
> es sei denn der compiler verschiebt wie durch ein> wunder die intialisierung aus der isr raus .....
(Hinter vorgehaltener Hand:
letzten Endes bleibt dem Compiler nichts anderes übrig. Das definieren
der static Variablen in einer Funktion limitiert lediglich den Scope
unter dem die Variable sichtbar ist, auf die Funktion. Im Grunde hat man
damit eine File-globale Variable erzeugt, die allerdings nur in dieser
Funktion zugänglich ist. Und genau genommen findet die Intialisierung
beim ersten Betreten der Funktion statt. Findet die Intialisierung aber
mit einer Konstanten statt, kann kein Mensch den Unterschied
herausfinden, denn wie gesagt: Ausserhalb der Funktion existiert die
Variable offiziell gar nicht)
>> und komm jetzt nicht mit static und so ... die initialisierung findet in> der isr statt ...
Es ist im C-Standard exakt geregelt, was mit der Initialisierung einer
Variablen in einer Funktion zu geschehen hat.
gastlich schrieb:
> hab mal in meinen Routinen nachgeschaut, da kommt diese zeile in der> timer ISR vor :> tmp = AT91C_BASE_TC0->TC_SR;
das hat leider auch nichts gebracht...
Ich poste nochmal die aktuelle ISR.
Jens K. schrieb:
> gastlich schrieb:>> hab mal in meinen Routinen nachgeschaut, da kommt diese zeile in der>> timer ISR vor :>> tmp = AT91C_BASE_TC0->TC_SR;>> das hat leider auch nichts gebracht...>> Ich poste nochmal die aktuelle ISR.
Die ISR wird nicht viel bringen.
Du musst im Datenblatt nachlesen:
Timereinstellung
Wie ist das Interrupt Flag zu handhaben
Jens K. schrieb:
> gastlich schrieb:>> hab mal in meinen Routinen nachgeschaut, da kommt diese zeile in der>> timer ISR vor :>> tmp = AT91C_BASE_TC0->TC_SR;>> das hat leider auch nichts gebracht...>> Ich poste nochmal die aktuelle ISR.
Leute, Entwarnung!
gastlich hat mit der obigen Aussage ins Schwarze getroffen. Ich habe nur
vergessen, dass der Timer auf 250 kHz eingestellt war und nicht auf 1
Hz. Jedenfalls funktioniert jetzt alles richtig!
Ich bedanke mich herzlich für Eure Hilfe!!!