Forum: Compiler & IDEs Daten übertragen


von besucher (Gast)


Lesenswert?

Hallo

Ich übertrage Daten über SPI von einem tlc549-ADC auf einen at90. Meine 
Frage ist jetzt ob der Code so passt.
Die Daten werden vom tlc549 seriell übertragen.
Schickt SPI_MasterReceive() die Daten erst wenn alle 8 Bit empfangen 
wurden oder sobald ein Bit erfolgreich empfangen wurde.
1
DDRB=0xF7; //PB3-Miso Eingang
2
SPCR=(1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPHA) | (0<<CPOL) | (1<<SPRO);
3
{
4
  char zahl[9];
5
  int int_zahl;
6
7
  PORTB &= 0xFE; //  /CS auf 0 setzen
8
9
  zahl= SPI_MasterReceive();
10
11
  PORTB |= 0x01;
12
13
  int_zahl= atoi (zahl);
14
}
15
16
char SPI_MasterReceive(void)
17
{
18
  while(!(SPSR & (1<<SPIF)))
19
  ;
20
21
  return SPDR;
22
}

MfG

von Stefan E. (sternst)


Lesenswert?

besucher schrieb:

> Schickt SPI_MasterReceive() die Daten erst wenn alle 8 Bit empfangen
> wurden oder sobald ein Bit erfolgreich empfangen wurde.

Weder noch, denn dein SPI_MasterReceive wird gar nichts empfangen. 
Anscheinend hast du das Prinzip von SPI noch nicht so ganz erfasst. Es 
wird gleichzeitig in beide Richtungen übertragen. Um etwas zu 
empfangen, musst du etwas senden.

von besucher (Gast)


Lesenswert?

Ich schicke ja den Messwert vom TLC 549.
Wenn ich PB0=0 (/CS) setze, sollte es den TLC549 zum Daten senden 
freischalten. Somit kommt der Datenwert bei PB3 (Miso) rein.

von Stefan E. (sternst)


Lesenswert?

besucher schrieb:
> Ich schicke ja den Messwert vom TLC 549.
> Wenn ich PB0=0 (/CS) setze, sollte es den TLC549 zum Daten senden
> freischalten. Somit kommt der Datenwert bei PB3 (Miso) rein.

Nein, eben nicht. Der Master gibt den Takt für die Datenübertragung vor. 
Du musst etwas zum TLC549 senden. Dabei werden dann gleichzeitig auch 
die vom TLC549 zu übertragenden Bits aus dem selben "rausgetaktet".

von besucher (Gast)


Lesenswert?

Hallo

sehe ich das richtig. Ich brauche immer die Miso und Mosi Leitung.
Somit schicke ich vom Master zum Slave irgend einen Wert zb. nur 0 und 
somit empfange ich den Wert vom Slave.

Wenn im Slave 8 Bit enthalten sind, wie wird das zum Master geschickt.

Der Master empfängt ja einzeln 8 Bit. Was befindet sich im SPDR.
Ist im SPDR ein BIT als char, somit 8 Bit gespeichert.

MfG

von besucher (Gast)


Lesenswert?

Ich habe jetzt noch einmal nachgeschaut. Beim TLC549 habe ich nur 3 
Leitungen bezüglich SPI.

I/O CLOCK
DATA OUT
CS

Hier habe ich den MISO-Anschluß, wie soll das funktionieren mit dem 
MOSI-Anschluß.

von Karl H. (kbuchegg)


Lesenswert?

besucher schrieb:

> sehe ich das richtig. Ich brauche immer die Miso und Mosi Leitung.

Aus Sicht des Masters: ja
Aber die Leitung muss ja nirgend hinführen :-)

> Somit schicke ich vom Master zum Slave irgend einen Wert zb. nur 0 und
> somit empfange ich den Wert vom Slave.

Genau

> Wenn im Slave 8 Bit enthalten sind, wie wird das zum Master geschickt.

Der Master schickt ein Byte zum Slabe, damit er im Gegenzug das Byte vom 
Slave emfpangen kann.
Der springende Punkt: Der Slave kann nicht von sich aus eine Übertragung 
initiieren. Es ist immer der Master, der zumindest den den 
Übertragungstakt (dadurch dass er ein Byte ausgibt) vorgibt. Und nur 
durch diesen Übertragungstakt kann der Slave sein Byte loswerden.

