Forum: Mikrocontroller und Digitale Elektronik C Kontrollstruktur will nicht AVR


von Peter M. (allforone)


Lesenswert?

Hallo Freunde der Sonne,
ich habe ein Problem bei einem einfachen C-Programm. Es soll auf meinem 
MyAVR USB MK2 Board laufen. Das tut eigentlich nichts zur Sache, es ist 
ein Logikfehler, den es zu finden gilt.
1
#include <avr/io.h>
2
#include <avr/delay.h> 
3
4
 uint8_t Modus;
5
6
int main(void)
7
{
8
  DDRB |= (1<<DDB0); //PORTB0 Ausgang
9
  Modus = 1;
10
  PORTB |= (1<<PORTB0); 
11
12
  while(1==1)
13
  { 
14
    if (Modus == 1){ //!!!!!Hier
15
    
16
      for(int i = 0;i>30;i++){
17
        
18
        if (!(PORTB & (1<<PORTB0))){
19
          PORTB |= (1<<PORTB0);
20
          }
21
        else{
22
          PORTB &= ~(1<<PORTB0);
23
          }
24
        _delay_ms(90);
25
      }  
26
      Modus+=1;
27
    }
28
    
29
    if (Modus == 2){
30
    
31
      for(int i = 0;i>30;i++){
32
  
33
        if (!(PORTB & (1<<PORTB0))){
34
          PORTB |= (1<<PORTB0);
35
        }
36
        else{ 
37
          PORTB &= ~(1<<PORTB0);
38
        }
39
        _delay_ms(45);
40
      }            
41
      Modus += 1; //!!!!!Hier
42
    }
43
44
    if (Modus == 3){
45
      PORTB &= ~(1<<PORTB0);
46
        for(int i = 0;i>30;i++){
47
          _delay_ms(100);
48
        }
49
      Modus= 1; //!!!!!Hier
50
    }   
51
  };
52
  return 0;
53
}

Zwischen den gekenntzeichneten 3 Zeilen springt der Debugger hin und 
her.
Nur verstehe ich nicht wieso. Es soll in eine 1 auf PortB0 in 
verschiedenen Frequenzen ausgegeben werden. Durch die For-Schleife soll 
eine Frequenz dann eine kurze Zeit anhalten und dann zur nächsten 
Wechseln.
Am Ende will ich damit eine Tonleiter basteln.

Vielen Dank!

von Peter II (Gast)


Lesenswert?

