switch / case macht etwas was ich nicht verstehe

OP #2173411
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
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
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?
OP
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.
Geht das nicht auch kürzer?
1
ISR (TIMER2_OVF_vect)
2
{
3
   PORTC = ~(1 << (pause/2));
4
   pause = (pause == 11) ? (0) : (pause + 1);
5
}
mfg mf

PS: Oder so?
1
ISR (TIMER2_OVF_vect)
2
{
3
   PORTC = ~(1 << (pause >> 1));
4
   pause += (pause == 11) ? -11 : 1;
5
}
OP
@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
pause| 0 1 | 2 3 | 4 5 | 6 7 | 8 9 |10 11
2
-----+-----+-----+-----+-----+-----+--------
3
shift|  0  |  1  |  2  |  3  |  4  |  5

Bei elftem Durchlauf wäre pause noch 10.

So müsste es jetzt passen:
1
//So
2
ISR (TIMER2_OVF_vect)
3
{
4
   PORTC = ~(1 << (pause/2));
5
   pause = (pause == 10) ? (0) : (pause + 1);
6
}
7

8
mfg mf
9

10
//Oder eben
11
ISR (TIMER2_OVF_vect)
12
{
13
   PORTC = ~(1 << (pause >> 1));
14
   pause += (pause == 10) ? -10 : 1;
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.
OP
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?
Angehängte Dateien:
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
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
  volatile long dimm1=2000,dimm2=2000,dimm3=2000,dimm4=2000,dimm5=2000,dimm6=2000,dimm7=2000,dimm8=2000;
2
  int direct1,direct2,direct3,direct4,direct5,direct6,direct7,direct8;
3
  int eins,zwei,drei,vier,fuenf,sechs,sieben,acht;

1
  volatile long dimm[8]={2000};
2
  int direct[8];
3
  int rand[8];
Der Zugriff erfolgt aber mit rand[0] bis rand[7], da die Indexierung mit 
0 beginnt.
OP
@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   |
Tu mir einen Gefallen.
Ändere dein Programm mal so um.
1
ISR (TIMER2_OVF_vect)
2
{
3
  static unsigned int delay = 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.
Gast
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.
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
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.
Gast
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.
OP
@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
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 15 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.