> Der Master empfängt ja einzeln 8 Bit. Was befindet sich im SPDR.
> Ist im SPDR ein BIT als char, somit 8 Bit gespeichert.

Nein.
Die Hardware setzt die 8 Bit wieder zu einem Byte zusammen.

von Karl H. (kbuchegg)


Lesenswert?

besucher schrieb:
> Ich habe jetzt noch einmal nachgeschaut. Beim TLC549 habe ich nur 3
> Leitungen bezüglich SPI.
>
> I/O CLOCK
> DATA OUT
> CS
>
> Hier habe ich den MISO-Anschluß, wie soll das funktionieren mit dem
> MOSI-Anschluß.

Der führt dann einfach ins Leere.
Entscheidend ist ja für den Slave nicht, was der Master schickt, sondern 
dass der Master den Übertragungstakt anlegt.

von besucher (Gast)


Lesenswert?

Hallo

ich habe auch gedacht dass der Übertragungstakt das entscheidende ist. 
Jemand anderer im Forum hat aber geschrieben dass man mit dem Master 
Daten schicken muss um die Daten aus dem Schieberegister vom Slave 
herauszuschieben.

>> Somit schicke ich vom Master zum Slave irgend einen Wert zb. nur 0 und
>> somit empfange ich den Wert vom Slave.

>Genau

Wenn der Slave keinen Eingang hat, kann ich ja keinen Wert schicken um 
das Schieberegister zu verschieben.

Genügt jetzt also nur der Takt?


>> Der Master empfängt ja einzeln 8 Bit. Was befindet sich im SPDR.
>> Ist im SPDR ein BIT als char, somit 8 Bit gespeichert.

>Nein.
>Die Hardware setzt die 8 Bit wieder zu einem Byte zusammen.

Mir ist noch unklar was im SPDR steht.

xxxxxxx1
xxxxxx10
xxxxx101

Wird der Wert mit jedem Takt um eins nach links geschoben oder steht am 
LSB immer der neue Wert und ich muss den alten Wert mit dem neuen 
zusammensetzen.

von Rolf Magnus (Gast)


Lesenswert?

> Jemand anderer im Forum hat aber geschrieben dass man mit dem Master
> Daten schicken muss um die Daten aus dem Schieberegister vom Slave
> herauszuschieben.

Muß man ja auch. Die müssen nicht unbedingt irgendwo ankommen. Aber erst 
durch das Senden eines Bytes wird der Takt erzeugt, der es dem Slave 
ermöglicht, seine Daten loszuwerden.

> Genügt jetzt also nur der Takt?

Ja.

> Mir ist noch unklar was im SPDR steht.

Du denkst da viel zu kompliziert. Der Slave sendet ein Byte, und das 
steht nachher in SPDR.

xxxxxxx1
xxxxxx10
xxxxx101

> Wird der Wert mit jedem Takt um eins nach links geschoben oder steht am
> LSB immer der neue Wert und ich muss den alten Wert mit dem neuen
> zusammensetzen.

Du mußt gar nichts zusammensetzen. Mach dir einfach keine Gedanken 
darüber, wie der Wert da reinkommt. Das braucht dich überhaupt nicht zu 
interessieren. Warte einfach, bis der Transfer fertig ist, dann steht 
das Byte genau so im Register, wie es soll. Die Hardware kümmert sich um 
den Rest.

von besucher (Gast)


Lesenswert?

>> Jemand anderer im Forum hat aber geschrieben dass man mit dem Master
>> Daten schicken muss um die Daten aus dem Schieberegister vom Slave
>> herauszuschieben.

>Muß man ja auch. Die müssen nicht unbedingt irgendwo ankommen. Aber erst
>durch das Senden eines Bytes wird der Takt erzeugt, der es dem Slave
>ermöglicht, seine Daten loszuwerden.

Jetzt ist es mir ca. klar. Was mir aber noch unklar ist wieso muss man 
unbedingt ein Byte verschicken (egal ob es ankommt oder nicht) damit man 
Daten empfangen kann.

Ich dachte wenn man den Takt anlegt fängt es an Daten zu verschicken.

>> Genügt jetzt also nur der Takt?

>Ja.

