Simulation einer for-schleife (Software SPI)

Gast #3103411
Lesenswert?

Guten Tag,

Zu allererst: Ich habe kein Ozilloskop und versuche mich deshalb gerade 
mit dem Simulator vom AtmelStudio 6.1.2440 beta.

Die Funktion, die aufgerufen wird, sieht folgendermaßen aus:
1
void send_spi(uint8_t byte){
2
uint8_t i=0;
3
//PB 7 = clock; , auf low ziehen
4
PORTB &= ~(1 << PB7);
5

6
  for (i=0;i<8;i++) {
7
    if (byte &(1 << (7-i))) {
8
      PORTB |= (1 << PB5);
9
    }      
10
    else {
11
      PORTB &= ~(1 << PB5);
12
    }
13
          
14
    PORTB |= (1 << PB7);
15
    _delay_ms(1);
16
    PORTB &= ~(1 << PB7);
17
    _delay_ms(1);
18
  }
19

20
PORTB &= ~(1 << PB5);
21
}

Letzendlich soll eine Art Software SPI realisiert werden. Der Simulator 
von Atmel geht allerdings bei i=0 nicht mehr in die if-Bedingung. Mir 
fehlt also in der Simulation das letzte Bit. Warum? Letzendlich würde 
ich dann ja haben:
if (byte &(1 << 0))
Mag das der Simulator nicht? Oder mag das der compiler schonmal 
garnicht?

Ich bin ratlos und weiß also nicht, ob der Fehler im Simulator oder im 
Code liegt.

Danke für jeden Hinweis!
#3103456
Lesenswert?

@  hilflos (Gast)

>Die Funktion, die aufgerufen wird, sieht folgendermaßen aus:

>void send_spi(uint8_t byte){
>uint8_t i=0;
>//PB 7 = clock; , auf low ziehen
>PORTB &= ~(1 << PB7);

>  for (i=0;i<8;i++) {
>    if (byte &(1 << (7-i))) {

Ist ungünstig. Besser so.

http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#Schiebeoperationen

>Letzendlich soll eine Art Software SPI realisiert werden.

Sieht OK aus.

> Der Simulator
>von Atmel geht allerdings bei i=0 nicht mehr in die if-Bedingung.

Doch.

> Mir
>fehlt also in der Simulation das letzte Bit.

Nö, i fängt ja mit 0 an!

> Warum? Letzendlich würde
>ich dann ja haben:
>if (byte &(1 << 0))
>Mag das der Simulator nicht?

Das sollte kein Problem sein.

>Ich bin ratlos und weiß also nicht, ob der Fehler im Simulator oder im
>Code liegt.

Möglicherweise am Simulator. Schalte mal im Compiler die Optimierung 
aus, in den Projektoptionen.
Gast #3103530
Lesenswert?

Hallo Falk!

Hab das Problem gelöst. Undzwar hab ich den Code mit Hilfe deines Links 
und ein bisschen google umgebaut und nun simuliert er einwandfrei. Mit 
den Optimierungsoptionen hab ich garnichts weiter getan. Zur 
Vollständigkeit hier einmal der Code:
1
void send_spi(uint8_t byte){
2
uint8_t i=0;
3
//PB 7 = clock;
4
uint8_t mask = 0x80;
5

6
  for (i=0;i<8;i++) {
7
    if (byte &(mask)) {
8
      PORTB |= (1 << PB5);
9
    }
10
    else {
11
      PORTB &= ~(1 << PB5);
12
    }
13

14
    PORTB |= (1 << PB7);
15
    _delay_ms(1);
16
    PORTB &= ~(1 << PB7);
17
    _delay_ms(1);
18
    mask = (mask >> 1);
19
  }
20

21
PORTB &= ~(1 << PB5);
22
}

Danke!
#3103570
Lesenswert?

@  hilflos (Gast)

>Vollständigkeit hier einmal der Code:

Das kann man noch ein klein wenig effizienter machen, ohne 
Schleifenzähler. Die Maske reicht. Siehe unten. Und byte ist kein guter 
Name für eine Variable.

1
void send_spi(uint8_t data){
2

3
  uint8_t mask;
4

5
  for (mask=0x80; mask !=0; mask >>= 1;) {
6
    if (data & mask) {
7
      PORTB |= (1 << PB5);
8
    }
9
    else {
10
      PORTB &= ~(1 << PB5);
11
    }
12

13
    PORTB |= (1 << PB7);
14
    _delay_ms(1);
15
    PORTB &= ~(1 << PB7);
16
    _delay_ms(1);
17
    mask >>= 1;
18
  }
19

20
PORTB &= ~(1 << PB5);
21
}
Gast #3103669
Lesenswert?

Falk Brunner schrieb:
> Eine Maskierung mit einer Konstanten ist hier auch nicht schneller.
> Einen Zugriff auf das Carry-Bit wie unter Assembler hat man in C nicht.

Richtig, mit dem Carry wäre es noch schneller. Aber selbst ohne ist die 
Version besser. Die Maskierung benötigt zwei Assembler-Befehle (mov, 
and) + Sprungbefehl. Ein konstantes Bit lässt sich entweder mit 
sbrc/sbrs oder mit bst+brts/brtc prüfen. Außerdem wird ein Register 
weniger benötigt (spielt hier keine Rolle).

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