Hallo!
Ich habe folgendes "Konstrukt" :
ISR (TIMER2_OVF_vect)
{
pause=pause+1;
switch (pause)
{
case 1:
PORTC=0b11111110;
break;
case 3:
PORTC=0b11111101;
break;
case 5:
PORTC=0b11111011;
break;
usw usw usw bis:
case 11:
PORTC=0b11011111;
pause=0;
break;
default:
PORTC=0xFF;
break;
}
}
Wenn ich mir jetzt Port 0 und Port 1 auf dem Oszilloskop anschaue sehe
ich das auf das "low" von Port 0 unmittelbar das "low" von Port 1 folgt.
Ich beabsichtige aber das zwischen den beiden "lows" ein Abstand ist.
Daher nehme ich bei den case Anweisungen ungerade Zahlen.
Was übersehe ich?
Danke schonmal!
Attila Ciftci schrieb:> Ich beabsichtige aber das zwischen den beiden "lows" ein Abstand ist.> Daher nehme ich bei den case Anweisungen ungerade Zahlen.
Wie schnell läuft denn dein Timer? Und wie lange willst du pausieren
zwischne den Zusänden?
Schon gerechnet?
Ich betrachte nur Bit 0 und Bit 1 (im Moment!)
Wie schnell der Timer läuft ist ja eigentlich nicht wesentlich. "pause"
wird bei jedem interrupt eins hochgezählt. Daher sollte ja bei pause =
2, 4, 6 ,8 und 10 der "default" Fall eintreten und alle Pins "high"
sein. Dem ist aber laut meinem Oszilloskop nicht so sondern case 3 folgt
unmittelbar case 1.
Pullups sind deaktiviert. Es ist ein Atmega 8.
@Karl Heinz: Die Variable pause kommt nur in der ISR vor.
@Mini Float: Danke! Sehr interessanter Ansatz den ich aber erst
vollständig verstehen muss.
Zur weiteren Verdeutlichung: An den Ports hängen 6 LEDs die im Prinzip
so Multiplexing-mässig angefahren werden. Funktioniert auch und hätte
ich mir das im Oszi nicht angeschaut hätte ich garnicht bemerkt das der
default-Fall nicht ausgeführt wird.
Attila Ciftci schrieb:> @Karl Heinz: Die Variable pause kommt nur in der ISR vor.
Zeigs trotzdem.
> Zur weiteren Verdeutlichung: An den Ports hängen 6 LEDs die im Prinzip> so Multiplexing-mässig angefahren werden. Funktioniert auch und hätte> ich mir das im Oszi nicht angeschaut hätte ich garnicht bemerkt das der> default-Fall nicht ausgeführt wird.
Er wird ausgeführt. Verlass dich drauf. Wenn du am Oszi nichts erkennen
kannst, dann gibt es noch einen Fehler in deinem Programm.
Mini Float schrieb:> Bitte zerfleischt mich!!
Gerne :).
Attila Ciftci schrieb:> @Mini Float: Danke! Sehr interessanter Ansatz den ich aber erst> vollständig verstehen muss.
Das sollte Dir zeigen, dass dieser Ansatz in real-world-Programmen, die
nicht write-only sind, großer Mist ist. Deine Lösung vom Anfang kann
jeder halbwegs brauchbare Programmierer ohne Stift+Papier durch
Draufsehen verstehen und ändern, das Macho-C von Mini-Float eher nicht.
Lieber Karl Heinz!
Wenn ich hier mein Programm veröfentliche dann wird es (wie schon einige
male passiert) dazu führen dass hier ein blutiger C Anfänger demontiert
wird und , wie man ja bereits sehen kann, am Thema vorbei gepostet wird.
Wetten? ;-)
Nur damit alle Beteiligten noch einmal wissen worum es mir geht: Warum
wird der default -Fall (scheinbar?) nicht ausgeführt?
Attila Ciftci schrieb:> Lieber Karl Heinz!>> Wenn ich hier mein Programm veröfentliche dann wird es (wie schon einige> male passiert) dazu führen dass hier ein blutiger C Anfänger demontiert> wird
demontiert würde ich nicht sagen.
Letzten Endes wirst da ja aus solchen Diskussionen immer etwas
mitgenommen haben.
> Nur damit alle Beteiligten noch einmal wissen worum es mir geht: Warum> wird der default -Fall (scheinbar?) nicht ausgeführt?
Ein Messfehler ist von deiner Seite her ausgeschlossen?
(Du musst es fir zur Gewohnheit machen, dass deine erste Annahme nie
darin besteht, dass der Compiler oder der µC Mist macht. In 99% der
Fälle sitzt das Problem immer vor dem Bildschirm)
In deinem Programm ist kein Grund erkennbar, warum der default Zweig
nicht ausgeführt werden sollte.
PS: Bist du daran interessiert, wie du dein Programm vereinfachen
kannst? Du bist nämlich reif für Arrays.
Attila Ciftci schrieb:> Wenn ich hier mein Programm veröfentliche dann wird es (wie schon einige> male passiert) dazu führen dass hier ein blutiger C Anfänger demontiert> wird und , wie man ja bereits sehen kann, am Thema vorbei gepostet wird.>> Wetten? ;-)
Steh drüber und lerne:
@Karl Heinz: Ja natürlich! Darum habe ich mich auch bei Mini Float
(ehrlich und NICHT zynisch) bedankt und auch zu verstehen gegeben das
meine C Kenntnisse nicht ausreichen um vollständig zu verstehen was er
da eigentlich gemacht hat.Die Idee etwas davon abhängig zu machen ob es
durch 2 teilbar ist finde ich spannend.
Auf meinem Oszi sehe ich zwei Rechtecke von etwa 100us Dauer die einen
Abstand von 10 us haben um es einfach auszudrücken und eine
"Missbedienung" meinersets auszuschliessen.
Attila Ciftci schrieb:> Auf meinem Oszi sehe ich zwei Rechtecke von etwa 100us Dauer die einen> Abstand von 10 us haben um es einfach auszudrücken
Bitte nicht einfach ausdrücken!
Drück dich präzise aus!
Also doch ein Abstand dazwischen?
So?
-------+ +---------------------------
| |
+-------+
--------------------+ +-------------
| |
+--------+
| 100 | 10 | 100 |
Attila Ciftci schrieb:> @Karl Heinz: Ja genau!
Also wird der default auch ausgeführt. Er ist der einzige Code, der
dafür sorgt, dass am Port C alle Pins auf 1 gehen.
@Karl Heinz: So gesehen hast Du recht. Aber warum nur so kurz? Die Dauer
bis zum interrupt sollte doch immer gleich sein? Egal ob der case-Fall
oder der default-Fall gilt?
Attila Ciftci schrieb:> @Karl Heinz: So gesehen hast Du recht. Aber warum nur so kurz? Die Dauer> bis zum interrupt sollte doch immer gleich sein? Egal ob der case-Fall> oder der default-Fall gilt?
richtig.
Aber an dem Rätsel grüble ich noch :-)
10us sind für einen AVR zuviel um das als "systembedingt" zu betrachten
oder? Also im Sinne von: Verarbeitungszeit bis der nächste Pin
geschaltet wird?
Tu mir einen Gefallen.
Ändere dein Programm mal so um.
1
ISR(TIMER2_OVF_vect)
2
{
3
staticunsignedintdelay=0;
4
5
delay++;
6
if(delay<31250)
7
return;
8
delay=0;
9
10
// ab hier so wie es vorher auch war
11
12
pause=pause+1;
13
14
...
15
}
das verlangsamt das Umschalten, so dass nur etwa jede 1 Sekunde pause um
1 weitergeschaltet wird. Dann kann man an den LED selber sehen, wie
lange sie leuchten und wie lange die Dunkelphase dazwischen ist.
Attila Ciftci schrieb:> 10us sind für einen AVR zuviel um das als "systembedingt" zu betrachten> oder?
10us = 10 * 10E-6
viel zu viel
Bei 8 Mhz arbeitet den µC da immerhin 80 Befehle ab.
Niemand schrieb:> Hi,> Du änderst die switch() variable innerhalb des "switch". Könnte mir> vorstellen, dass einige Compiler da Mist generieren.
Du meinst im case 15?
Nö, das ist in Ordnung. Das bringt keinen Compiler in Schwierigkeiten.
Attila Ciftci schrieb:> @Karl Heinz: Hab ich gemacht. Jetzt gehen die LEDs etwa im> 2-Sekundentakt nacheinander an.
ohne Pause dazwischen?
IMHO müsste es so sein.
LED 0 leuchtet
1 Sekunde
LED 0 geht aus
1 Sekunde
LED 1 leuchtet
1 Sekunde
LED 1 geht aus
1 Sekunde
....
Kommentiere mal bitte alles, was im while(1)-Block steht, aus. Du
verwendest da munter (vermutlich) vorzeichenbehaftete Variablen
unterschiedlicher Länge und weist sie dann einem (vorzeichenlosen)
Register (8 Bit? 16 Bit? Konnte keinen CPU-Typ finden; hab ich ihn
überlesen?) zu, ohne irgendwelche Prüfungen auf Über-/Unterläufe bei
Deinen Additionen und Subtraktionen.
@Patrick: Mache ich sobald ich wieder nüchtern bin ;-) Könnte denn das
was in der while Schleife passiert Einfluss auf den default-Fall in der
ISR haben? Ich kann es mir nicht recht vorstellen.
Attila Ciftci schrieb:> Eher etwa 2 Sekunden an und 2 Sekunden aus. Ansonsten so wie Du es> beschreibst.
OK. Die 2 Sekunden sind mir zwar nicht klar, rein rechnerisch müssten
sich bei 8Mhz 1 Sekunde ergeben (*), aber wenn die Pause gleich lang wie
das Leuchten ist, dann ist alles in Ordnung.
(* ausser ich hab mich verrechnet. Mag sein)
Nicht im default-Fall, aber in case 1 beschreibst Du ja OCR2 mit
dimm1/1000. D. h. wenn Timer 2 8 Bit breit ist, kriegt OCR2 nur die 8
LSB ab; das kann natürlich zu witzigen Effekten führen.
@Patrick: Ich habe grade vor das while ein weiteres while(1) gesetzt.
Alle LEDs leuchten ganz leicht (Alle dimm=2000) aber wesentlich ist dass
das Bild sich auf meine Oszi nicht geändert hat.
@Patrick: Was natürlich (!!!) nicht heissen soll das ich deine Anmerkung
zu den Variablen ignoriere sondern dankend wahrnehme! Es scheint aber
nicht das Problem zu sein.
Könnte sein, dass die Divisionen durch 1000 in der ISR zu lange dauern.
Ist immerhin eine long-Division. Vielleicht zum Test mal die OCRx-Werte
in main innerhalb der while(1)-Schleife bei jeder Veränderung berechnen
und in neu zu definierende Variablen ocrnew1 .. ocrnew8, je nach
OCR-Breite unsigned char oder unsigned short, und in der ISR auf diese
Variablen statt der dimmX zugreifen.
@GS_Gast: Treffer! Versenkt! Ich habe das Teilen durch 1000 in der ISR
gelöscht und siehe da: Das Oszilloskop zeigt was ich erwartet habe.
Es ist jetzt (was schlüssig ist) 60 us Pin 0 low, 60 us beide pins high
und 60 us Pin 1 low.
Eine weitere Verbesserung wäre, den Faktor 1000 durch 1024 zu ersetzen.
Damit könnten die Divisionen jeweils durch ocrnewX = dimmX>>10; ersetzt
werden. Natürlich müssen dann die Konstanten entsprechend angepasst
werden, also 2048 statt 2000, 206848 (=1024*(202000/1000)) statt 202000
usw. Mit dieser Maßnahme bleibt in der while(1)-Schleife wesentlich mehr
Rechenzeit übrig.
@GS_Gast: ocrnewX=dimmX>>10; ???
Das kenne und verstehe ich nicht ">>10" tut was? Und wie heisst die
Operation damit ich sie suchen und nachlesen kann?
Attila Ciftci schrieb:> @GS_Gast: ocrnewX=dimmX>>10; ???>> Das kenne und verstehe ich nicht ">>10" tut was? Und wie heisst die> Operation damit ich sie suchen und nachlesen kann?
die Lektüre liefere ich bleich mit -> Bitmanipulation