> for(int i = 0;i>30;i++){

schau mal genau was dort steht.

von holger (Gast)


Lesenswert?

for(int i = 0;i>30;i++){

Wird nie ausgeführt.

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

habe mal alles fehler korrigiert für dich!!

von Peter M. (allforone)


Lesenswert?

Vielen Dank Peter,Holger und Martin. Vor lauter Bäumen habe ich den Wald 
nicht mehr gesehen.

von Name (Gast)


Lesenswert?

Das Toggeln von PORTB0 lässt sich auch deutlich kürzer schreiben:
1
PORTB ^= (1<<PORTB0);
statt
1
if (!(PORTB & (1<<PORTB0))){
2
          PORTB |= (1<<PORTB0);
3
          }
4
        else{
5
          PORTB &= ~(1<<PORTB0);
6
          }
Grüße

von Peter II (Gast)


Lesenswert?

Name schrieb:
> Das Toggeln von PORTB0 lässt sich auch deutlich kürzer
> schreiben:PORTB ^= (1<<PORTB0);

Vorsicht: das ist aber langsamer und nicht atomar.

Lass es lieber so wie es da steht.

von ich bin ein gast ob es dem server gefällt oder nic (Gast)


Lesenswert?

Peter II schrieb:
> Vorsicht: das ist aber langsamer und nicht atomar.

Gab es bei den neueren AVRs nicht die Möglichkeit per Schreiben auf PINx 
einen oder mehrere Ausgänge zu toogeln? Das sollte doch schneller und 
wieder atomar sein?

von Peter II (Gast)


Lesenswert?

ich bin ein gast ob es dem server gefällt oder nic schrieb im Beitrag 
#2789217:
> Gab es bei den neueren AVRs nicht die Möglichkeit per Schreiben auf PINx
> einen oder mehrere Ausgänge zu toogeln? Das sollte doch schneller und
> wieder atomar sein?

ja aber das wird anders gemacht.

von ich bin ein gast ob es dem server gefällt oder nic (Gast)


Lesenswert?

Hab ich mich doch richtig erinnert.

Peter II schrieb:
> ja aber das wird anders gemacht.
Schon klar, das ist nicht das was da oben steht.

von Peter M. (allforone)


Lesenswert?

Was heißt nicht atomar?

von Peter II (Gast)


Lesenswert?

Jan R. schrieb:
> Was heißt nicht atomar?

das die anweisung von compiler ein 3 schritte zerlegt wird.

Port einlesen
verordern
Port ausgeben


Atomar ist alles was in einem Schritt erledigt werden kann. Wo also ein 
Interupt nichts durcheinander bringen kann.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Siehe atomar

von ./. (Gast)


Lesenswert?

Peter II schrieb:
> Vorsicht: das ist aber langsamer und nicht atomar.

Ach, und das Original des TO ist atomar?! Da werden nicht nur sbi und 
cbi verwendet, sondern etwas Kontrollfluss wird auch noch benötigt.
Und langsamer ist das auch nicht. Das XOR braucht 4 Takte; das 
if-else-Konstrukt 8 bzw. 4 (je nach Verzweigung). Damit ist das 
if-else-Konstrukt im Falle der Gleichverteilung (Bit gesetzt/nicht 
gesetzt) sogar langsamer.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

./. schrieb:
> Peter II schrieb:
>> Vorsicht: das ist aber langsamer und nicht atomar.
>
> Ach, und das Original des TO ist atomar?!

Ja, ist es.

Lass zum Beispiel
 
1
#include <avr/io.h>
2
3
void foo (void)
4
{
5
    while (1)
6
    {
7
        if (!(PORTB & (1 << PORTB0)))
8
            PORTB |= (1 << PORTB0);
9
        else
10
            PORTB &= ~(1 << PORTB0);
11
    }
12
}

durch avr-gcc -O und du bekommst
 
1
foo:
2
.L5:
3
  sbic 0x18,0
4
  rjmp .L3
5
  sbi 0x18,0
6
  rjmp .L5
7
.L3:
8
  cbi 0x18,0
9
  rjmp .L5

Es ist nun kein Problem mehr, wemm asynchron zum Beispiel PB.1 verändert 
wird.

Kommt es auf die Reihenfolge von Änderungen an, etwa daß PB.1 nur nach 
einer bestimmten Aktion an PB.0 verändert werden darf, dann ist das ein 
Synchronisierungsproblem aber keines der Atomarität.

Code wie
 
1
PINB = 1 << PORTB0;

wie ihn neuere AVRs erlauben ist natürlich das beste, aber ein Compiler 
darf und wird nicht eine Sequenz wie
 
1
PORTB ^= 1 << PORTB0;

darin umwandeln.

von ./. (Gast)


Lesenswert?

Du hast natürlich Recht. Ich hatte mit -O2 getestet, aber mit -Os werden 
die rjmps noch schön auf beide Zweige aufgeteilt, so dass sie gleich 
"lang" sind.
Weißt du wie lange ein sbic braucht? Im Datenblatt steht "1  2  3" - 
da bin ich nicht recht schlau geworden und habe 2 angommen, was ggf. 
nicht korrekt ist.

von Coder (Gast)


Lesenswert?

Wenn ich im Code Verzögerungen in ms sehe, würde ich mir über die 
Ausführungsgeschwindigkeit von Bits toggeln und ähnlichem keine Gedanken 
machen (wollen). Zum Anderen werden ja hier keine Interrupts verwendet, 
so dass man sich auf über "atomarität" und synchronisation ebenso keine 
Gedanken machen muss.

von spess53 (Gast)


Lesenswert?

Hi

>Weißt du wie lange ein sbic braucht? Im Datenblatt steht "1  2  3" -
>da bin ich nicht recht schlau geworden und habe 2 angommen, was ggf.
>nicht korrekt ist.

1 Takt, wenn der nächste Befehl nicht übersprungen wird

2 Takte, wenn der nächste Befehl übersprungen wird und der übersprungen
  Befehl 1 Word lang ist

3 Takte, wenn der nächste Befehl übersprungen wird und der übersprungen
  Befehl 2 Words lang ist

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

der übersprungen -> der übersprungene

MfG Spess

von ./. (Gast)


Lesenswert?

Vielen Dank für die Info.

von Axel S. (a-za-z0-9)


Lesenswert?

Martin schrieb:
> habe mal alles fehler korrigiert für dich!!

Ich zweifle die Programm-Logik Logik immer noch an. Wenn man mal das 
Rauschen wegläßt, dann steht da:
1
modus=1;
2
for (;;) {
3
  if (modus==1) {
4
    modus=2;
5
  }
6
  if (modus==2) {
7
    modus=3;
8
  }
9
  if (modus==3) {
10
    modus=1;
11
  }
12
}

maW: die ganzen if()s sind vollkommen sinnlos, weil immer wahr. Die 
"modus" Variable erfüllt keinen Zweck und kann wegoptimiert werden.


XL

von dochgast (Gast)


Lesenswert?

Wenn das ein Zustandsautomat sein soll würde ich mal elsif 
ausprobieren...

von EGS_TI (Gast)


Lesenswert?

Ja, so wie es da steht springt er doch von einem if-Block in den 
nächsten....

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.