Ich hätte wieder gesagt ein Takt genügt nicht, es müssen auch Daten 
verschickt werden. Ob sie ankommen ist wieder eine andere Sache.

von Karl H. (kbuchegg)


Lesenswert?

besucher schrieb:
>>> Jemand anderer im Forum hat aber geschrieben dass man mit dem Master
>>> Daten schicken muss um die Daten aus dem Schieberegister vom Slave
>>> herauszuschieben.
>
>>Muß man ja auch. Die müssen nicht unbedingt irgendwo ankommen. Aber erst
>>durch das Senden eines Bytes wird der Takt erzeugt, der es dem Slave
>>ermöglicht, seine Daten loszuwerden.
>
> Jetzt ist es mir ca. klar. Was mir aber noch unklar ist wieso muss man
> unbedingt ein Byte verschicken (egal ob es ankommt oder nicht) damit man
> Daten empfangen kann.

Oh Mann. Dir ist noch überhaupt nichts klar.

Du musst dem Master befehlen, ein Byte zu schicken, damit die 
Sendehardware im Master anfängt den Takt zu generieren und gleichzeitig 
ein Byte zu empfangen.

Die Hardware ist so ausgelegt, dass der Vorgang des Sendens alles andere 
triggert. Du befiehlst dem Master ein Byte zu senden und die Hardware 
macht das dann auch. Aber: damit sie das kann, muss sie den Takt 
erzeugen. Und nur darauf bist du in deinem Fall aus: Dass die 
Sendehardware den Übertragungstakt erzeugt, damit der Slave sein Byte 
senden kann. Welches Byte dabei vom Master gesendet wird und ob da 
überhaupt jemand zuhört, ist dir piepschnurzegal.

Stell dir vor, du hast eine Elektronik, die auf einen Telephonanruf 
reagiert: Wenn angerufen wird, schaltet sich meinetwegen die Heizung 
ein. Du bist jetzt unterwegs und willst zu Hause die Heizung 
einschalten. Also rufst du zu Hause an. Es ist völlig wurscht, was du in 
den Telephonhörer hineinsagst, du kannst deine Heizung beschimpfen oder 
sonst tun was du willst. Aber du MUSST anrufen. Nur das ist wichtig. Es 
spielt keine Rolle ob an der Gegenstelle jemand zuhört oder nicht. Es 
spielt keine Rolle, ob an deiner Heizung ein Lautsprecher hängt oder 
nicht, damit dich jemand fluchen hört. Das ist alles nicht wichtig. 
Wichtig ist nur, dass du anrufen musst. Genau genommen, müsste das 
Telephon dazu noch nicht einmal eine Sprachverbindung aufbauen. Aber 
sowohl für dich als auch für den Hersteller des Telephons und der 
Heizung ist das am einfachsten. Denn das Telephon kann das sowieso 
schon: eine Sprachverbindung aufzubauen, mit allem was dazu gehört. Da 
jetzt noch einen zusätzlichen Modus einzubauen "Baue eine Verbindung 
auf, aber ohne Sprachübertragung, weil ja eh niemand zuhört" ist einfach 
nur zusätzlicher Aufwand für nichts.

So auch hier: Du MUSST ein Byte schicken, damit der Mechanismus der 
Taktgenerierung und des Byteempfangens in Gang kommt. Ob das von dir 
gesendete Byte irgendjemand 'hört' oder nicht, ist in deinem Fall völlig 
uninteressant. Lass also die Leitung, an der der Master sein Byte 
rausschickt einfach offen und lass den Master da sein Byte 
'rausschicken'. Die Sendeleitung isteressiert in deinem Fall nicht 
weiter. Was dich aber interessiert ist, dass die SPI Einheit im Master 
den Rest erledigt: Den Takt erzeugen und das was er vom Slave bekommt, 
wieder zu einem Byte zusammensetzen. Nur darauf bist du aus und am 
einfachsten bekommst du das, indem du den Master einfach etwas senden 
lässt.

> Ich dachte wenn man den Takt anlegt fängt es an Daten zu verschicken.

Wir reden hier vom Sender und nciht vom Empfänger.
Und so einfach wird es sich der Empfäbnger auch nicht machen. Da wird es 
schon noch einen Selektionsmenachnismus geben, der den Slave generell 
freischaltet. CS (als Abkürzung für 'Chip Select') sieht mir ganz danach 
aus.

