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!
Gast
#2173578
Ich sehe nur, dass auf das Low von Bit 5 das Low auf Bit 0 folgt, was Du verhindern kannst, indem Du in "case 11" Pause auf -1, statt auf 0 setzt.
Gast
#2173579
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.
Dann zeig mal dein komplettes Programm. Irgendwo wirst du wohl die Variable pause noch zusätzlich vrändern.
Geht das nicht auch kürzer?
1 | |
2 | |
3 | |
4 | |
5 | |
mfg mf PS: Oder so?
1 | |
2 | |
3 | |
4 | |
5 | |
Gast
#2173615
Jepp, sollte so auch gehen, is auf jeden Fall wesentlich kompakter! Knut
@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.
Bitte zerfleischt mich!! Die "Shift"werte sehen so aus:
1 | |
2 | |
3 | |
Bei elftem Durchlauf wäre pause noch 10. So müsste es jetzt passen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
mfg mf PS: Informatiker am Bahnhof-Problem: Er zählt seine Koffer: "Null, Eins, Zwei...Sh“¡¶¢ wo ist mein DRITTER KOFFER???"
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?
Danke Tom! :-)
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.
Gast
#2173657
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:
1 | |
2 | |
3 | |
1 | |
2 | |
3 | |
Der Zugriff erfolgt aber mit rand[0] bis rand[7], da die Indexierung mit 0 beginnt.
@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 |
@... ... ...: Danke! Das mit Arrays zu lösen ist natürlich ein guter Tip!
@Karl Heinz: Ja genau!
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
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.
Gast
#2173690
Hi, Du änderst die switch() variable innerhalb des "switch". Könnte mir vorstellen, dass einige Compiler da Mist generieren.
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.
@Karl Heinz: Hab ich gemacht. Jetzt gehen die LEDs etwa im 2-Sekundentakt nacheinander an.
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 ....
Eher etwa 2 Sekunden an und 2 Sekunden aus. Ansonsten so wie Du es beschreibst.
Gast
#2173734
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)
Gast
#2173754
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.
@Karl Heinz: Hast recht, Wirklich merkwürdig. Hab grade die Fuses gecheckt und probeweise den Quarz rausgezogen. Daran scheint es nicht zu liegen.
@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.
Gast
#2173804
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.
Gast
#2174059
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?
Gast
#2174196
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
Danke!
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.