switch / case macht etwas was ich nicht verstehe

#2173411
Lesenswert?

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!
#2173589
Lesenswert?

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.
#2173616
Lesenswert?

@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.
#2173621
Lesenswert?

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???"
#2173622
Lesenswert?

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.
#2173628
Lesenswert?

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.
#2173636
Lesenswert?

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:
#2173647
Lesenswert?

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
Lesenswert?

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.
#2173663
Lesenswert?

@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.
#2173689
Lesenswert?

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 #2173734
Lesenswert?

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.
Gast #2173804
Lesenswert?

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.
Gast #2174059
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren