Forum: Mikrocontroller und Digitale Elektronik Soft SPI Problem


von TM F. (p_richner)


Lesenswert?

Hallo zusammen

Ich habe ein Soft SPI und möchte 9 Bit übertragen, stehe jedoch auf dem 
Schlauch bei dem Problem.

Hier der Code:
1
#define SPI_CLK                 PB5
2
#define SPI_DATA                PB3
3
4
#define HIGH                    1
5
#define LOW                     0
6
7
8
void softspi(unsigned int data)
9
{
10
    unsigned int i=0;
11
12
  SPI_CLK = LOW;            //CS=low übertragung anfang
13
  for (i=9;i<0;i--)
14
15
    {
16
17
    SPI_CLK = LOW; //clock low
18
19
    if (data  & 0x1FF){      /* Wenn MSB-Bit gesetzt     */
20
      SPI_DATA = HIGH;      /* Data-Pin auf 1 schalten, */
21
    }
22
    else{
23
      SPI_DATA = LOW;      /* ansonsten auf 0          */
24
    }
25
    data = data << 1;
26
27
    SPI_CLK = HIGH; //Clock bit rising edge
28
29
    }
30
31
  SPI_CLK = HIGH; //CS high, übertragung beendet
32
}

error: lvalue required as left operand of assignment

Dies kommt mir bei jeder Zuweisung von SPI_CLK oder SPI_DATA.

Kann mir jemand eine Lösung sagen?

MfG und danke

von Achim S. (Gast)


Lesenswert?

schau mal nach, wie PB3 definiert ist. Dann verstehst du sofort, warum 
du nichts zuweisen kannst.

TM F. schrieb:
> Kann mir jemand eine Lösung sagen?

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ausg.C3.A4nge

von Jim M. (turboj)


Lesenswert?

Konstanten kann man keine Werte zuweisen, schau Dir mal die Makros PB3 
und PB5 genauer an.

So gehts:
1
PORTB &= ~(1<<SPI_CLK); 
2
3
if (data  & 0x100){      /* Wenn MSB-Bit gesetzt     */
4
      PORTB |= (1<<SPI_DATA);      /* Data-Pin auf 1 schalten, */
5
  }

von Ingo L. (corrtexx)


Lesenswert?

TM F. schrieb:
> Dies kommt mir bei jeder Zuweisung von SPI_CLK oder SPI_DATA.
>
> Kann mir jemand eine Lösung sagen?
Ist verständlich. Du versuchst dein #define zu überschreiben.
Mach es anders:
1
#define SPI_CLK_LOW()                 (PORTB &= ~(1<<PB5))
2
#define SPI_CLK_HIGH()                (PORTB |= (1<<PB5))
3
4
#define SPI_DATA_LOW()                 (PORTB &= ~(1<<PB3))
5
#define SPI_DATA_HIGH()                (PORTB |= (1<<PB3))

und nutze diese #defines

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ TM FW (p_richner)


>Ich habe ein Soft SPI und möchte 9 Bit übertragen, stehe jedoch auf dem
>Schlauch bei dem Problem.

Hmm

>error: lvalue required as left operand of assignment

Linkswert als linker operand einer Zuweisung benötigt.

>Dies kommt mir bei jeder Zuweisung von SPI_CLK oder SPI_DATA.

Logisch.

>Kann mir jemand eine Lösung sagen?

Eher so.

PORTB |= (1<<SPI_CLK);

Siehe Bitmanipulation.

>    if (data  & 0x1FF){      /* Wenn MSB-Bit gesetzt     */
>      SPI_DATA = HIGH;      /* Data-Pin auf 1 schalten, */
>    }

Darüber würde ich auch nochmal nachdenken.

>  SPI_CLK = HIGH; //CS high, übertragung beendet

NÖ. CS ist nich CLK, das ist ein extra Signal.

von Mitlesa (Gast)


Lesenswert?

TM F. schrieb:
> for (i=9;i<0;i--)

??

von Michael U. (amiga)


Lesenswert?

Hallo,

ich bin nicht der Spuer-C-Spezi, aber welche Lösung wäre Dir angenehm?
a) befasse Dich mit den Grundlagen von C, mit dem Präprozessor und was 
noch dazugehört.

b) #define SPI_CLK                 PB5
bearbeitet der Präprozessor, das ist also eine reine Textersetzung.
Überall, wo SPI_CLK im Code auftaucht, wird es durch PB5 ersetzt.
Also z.B. hier:
aus   SPI_CLK = LOW;            //CS=low übertragung anfang
wird  PB5 = 0
Das LOW wird ja auch ersetzt.
Dummerweise ist PB5 aber auch schon ein #define in den 
AVR-Standard-Includes,
es wird duchr die Bitnummer ersetzt, hier also 5.

Somit bekommr der Compiler also 5 = 0 vor die Füße geworfen und darüber 
beklagt er sich, er will zu Recht links eine Variable haben.

Was Du willst ist, daß in PortB das Bit 5 auf Low gesetzt wird.
Also PORTB = PORTB & ~(1<<SPI_CLOCK).
Meist verküzt geschreiben, also PORTB &= ~(1<<SPI_CLOCK).
Was passiert hier? Es wird der Inhalt von PortB eingelesen.
Es wird eine Byte-Maske erzeugt, die eine 1 um 5 Positionen nach links 
verschoben enthält, also 0b00100000.
Diese Maske wird invertiert, also zu 0b11011111.
Dann wird die Maske mit dem eingelesenen Byte von PortB AND verknüpft, 
also alles außer Bit 5 bleibt wie es ist, nur Bit 5 wird zu 0.
Das Ergebnis wird dann an PortB ausgegeben.

Warum diese Umstände? Es soll ja nur Bit5 in PortB geändert werden, 
alles andere muß erhalten bleiben.

Der Compiler wird beim Optimieren sehr wahrscheinlich ein cbi portb,5 
draus machen.

Das muß aber der Compiler entscheiden, nicht jeder µC kennt diesen 
Befehl und der C-Compiler kann ja je nach Angabe für etliche 
verschiedene Controller benutzt werden.

Gruß aus Berlin
Michael

von TM F. (p_richner)


Lesenswert?

Danke für die vielen Hilfen.

Mit Ingo Less Lösung habe ich eine gute Lösung erhalten.

: Bearbeitet durch User
von Christian B. (luckyfu)


Lesenswert?

Wenn du jetzt noch sagst, wann ein unsigned integer kleiner als 0 wird, 
weißt du auch, wann deine Schleife abgebrochen wird.

Das Problem ist, i wird, wenn es auf 0 steht und du das nächste mal eins 
abziehst nicht etwa -1 (da ja unsigned), sondern 65535 werden...

von TM F. (p_richner)


Lesenswert?

Ich hab noch einen Fehler gefunden. Es sollte so sein:
1
for (i=9;i>0;i--)
2
{
3
}
anstatt
1
for (i=9;i<0;i--)
2
{
3
}

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

TM F. schrieb:
> Ich hab noch einen Fehler gefunden. Es sollte so sein:

Mitlesa schrieb:
> TM F. schrieb:
>> for (i=9;i<0;i--)
>
> ??

 Und was hat dir Mitlesa  geschrieben ?

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.