C Kontrollstruktur will nicht AVR

OP #2789072
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!
Gast #2789218
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.
Gast #2789698
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.
Persönliche Seite #2789763
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.
Gast #2789809
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.
Gast #2789830
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.
Gast #2789841
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
#2790014
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

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