Und nein, der Slave generiert sich den Takt nicht selbst. Der Takt kommt 
immer vom Master.

von Simon K. (simon) Benutzerseite


Lesenswert?

Wichtig zum Verständnis ist auch zu wissen das bei SPI nicht entweder 
Daten abgerufen oder Daten gesendet werden.
Viel mehr ist es so, dass es nur eine Art von Transaktion gibt. Während 
dieser Transaktion sendet der Slave seine Daten an den Master und 
gleichzeitig empfängt er die Daten vom Master.
Anders geht es nicht.
Wenn du jetzt also ein Byte Daten vom Slave lesen willst, musst du einen 
Takt erzeugen. Welches Datenbyte bei dieser Transaktion der Master dem 
Slave schickt ist völlig egal.

von besucher (Gast)


Lesenswert?

Danke für die Erklärungen

>Wenn du jetzt also ein Byte Daten vom Slave lesen willst, musst du einen
>Takt erzeugen.

Genau das ist ja das Problem. Ich habe noch nirgends die richtige 
Antwort auf meine Frage gefunden.

Einen Takt erzeuge ich ja. Das reicht aber nicht aus. Damit der Takt 
auch funtkioniert muss ich auch Daten schicken. Wieso muss ich Daten 
schicken damit die Taktgenerierung beginnt. Wenn die Daten irgendwo 
ankommen würden, würde ich sagen ok. Aber die Daten kommen nirgends an 
aber trotzdem ist es wichtig Daten zu schicken. damti der Takt anfängt.


Letztendlich wenn der Code so passt wäre mir der Rest schon egal. 
Wichtig ist nur dass die Übertragung funktioniert.


1
DDRB=0xF7; //PB3-Miso Eingang
2
SPCR=(1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPHA) | (0<<CPOL) | (1<<SPRO);
3
4
volatile char cData;
5
6
void function(void)
7
{
8
  char wert;
9
  int int_zahl;
10
  float neue_zahl;
11
  
12
13
  PORTB &= 0xFE; //  /CS auf 0 setzen
14
15
  SPI_MasterTransmit('0');
16
  
17
  wert= SPI_SlaveReceive();
18
19
  PORTB |= 0x01;
20
21
  int_zahl= atoi (wert);
22
  
23
  neue_zahl= (5/256) * int_zahl;
24
25
}
26
27
void SPI_MasterTransmit(char cData)
28
{
29
30
SPDR = cData;
31
32
while(!(SPSR & (1<<SPIF)))
33
;
34
}
35
36
37
char SPI_SlaveReceive(void)
38
{
39
40
while(!(SPSR & (1<<SPIF)))
41
;
42
return SPDR;
43
}

von Karl H. (kbuchegg)


Lesenswert?

besucher schrieb:
> Danke für die Erklärungen
>
>>Wenn du jetzt also ein Byte Daten vom Slave lesen willst, musst du einen
>>Takt erzeugen.
>
> Genau das ist ja das Problem. Ich habe noch nirgends die richtige
> Antwort auf meine Frage gefunden.
>
> Einen Takt erzeuge ich ja. Das reicht aber nicht aus. Damit der Takt
> auch funtkioniert muss ich auch Daten schicken. Wieso muss ich Daten
> schicken damit die Taktgenerierung beginnt.

Weil die Hardware nun mal so aufgebaut ist.
Klar kannst du auch den Takt händisch erzeugen und das Empfangen selbst 
ausprogrammieren. Du kannst das aber auch der Hardware überlassen. Die 
arbeitet aber nur dann, wenn du etwas schickst.
Summa summarum: Für dich ist es viel einfacher, wenn du ein Byte 
schickst. Denn dann nimmt dir die Hardware die restliche Arbeit ab.

von Karl H. (kbuchegg)


Lesenswert?

1
void SPI_MasterTransmit(char cData)
2
{
3
4
SPDR = cData;
5
6
while(!(SPSR & (1<<SPIF)))
7
;
8
}
9
10
11
char SPI_SlaveReceive(void)
12
{
13
14
while(!(SPSR & (1<<SPIF)))
15
;
16
return SPDR;
17
}

