www.mikrocontroller.net

Forum: Compiler & IDEs Daten übertragen


Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
DDRB=0xF7; //PB3-Miso Eingang
SPCR=(1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPHA) | (0<<CPOL) | (1<<SPRO);
{
  char zahl[9];
  int int_zahl;

  PORTB &= 0xFE; //  /CS auf 0 setzen

  zahl= SPI_MasterReceive();

  PORTB |= 0x01;

  int_zahl= atoi (zahl);
}

char SPI_MasterReceive(void)
{
  while(!(SPSR & (1<<SPIF)))
  ;

  return SPDR;
}

MfG

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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".

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.


DDRB=0xF7; //PB3-Miso Eingang
SPCR=(1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPHA) | (0<<CPOL) | (1<<SPRO);

volatile char cData;

void function(void)
{
  char wert;
  int int_zahl;
  float neue_zahl;
  

  PORTB &= 0xFE; //  /CS auf 0 setzen

  SPI_MasterTransmit('0');
  
  wert= SPI_SlaveReceive();

  PORTB |= 0x01;

  int_zahl= atoi (wert);
  
  neue_zahl= (5/256) * int_zahl;

}

void SPI_MasterTransmit(char cData)
{

SPDR = cData;

while(!(SPSR & (1<<SPIF)))
;
}


char SPI_SlaveReceive(void)
{

while(!(SPSR & (1<<SPIF)))
;
return SPDR;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void SPI_MasterTransmit(char cData)
{

SPDR = cData;

while(!(SPSR & (1<<SPIF)))
;
}


char SPI_SlaveReceive(void)
{

while(!(SPSR & (1<<SPIF)))
;
return SPDR;
}

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!
unsigned char SPI_MasterTransmit( unsigned char cData)
{
  SPDR = cData;              // ein Byte wegschicken
  while(!(SPSR & (1<<SPIF))) // warten bis alles draussen ist
    ;                        // in der Zwischenzeit wird das Byte vom
                             // Slave empfangen
  return SPDR;               // das empfangene Byte zurückliefern
}

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

DDRB=0xF7; //PB3-Miso Eingang
SPCR=(1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPHA) | (0<<CPOL) | (1<<SPRO);

volatile char cData;

void function(void)
{
  char wert;
  int int_zahl;
  float neue_zahl;
  

  PORTB &= 0xFE; //  /CS auf 0 setzen

  wert= SPI_MasterTransmit('0');

  PORTB |= 0x01;

  int_zahl= atoi (wert);
  
  neue_zahl= (5/256) * int_zahl;

}

unsigned char SPI_MasterTransmit( unsigned char cData)
{
  SPDR = cData;              // ein Byte wegschicken
  while(!(SPSR & (1<<SPIF))) // warten bis alles draussen ist
    ;                        // in der Zwischenzeit wird das Byte vom
                             // Slave empfangen
  return SPDR;               // das empfangene Byte zurückliefern
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.