Habe den Timer1 mit 64 als Vorteiler aktiv und verwende 7.3728MHz.
Interrupts werden ca alle 0,569 Sekunden ausgelöst.
Nun möchte ich aber einen separaten Counter die Interrupts hochzählen
und später z.B. nach dem 10 Interrupt was anderes ausführen.
Daher dachte ich an dem Modulo Operator.
Ganz banal sollen die LEDs nach und nach aufblinken und wieder ausgehen.
Leider keine Lösung für dein Problem, dafür ein paar Anmerkungen:
cli();
sei();
habe nichts in der ISR zu suchen, du schaffst damit nur neue Probleme.
#ifndef F_CPU
# define F_CPU 7372800 /* 7.3728 MHz */
#endif
ist auch fehleranfällig, du bekommst nicht mit wenn F_CPU auf einen
andere Wert gesetzt ist. Lass es komplett weg und setze es im Projekt.
Peter II schrieb:> Leider keine Lösung für dein Problem, dafür ein paar Anmerkungen:>> cli();> sei();>> habe nichts in der ISR zu suchen, du schaffst damit nur neue Probleme.
Da ich parallel noch die ADC Eingänge nutze und den Analog Comperator,
muss ich doch bei einem Interrupt andere zunächst ausblenden?
Oder geraten die anderen Interrupts dann in Warteschleife?
Meine LED PD1 müsste prinipiell dann leuchten wenn Interrupt das zweite
mal ausgeführt wird. Also quasi wenn erste LED an PD0 aus ist.
Aber es ist nicht ganz rund. Mal leuchten 5 Sekunden lang beide im Takt
an und aus und mal eben richtig versetzt.
Rene Müller schrieb:> Da ich parallel noch die ADC Eingänge nutze und den Analog Comperator,> muss ich doch bei einem Interrupt andere zunächst ausblenden?> Oder geraten die anderen Interrupts dann in Warteschleife?
die Atmels können nur eine ISR gleichzeitig bearbeiten. Diese Sperre
hebelst du mit deinem Code aus. Damit wird im schlimmsten Fall die 2.ISR
schon ausgeführt obwohl die 1.ISR nicht zu ende ist.
Peter II schrieb:> die Atmels können nur eine ISR gleichzeitig bearbeiten. Diese Sperre> hebelst du mit deinem Code aus. Damit wird im schlimmsten Fall die 2.ISR> schon ausgeführt obwohl die 1.ISR nicht zu ende ist.
Genau deswegen cli() um keine Interrupts zuerlauben während ein
Interrupt läuft oder nicht?
Ging davon aus,dass man genau aus diesem Grund in einem Interrupt andere
Interrupts nicht erlaubt.
Rene Müller schrieb:> Genau deswegen cli() um keine Interrupts zuerlauben während ein> Interrupt läuft oder nicht?> Ging davon aus,dass man genau aus diesem Grund in einem Interrupt andere> Interrupts nicht erlaubt.
cli() am Anfang ist unnötig, weil das schon die Hardware selber macht ->
siehe Datenblatt
sei() ist das Problem, denn damit schaltest du die Interrupts ein,
obwohl du noch in der ISR bist. Es müssen ja noch Daten von Stack
gelöscht werden und das Prozessorregister widerherstellt werden.
Danke!
Wenn ich in der While Schleife nach jedem Durchlauf ein Port auslese um
dementsprechend das Programmlaufen lassen möchte: Hier Analog Comperator
oder ADC Einlesung.
Ist es für diese Abfrage sinnvoll Interrupts nicht zu zulassen?
>Meine LED PD1 müsste prinipiell dann leuchten wenn Interrupt das zweite>mal ausgeführt wird. Also quasi wenn erste LED an PD0 aus ist.>Aber es ist nicht ganz rund. Mal leuchten 5 Sekunden lang beide im Takt>an und aus und mal eben richtig versetzt.
Du hast ein Problem mit atomaren Zugriffen.
counter kann sich ändern wenn du in der main()
darauf zugreifst. Genauso ist ^= beim Port nicht atomar.
Der ganze Block muss unter Interruptsperre:
holger schrieb:> Du hast ein Problem mit atomaren Zugriffen.> counter kann sich ändern wenn du in der main()> darauf zugreifst. Genauso ist ^= beim Port nicht atomar.> Der ganze Block muss unter Interruptsperre:
In der Tat. Danke, habe dennoch gelegentlich aussetzer. Liegt das daran,
dass ein Interrupt ausgelöst werden möchte gerade wenn es gesperrt wird?
Müsste das nicht ziemlich unwahrscheinlich sein bei über 7MHz.
Vorallem wenn nun wirklich nur noch dieser Quellcode genutzt wird:
1
intmain(void)
2
{
3
DDRB=0xFF;// Blaue LED: Ausgang
4
DDRB&=~((1<<DDB2)|(1<<DDB3));// PB2 und PB3 Eingänge
>Nach 2 Wellen ist alles Chaos. Wird doch irgendwie machbar sein eine>Lichterwelle konstant und sicher laufen zu bekommen?
Natürlich geht das. Frag dich mal ob du wirklich jeden
main() Zyklus deine Ports xoren willst? Oder vieleicht
nur wenn counter sich ändert?
Omg schrieb:> ;)
Für den Zweck an sich sehr nice.
Nur möchte ich in Zukunft kontinuierlich 8 ADC Eingänge permanent
einlesen und bei einem Tastendruck einen Timer aktivieren, während
dessen soll bei einem gewissen Zeitintervall wo der Knopf erneut
gedrückt wird das Eingangssignal switchen, welches gerade am Display
ausgegeben wird. Und zuletzt nach einer gewissen Zeit ohne jeglichem
Tastendruck in den Ursprungsmodus/Anzeige zurückswitcht.
Kurz: Wenn möglich sicher 2 Prozesse parllel laufen.
holger schrieb:> Natürlich geht das. Frag dich mal ob du wirklich jeden> main() Zyklus deine Ports xoren willst? Oder vieleicht> nur wenn counter sich ändert?
So funktioniert aktuell dann gar nichts. Ich denke mal, dass sich Deine
Idee für ein Programm eignet, wo auch deutlich mehr Inhalt ist als der
Timer an sich. So sperrt er fast durchgehend die Interrupts :(.
>So funktioniert aktuell dann gar nichts.
Was funktioniert nicht?
> Ich denke mal, dass sich Deine>Idee für ein Programm eignet, wo auch deutlich mehr Inhalt ist als der>Timer an sich. So sperrt er fast durchgehend die Interrupts :(.
Dann mach halt ein _delay_ms(10); in die Mainloop mit rein;)
Die Interruptsperre ist dann nur zu 0,00002% aktiv und den
Rest der Zeit wird heisse Luft erzeugt.
>>So funktioniert aktuell dann gar nichts.>>Was funktioniert nicht?
Bei mir funktioniert es nach meinem Vorschlag. Allerdings an PORTB.
PB0 blinkt perfekt. PB1-6 gehen nacheinander an und
dann nacheinander aus. Also was erzählst du für einen Blödsinn?
>die neuere Atmels könnne auch einen Pin Togglen und das Atomar, dann>braucht man die sperre auch nicht.
Das geht dann aber auch nur für neuere Atmels.
Schade das da ein Post gelöscht wurde.
Den ganzen Kram im Interrupt zu machen entspricht
auch einer Interruptsperre weil in Interrupts
Interrupts disabled sind;)
Noch mehr zum Nachdenken: Es ist ganz normal, dass es für einen µC
(kurzzeitig) nichts zu tun gibt. Damit er solche Zeitspannen nicht
pseudo-beschäftigt verbringen muss, sondern wirklich ruhen kann, hat man
den Sleep-Modus erfunden. Mach Dich darüber mal schlau.
Rene Müller schrieb:> cli();> if(counter%7==1) PORTD ^= (1<< PD1);> if(counter%7==2) PORTD ^= (1<< PD2);> if(counter%7==3) PORTD ^= (1<< PD3);> if(counter%7==4) PORTD ^= (1<< PD4);> if(counter%7==5) PORTD ^= (1<< PD5);> if(counter%7==6) PORTD ^= (1<< PD6);> sei();
Hör mit dieser blödsinnigen Interrupt-Sperrerei auf und setz diesen
Piffelkram in die ISR. Es gibt zwar die allgemeine
So-Kurz-Wie-Möglich-Empfehlung, das heisst aber nicht, dass man in der
ISR gar nichts machen darf. Und das bisschen ist so gut wie gar nichts.
Dein ganzes Timing ist völliger Mist.
LostInMusic schrieb:> Noch mehr zum Nachdenken: Es ist ganz normal, dass es für einen µC> (kurzzeitig) nichts zu tun gibt. Damit er solche Zeitspannen nicht> pseudo-beschäftigt verbringen muss, sondern wirklich ruhen kann, hat man> den Sleep-Modus erfunden. Mach Dich darüber mal schlau.
und wozu? Ihm wird schon nicht langweile wenn er in einer schleife NOP
ausführt.
Bei einen Gerät was nicht grade an einer Batterie hängt, macht der Sleep
wenig sinn. Denn Sleep wurde zum Energiesparen eingebaut.
Die ersten PCs haben auch nicht geschlafen, weil es einfach keinen Sinn
gemacht hat.
holger schrieb:>> switch(Counter % 7)>> Beim Überlauf von counter geht wieder alles durcheinander;)> Schon mal drüber nachgedacht?
Nö. Aber dann lässt man ihn einfach nicht überlaufen.
1
...
2
Counter++;
3
if(Counter==253)Counter=0;
16 Bit für den Counter ist sowieso Quatsch. Genauso wie Modulo. von 0 -
6 durchzählen reicht für das Programm oben auch. Genauso wie es Perlen
vor die Säue werfen ist, den 16-Bit Timer zu benutzen. Dafür reicht ein
8-Bit Timer dicke.
mfg.
>macht der Sleep wenig sinn.
Für mich macht das, was der µC ohne Sleep tun muss, noch weniger Sinn.
Schaden nimmt der µC in beiden Fällen keinen.
>Denn Sleep wurde zum Energiesparen eingebaut.
Ja. Deshalb sind anderweitige Verwendungen aber nicht verboten.
>Die ersten PCs haben auch nicht geschlafen, weil es einfach keinen Sinn>gemacht hat.
Oder weil es mangels Sleepmodus keine Alternative gab? ;-)
Wow, so viel Antworten, Danke. Werde dies versuchen umzusetzen.
Prinzipiell spricht doch nicht gegen einen 16Bit Timer1 anstelle 8Bit
Timer0?
Der Mikrocontroller wird später keinen Leerlauf mehr haben. Er soll
permanent von PA0 bis PA7 die ADC Werte der Signale einlesen und
vergleichen. Je nach Schwellwert einen ASCI Code entsprechend am
Bildschirm ausgeben.
Daher sollte der Timer und die Interrupts so unabhängig wie möglich sein
und keinen Einfluss auf Interpretation der Signale haben.
Thomas Eckmann schrieb:> ISR(TIMER0_OVF_vect)> {> static unsigned char PreCounter = 0;> static unsigned char Counter = 0;
Besser die Variablen nicht im Interrupt immer neu deklarieren sondern
einmal außerhalb der ISR.
Rene Müller schrieb:> Besser die Variablen nicht im Interrupt immer neu deklarieren sondern> einmal außerhalb der ISR.
Was der Compiler auch macht - kein Unterschied, nur ist die Deklaration
in der ISR übersichtlicher.
Rene Müller schrieb:> Thomas Eckmann schrieb:>> ISR(TIMER0_OVF_vect)>> {>> static unsigned char PreCounter = 0;>> static unsigned char Counter = 0;>> Besser die Variablen nicht im Interrupt immer neu deklarieren sondern> einmal außerhalb der ISR.
Besser erst mal ergründen, was 'static' eigentlich macht und dann
darüber nachdenken, warum wohl Thomas den Scope der Variablen auf die
ISR beschränken möchte.
Das hat nämlich dann auch was mit sog. 'defensivem Programmieren' zu
tun.