Du hast es immer noch nicht.
Transmit und Receive sind 1 Vorgang! Senden und Empfangen sind 
untrennbar miteinander verbunden. Während der Sendevorgang läuft, wird 
gleichzeitig auch Empfangen. Du brauchst nur 1 Funktion!
1
unsigned char SPI_MasterTransmit( unsigned char cData)
2
{
3
  SPDR = cData;              // ein Byte wegschicken
4
  while(!(SPSR & (1<<SPIF))) // warten bis alles draussen ist
5
    ;                        // in der Zwischenzeit wird das Byte vom
6
                             // Slave empfangen
7
  return SPDR;               // das empfangene Byte zurückliefern
8
}

von Oliver (Gast)


Lesenswert?

>Einen Takt erzeuge ich ja.

Du erzeugst doch gar nichts. Die SPI-Hardware im AVR erzeugt den Takt. 
Diese kennt aber keinen Befehl "Takt erzeugen", die kennt nur "Senden", 
und beim Senden erzeugt die auch den benötigten Takt. Das dabei dann 
auch 8 bit "gesendet" werden, ist in deinem Fall(=Empfangen) unnötig, 
stört aber auch niemanden.

Oliver

von besucher (Gast)


Lesenswert?

>Du hast es immer noch nicht.

Es wundert mich auch nicht. Ich habe mich an die Bsp. vom Datenblatt 
gehalten.


>Die SPI-Hardware im AVR erzeugt den Takt.

Ich habe die SCK Frequenz gesetzt, somit bin auch davon ausgegangen dass 
ein Takt erzeugt wird.


Der "wert" wird in int umgewandelt. Bei der Berechnung von neue_Zahl- 
wird "wert" als binär oder dezimal verwendet?

1
DDRB=0xF7; //PB3-Miso Eingang
2
SPCR=(1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPHA) | (0<<CPOL) | (1<<SPRO);
3
4
volatile char cData;
5
6
void function(void)
7
{
8
  char wert;
9
  int int_zahl;
10
  float neue_zahl;
11
  
12
13
  PORTB &= 0xFE; //  /CS auf 0 setzen
14
15
  wert= SPI_MasterTransmit('0');
16
17
  PORTB |= 0x01;
18
19
  int_zahl= atoi (wert);
20
  
21
  neue_zahl= (5/256) * int_zahl;
22
23
}
24
25
unsigned char SPI_MasterTransmit( unsigned char cData)
26
{
27
  SPDR = cData;              // ein Byte wegschicken
28
  while(!(SPSR & (1<<SPIF))) // warten bis alles draussen ist
29
    ;                        // in der Zwischenzeit wird das Byte vom
30
                             // Slave empfangen
31
  return SPDR;               // das empfangene Byte zurückliefern
32
}

von Karl H. (kbuchegg)


Lesenswert?

besucher schrieb:
>
>   wert= SPI_MasterTransmit('0');
>
>   PORTB |= 0x01;
>
>   int_zahl= atoi (wert);

Was soll der atoi da drinnen?
Du hast hier keinen String.
Du hast ein Byte, welches einen Zahlenwert enthält.
Dieser Zahlenwert mag der ASCII Code eines Zeichens sein (weiß ich 
nicht), aber eines ist er ganz sicher nicht: Ein String so wie man sich 
in C einen String vorstellt.

>  neue_zahl= (5/256) * int_zahl;

Selbst wenn int_zahl einen vernünftigen Wert enthalten würde. Spätestens 
jetzt wäre neue_zahl immer 0!  5/256 ergibt nämlich 0. Und 0 mal 
irgendeine andere Zahl ist immer noch 0

von Karl H. (kbuchegg)


Lesenswert?

Ganz ehrlich:
Deine Fragen, wie du sie stellst und der Inhalt der Fragen, bringen mich 
zum gut gemeinten Rat:
Verschaff dir erst mal etwas Übung in den Grundlagen der 
C-Programmierung, ehe du SPI angehst.

von besucher (Gast)


Lesenswert?

>   int_zahl= atoi (wert);

Das war noch ein Fehler von vorher, wo es ein Array war.

>Verschaff dir erst mal etwas Übung in der Programmierung,

Was sollte ich deiner Meinung nach noch üben.

Ich kenne kein Beispiel bei der Ansi C-Programmierung wo mit 
Bitmaskierungen gearbeitet wird.

Wenn, dann sind es Arrays.

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.