Forum: Mikrocontroller und Digitale Elektronik SPI 16-Bit Problem


von MSPLer (Gast)


Lesenswert?

Hallo zusammen,

ich beschäftige mich seit ein paar Tagen mit der USCI SPI Schnittstelle 
des MSP430G2553 und habe das Beispiel von TI bereits durchgearbeitet. 
Nun möchte ich jeweils 16-Bit übertragen und empfangen.

Das senden von 16-bit lässt sich recht einfach mit folgendem Code 
erreichen:
1
while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
2
UCA0TXBUF = cmd1;
3
__delay_cycles(50);
4
5
while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
6
UCA0TXBUF = cmd2;
7
__delay_cycles(50);


Das Empfangen habe ich wie folgt realisiert:
1
if (RXByteCounter == 1)
2
{
3
  data0= UCA0RXBUF;     
4
  RXByteCounter--;            
5
}
6
else if (RXByteCounter == 0)
7
{ 
8
  data1= UCA0RXBUF;                       // Last byte to be received
9
  data = (data1<< 8) | data0;
10
  RXByteCounter = 1;
11
}

Das Empfangen ist, das gebe ich zu, Schwachsinn! Mal wird cmd2 zuerst 
empfangen, mal cmd1. Ich brauche also irgend eine Art Synchronimpuls.

Wie reaisiert man das bei SPI am Besten, es gibt ja keine direkte 
Adressierung und ACKs wie z.B. bei I2C?!

Ich bin über jede Anregung sehr dankbar und bedanke mich bereits im 
Vorraus herzlich für jede Unterstützung.

Beste Grüße,
MSPLer

von Slave Select (Gast)


Lesenswert?

Du kannst es ähnlich wie bei der SPI machen! Dort wird der /CS zum 
"syncen" verwendet.

von MSPLer (Gast)


Lesenswert?

Hallo,
danke für die schnelle Antwort. Das habe ich schon versucht.

Beim Slave habe ich P1.5 über PSEL und PSEL2 als CS-Signal konfiguriert 
und UCMODE_2 gesetzt, sprich der Slave ist aktiv, wenn CS = 0.

Das CS Bit habe ich beim Master manuell als GPIO konfiguriert und 
gesetzt. Dennoch führt das auch nicht zum gewünschtem Erfolg.

Gibt es von Seitens TI mehr Beispiele dazu?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPLer schrieb:
> Das Empfangen habe ich wie folgt realisiert:
Wo läuft dieser "Empfangscode"? Auch auf dem Master?

> Nun möchte ich jeweils 16-Bit übertragen und empfangen.
Dir ist klar, wie SPI funktioniert? Dass beim SPI-Master 
"Empfangen=Senden" ist? SPI ist nichts anderes als gekoppelte 
Schieberegister. Für jedes gesendete Bit wird gleichzeitig eines 
empfangen. Deshalb musst du nach dem Senden eines Bytes eigentlich nur 
das Empfangsregister lesen, denn du hawst "nebenher" auch ein Byte 
empfangen.

Siehe dort: http://www.lothar-miller.de/s9y/archives/15-SPI.html

von echter MSPler (Gast)


Lesenswert?

> Das senden von 16-bit lässt sich recht einfach mit folgendem Code erreichen

Das ist schwachsinns Code!

Wie Lothar schon schrieb, SPI ist nur ein synchroner Bitstrom. Du kannst 
also soviel Bit wie du auch immer willst an einem Stück übertragen. Es 
gilt immer Daten anlegen und Strobe (Takt), Daten ...

von MSPLer (Gast)


Lesenswert?

@Lothar Miller:
> Wo läuft dieser "Empfangscode"? Auch auf dem Master?
Nein, der läuft auf dem Slave ab, ich verwende dazu zwei MSP430 
Launchpads.

> Dir ist klar, wie SPI funktioniert?
Offensichtlich hab ich da was elementares falsch verstanden, danke für 
den Link, der ist wirklich sehr hilfreich!

> Das senden von 16-bit lässt sich recht einfach mit folgendem Code erreichen
> Das ist schwachsinns Code!
Wie würde man es besser machen? Wenn ich an einem Stück übertragen kann, 
könnte ich es dann so schreiben? :
1
while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
2
UCA0TXBUF = cmd1;
3
UCA0TXBUF = cmd2;

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


Lesenswert?

MSPLer schrieb:
> Wie würde man es besser machen? Wenn ich an einem Stück übertragen kann,
> könnte ich es dann so schreiben? :

 Kenne mich mit MSP430G2553 nicht aus, aber vielleicht so:
1
 while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
2
 UCA0TXBUF = cmd1;
3
 // Prufen, ob Senden fertig ist (gibt es UCA0RXIFG ? )...
4
 data0= UCA0RXBUF;     
5
6
 while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
7
 UCA0TXBUF = cmd2;
8
 // Prufen, ob Senden fertig ist (gibt es UCA0RXIFG ? )...
9
 data = (UCA0RXBUF << 8) | data0;

: Bearbeitet durch User
von Mike (Gast)


Lesenswert?

MSPLer schrieb:
> Wie würde man es besser machen? Wenn ich an einem Stück übertragen kann,
> könnte ich es dann so schreiben? :
>
> while (!(IFG2 & UCA0TXIFG));
> // USCI_A0 TX buffer ready?
> UCA0TXBUF = cmd1;
> UCA0TXBUF = cmd2;

Guck dir mal an, was du da schreibst. Du musst dem Schieberegister schon 
eine Chance geben, seine Daten los zu werden, bevor du das nächste Byte 
in den Sendepuffer schreibst.

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


Lesenswert?

Marc V. schrieb:
> Kenne mich mit MSP430G2553 nicht aus, aber vielleicht so:

 Eigentlich reicht die Abfrage des UCA0TXIFG, also:
1
 while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
2
 UCA0TXBUF = cmd1;
3
4
 while (!(IFG2 & UCA0TXIFG));              // cmd1 gesendet?
5
 data0= UCA0RXBUF;     
6
 UCA0TXBUF = cmd2;
7
8
 while (!(IFG2 & UCA0TXIFG));              // cmd2 gesendet?
9
 data = (UCA0RXBUF << 8) | data0;

: Bearbeitet durch User
von echter MSPler (Gast)


Lesenswert?

Wie wäre es mit Interrupts? Das USCI kann das.

Die Aufgabenstellung ist völlig losgelöst vom uC  oder der Art der 
Übertragung. Es gibt einen Sendepuffer und einen Empfangespuffer. Der 
Austausch erfolgt per Interrupt. Natürlich muss eine Synchronisation 
erfolgen.

von Peter D. (peda)


Lesenswert?

MSPLer schrieb:
> Ich brauche also irgend eine Art Synchronimpuls.

Der Master mus ja /SS des gewünschten Slave auf low ziehen.
Damit kann der Slave einen Interrupt auslösen und seinen Byte-Counter 
auf 0 setzen.
Sollte /SS nicht interruptfähig sein, muß man ihn zu einem 
Interrupteingang parallel schalten.

Pseudocode:
Master:
/SS_slave = 0
spidata = byte_1
while( not done )
...
spidata = byte_n
while( not done )
/SS_slave = 1

Slave:
interrupt on /SS = 0:
bytecounter = 0

interrupt on receive:
inbuff[bytecounter++] = spidata

von MSPLer (Gast)


Lesenswert?

Hallo zusammen,

dank eurer Hilfe habe ich eine kleinen Fortschritt machen können.

Das senden von zwei Bytes habe ich nun anhand einer Funktion 
implementiert, welche wie folgt aussieht:
1
while(count)
2
{
3
  UCA0TXBUF = *tx_array;
4
  tx_array++;
5
  while ((IFG2 & UCA0TXIFG) == 0); // wait for tx buffer to be ready
6
  count--;
7
}
8
while ((UCA0STAT & UCBUSY) == 1);  // wait for transfer to complete
9
IFG2 &= ~UCA0RXIFG;                // clear the rx flag

Nun werden zwei Byte zumindest schon mal zuverlässig übertragen.

Als nächstes werde ich auf der SPI Slave Seite weiter fortfahren und 
Interrupt gesteuert zwei Bytes empfangen.

@Lothar Miller: Deine anregende Kritik war gold Wert, ebenso der Link zu 
deiner Seite, danke!

von MSPLer (Gast)


Lesenswert?

Eine Sache erscheint mir allerdings immer noch merkwürdig.

Auf der SPI Slave Seite habe ich "UCxSTE" aktiviert und UCMODE_2 
gesetzt. Ich verstehe dieses Signal als Slave Select Signal, richtig?

Mich wundert nur, dass ich keinen Interrupt bekomme, wenn UCxSTE = 0 
wird. Dann könnte ich dann nämlich meinen RXCounter auf Null zurück 
setzen.

Das USCI-Modul bietet nur Interrupt für RX und TX.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPLer schrieb:
> danke!
Keine Ursache.
Aber eines wollte ich noch loswerden: zur Kommunikation zwischen 2 
Prozessoren würde ich eine "normale" serielle Schnittstelle nehmen (aka. 
RS232 mit TTL-Pegeln).
Bei so einer Schnittstelle ist nämlich eine Antwort zeitlich nicht 
zwingend an das Senden gekoppelt. Der Slave hat es wesentlich einfacher, 
zu reagieren. Du wirst jetzt auf der Slave-Seite dann leicht erkennen, 
dass dieser Zwang, sofort/schnell auf den SPI-Master reagieren zu 
müssen, unschön ist...

von echter MSPler (Gast)


Lesenswert?

@Lothar
Im SPI Modus sind die USCI Register nicht auf 1 Bit beschränkt. Denk mal 
darüber nach. ;-)

Bei vielen uC erlaubt die synchrone Übertragung höhere Baudaten als die 
asynchrone.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

echter MSPler schrieb:
> Im SPI Modus sind die USCI Register nicht auf 1 Bit beschränkt. Denk mal
> darüber nach. ;-)
Gut, mach ich. Fertig. Das ging ja schnell... :-o

> Bei vielen uC erlaubt die synchrone Übertragung höhere Baudaten als die
> asynchrone.
Schon klar. Nur ist es eben so, dass der Slave bei der RS232 antworten 
kann, wenn er will und mit seinen Berechnungen fertig ist. Beim SPI 
muss der Slave ständig gepollt werden, oder es muss sicherheitshalber 
gewartet werden, bis er "fertig" ist. Der Slave kann von sich aus nicht 
mit einer Übertragung beginnen. Als Workaround zu diesem Thema wird dann 
oft der Übertragungswunsch des Slaves per zusätzlicher Interruptleitung 
an den Master signalisiert.

Etwas komplett anderes ist hier z.B. ein mehrkanaliger ADC, der 
gleichzeitig mit dem Senden des nächsten Kommandos den vorherigen 
Wandlungswert zurückgibt. Da ist SPI super aufgehoben, weil der ADC ja 
sowieso nichts "von sich aus" macht...

von Peter D. (peda)


Lesenswert?

Lothar M. schrieb:
> Nur ist es eben so, dass der Slave bei der RS232 antworten
> kann, wenn er will und mit seinen Berechnungen fertig ist.

Noch schöner ist CAN, da nimmt einen die HW den ganzen Protokoll-, 
Timing- und Fehlerschrunz ab. Da muß man wirklich nur was in den 
Sendepuffer schreiben bzw. den Empfangspuffer auslesen. Minimal 
aufwendiger wird es bei Paketen >8Byte.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Noch schöner ist CAN, da nimmt einen die HW den ganzen Protokoll-,
> Timing- und Fehlerschrunz ab.
Aber der Transceiver ist in den meisten uC nicht enthalten.

EDIT:
Ist wohl halb so schlimm, mit ein paar Dioden sollte das wohl auch auf 
TTL-Ebene und ohne Transceiver gehen... ;-)

: Bearbeitet durch Moderator
von echter MSPler (Gast)


Lesenswert?

Man muss Client Server nur richtig zuordnen.:-(

Komisch, dass Displays und andere Peripherals synchron und nicht 
asynchron angeschlossen werden? Da muss die Industrie aber noch viel vom 
Loddar lernen. :-D :-D :-D

von Karl H. (kbuchegg)


Lesenswert?

Och, es gibt auch Display Module, die über eine serielle Schnittstelle 
angesprochen werden (TTL oder echtes RS232).
Ist halt alles eine Frage der FInanzen. Ein simples getaktetes 
Schieberegister ist eben billiger als eine UART.

von c-hater (Gast)


Lesenswert?

echter MSPler schrieb:

> Komisch, dass Displays und andere Peripherals synchron und nicht
> asynchron angeschlossen werden? Da muss die Industrie aber noch viel vom
> Loddar lernen. :-D :-D :-D

Das ist doch Quatsch. Es gibt auch unendlich viel asynchron oder 
"halbsynchron" betriebene Peripherie.

Siehe z.B. USB. Nicht gerade wenig verbreitet, oder bist du da anderer 
Meinung?

Wie auch immer deine werte Meinung ist, Tatsache ist jedenfalls: USB 
kann man bestenfalls als halbsynchron zu bezeichnen. Zwar ist die 
Übertragung innerhalb der einzelnen Pakete synchron (sie tragen ihren 
Takt ja in sich), aber das Timing der Pakete insgesamt ist eindeutig 
asynchron, der jeweilige Empfänger muß sich auf den Paketbegin und das 
darin enthaltene Sync-Muster jedesmal neu synchronisieren (genau 
deswegen gibt's das nämlich überhaupt nur).

Oder ein anderes Beipiel, Ethernet in den heute üblichen Ausprägungen 
zwischen 100MBit und 10GBit über Kupfer, auch nicht gerade wenig 
verbreitet...

Hier ganz genau dieselbe Soße, innerhalb der Pakete synchron, Pakete 
aber asynchron.

Ich könnte noch seitenweise weitere Beipiele anführen, aber die zwei 
sollten allein schon reichen, um dir klar zu machen, wie wenig du 
eigentlich weisst...

von echter MSPler (Gast)


Lesenswert?

Karl H. schrieb:
> Och, es gibt auch Display Module, die über eine serielle
> Schnittstelle angesprochen werden (TTL oder echtes RS232).
> Ist halt alles eine Frage der FInanzen. Ein simples getaktetes
> Schieberegister ist eben billiger als eine UART.

Natürlich, es gibt auch heute noch Monitore mit VGA. :-(

@C-Ha...
Dein Nick, dieser Beitrag und viele deiner anderen outen dich als einen 
Kasper der vergangegenen Zeit. Von dir ist nix zu erwarten. :-(

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


Lesenswert?

echter MSPler schrieb:
>> Ist halt alles eine Frage der FInanzen. Ein simples getaktetes
>> Schieberegister ist eben billiger als eine UART.
>
> Natürlich, es gibt auch heute noch Monitore mit VGA. :-(

 Was hat das mit der Tatsache zu tun, dass Karl H. Recht hat ?
 Knapp 2 Meter Kabel, nur ein Teilnehmer, was kann da billiger,
 zuverlässiger und schneller sein ?


> @C-Ha...
> Dein Nick, dieser Beitrag und viele deiner anderen outen dich als einen
> Kasper der vergangegenen Zeit. Von dir ist nix zu erwarten. :-(

 Ich bin nicht gerade sein Fan, aber wenn er etwas schreibt, dann weiss
 er meistens wovon er spricht ( im Gegensatz zu dir ).
 Was ist in seinem Beitrag falsch oder entspricht nicht den Tatsachen ?

: Bearbeitet durch User
von MSPLer (Gast)


Lesenswert?

Hallo zusammen,

> Du wirst jetzt auf der Slave-Seite dann leicht erkennen,
>dass dieser Zwang, sofort/schnell auf den SPI-Master reagieren zu
>müssen, unschön ist...
Ohja! Das habe ich .. :-(

Ich habe das Problem bisher so angegangen, dass ich auf der Slave Seite 
in der ISR eine FSM implementiert habe, sieht als Minimalbeispiel 
erstmal so aus:
1
#pragma vector=USCIAB0RX_VECTOR
2
__interrupt void USCI0RX_ISR (void)
3
{
4
  switch(state)
5
  {
6
  //===============================================================================//
7
  // IDLE: 
8
  //===============================================================================//
9
  case IDLE:  UCA0TXBUF = 0xFF;             // dummy write
10
              while ((IFG2 & UCA0RXIFG) == 0);    // transfer complete?
11
              slave_adr = UCA0RXBUF;
12
13
              if(slave_adr == 10)
14
              {
15
                state = TRANSMIT;
16
              }
17
              else
18
              {
19
                state = IDLE;
20
                break;
21
              }
22
  //===============================================================================//
23
  // TRANSMIT: 
24
  //===============================================================================//
25
  case TRANSMIT:    src = (uint8_t *) tx_array;
26
27
              while(TXByteCounter)
28
                {
29
                  UCA0TXBUF = *src;
30
                  src++;
31
                    while ((IFG2 & UCA0TXIFG) == 1);   // wait for tx buffer to be ready
32
                  TXByteCounter--;
33
                }
34
                while ((UCA0STAT & UCBUSY) == 1);     // wait for transfer to complete
35
                IFG2 &= ~UCA0RXIFG;           // clear the rx flag
36
                state = IDLE;
37
                break;
38
  //===============================================================================//
39
  // DEFAULT: 
40
  //===============================================================================//
41
  default:      break;
42
  }
43
}

Das empfangen klappt wie bisher wunderbar, nur beim Senden habe ich 
massive Probleme.

Es sollen die Werte 80 und 10 zurück gesendet werden. In der ISR werden 
auch die richtigen Werte in das Sendebuffer geschoben, das kann ich beim 
Debuggen nachvollziehen.

Aber auf dem Oszilloskop sehe ich, dass 2x der Wert 80 übertragen wird. 
Also offensichtlich mache ich hier etwas beim Senden und/oder Auslesen 
falsch.

Meine Slave Konfiguration sieht wie folgt aus:
1
void spi_config_slave()
2
{
3
    P1SEL = BIT1 + BIT2 + BIT4 + BIT5;
4
    P1SEL2 = BIT1 + BIT2 + BIT4 + BIT5;
5
    UCA0CTL1 = UCSWRST;                             // **Put state machine in reset**
6
    UCA0CTL0 |= UCCKPL + UCMSB + UCMODE_2 + UCSYNC;        // 4-pin, 8-bit SPI master
7
    UCA0CTL1 &= ~UCSWRST;                           // **Initialize USCI state machine**
8
    IE2 |= UCA0RXIE;                            // Enable USCI0 RX interrupt
9
}

Ich freue mich über jeden Ratschlag, ich habe leider im Moment keine :-(

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


Lesenswert?

MSPLer schrieb:
> Es sollen die Werte 80 und 10 zurück gesendet werden. In der ISR werden
> auch die richtigen Werte in das Sendebuffer geschoben, das kann ich beim
> Debuggen nachvollziehen.
>
> Aber auf dem Oszilloskop sehe ich, dass 2x der Wert 80 übertragen wird.
> Also offensichtlich mache ich hier etwas beim Senden und/oder Auslesen
> falsch.

 LOL.
 Weil du 2 Bytes hintereinander in der ISR senden willst ?

 So geht das nicht. Dein Zeiger wird in der ISR auf:
1
 src = (uint8_t *) tx_array;
 gesetzt. Wenn du beim SPI etwas gesendet hast, hast du auch etwas
 empfangen, also wird der INT gleich nach dem senden vom ersten Byte
 wieder feuern und da du den Zeiger auf Anfang stellst...

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPLer schrieb:
>> Du wirst jetzt auf der Slave-Seite dann leicht erkennen, >dass dieser
>> Zwang, sofort/schnell auf den SPI-Master reagieren zu >müssen, unschön
>> ist...
> Ohja! Das habe ich .. :-(
Ja, da wäre jetzt ein "echter MSPler" gefragt. Einer eben, der sich mit 
den ganzen Registern im MSP auskennt...

Sagen wirs mal so:
Weil das Senden und das Empfangen beim SPI gleichzeitig passiert, musst 
du das erste Byte im Slave schon bereitstellen, bevor der Master sein 
erstes Datenbyte sendet. Dann sind beide Schieberegister mit den 
aktuellen Daten ausgestattet und der Transfer kann beginnen. Dieses Byte 
kannst du z.B. schon sofort nach der vorhergehenden Übertragung 
bereitstellen (und hoffen, dass der Master sie irgendwann abholt). Oder 
du reagierst recht zügig auf einen Interrupt und triggerst den mit der 
fallenden SS-Flanke. Dann nicht viel Zeit verplempert und sofort das 
Datenbyte ins Slave-TX-Register geschreiben!
Nach der Übertragung des ersten Bytes gibt es auf der Slaveseite 
irgendein Signal/Interrupt, das die Übertragung eines Bytes 
signalisiert. Das ist dann der Zeitpunkt, wo der Master sein zweites 
Datenbyte ins Senderegister schreibt. Auf der Slave-Seite heißt das dann 
"hurtig, hurtig", denn vor dem nächsten SPI-Takt muss auch der Slave das 
nächste Datenbyte in sein TX-Register schreiben.
Und natürlich muss der Slave dann zusätzlich noch das empfangene Byte 
rechtzeitig aus dem RX-Register auslesen, denn sonst wird das 
überschrieben...

Mit ein wenig Glück hat der jeweilige uC noch ein paar 
Double-Buffer-Stufen, um diese Hektik auf der Slave-Seite zu entspannen. 
Dazu musst du das Datenblatt genau lesen.


MSPLer schrieb:
> Ich habe das Problem bisher so angegangen...
> #pragma vector=USCIAB0RX_VECTOR
> __interrupt void USCI0RX_ISR (void)
> {
>  .....
>               while ((IFG2 & UCA0RXIFG) == 0); // wait
>              while(TXByteCounter)
>                    while ((IFG2 & UCA0TXIFG) == 1);   // wait
>                while ((UCA0STAT & UCBUSY) == 1);     // wait

In einem Interrupt hat ein while() nichts zu suchen. Da wird niemals 
auf irgendwas gewartet! Du wirst nochmal drüber nachdenken müssen...

echter MSPler schrieb:
> Da muss die Industrie aber noch viel vom Loddar lernen. :-D :-D :-D
Du hast da einen Schreibfehler im Satz.

: Bearbeitet durch Moderator
von Peter D. (peda)


Lesenswert?

Viele Slave-SPI sind leider nur ungepuffert bzw. nur mit Empfangspuffer 
(z.B. AVR).
Dann muß der Master nach jedem Byte erstmal lange Gedenkpausen einlegen, 
damit der Slave einen gerade laufenden Interrupt beenden kann, dann in 
den SPI-Interrupt springen kann, dann dessen Prolog abrasselt, um 
endlich das nächste Byte in das Schieberegister zu schreiben.

Nur ein gepufferter Slave kann schon das nächste Byte in den Puffer 
schreiben, wärend der Master das vorherige noch rausschiebt.
Gesehen habe ich gepufferte Slaves bisher nur bei einigen 8051, z.B. 
AT89LP4052.

Natürlich kann kein Slave hellsehen, welches Paket der Master als 
nächstes lesen will. Da muß man sich ein Protokoll ausdenken. Z.B. 
schickt der Master erstmal ein Kommando, liest dann ein Dummybyte, 
wärend dessen der Slave das Kommando parst und die zu sendenden Daten 
bereitstellt.

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


Lesenswert?

Peter D. schrieb:
> Natürlich kann kein Slave hellsehen, welches Paket der Master als
> nächstes lesen will. Da muß man sich ein Protokoll ausdenken. Z.B.
> schickt der Master erstmal ein Kommando, liest dann ein Dummybyte,
> wärend dessen der Slave das Kommando parst und die zu sendenden Daten
> bereitstellt.

 Klar.
 Bei mir schreibt der Slave wenn er ein Kommando empfangen hat, 0xF0 ins
 Senderegister und nachdem er dieses Kommando abgearbeitet hat, wird ein
 0x55 ins Senderegister geschrieben, so weisst der Master gleich nach
 dem ersten Byte ob der Slave schon fertig ist und ob er weiter senden
 soll.
 Wenn es aber ein kurzes, bzw. schnelles Kommando ist, wird mit zweitem
 Byte etwas gewartet und das Resultat gleich abgeholt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Z.B. schickt der Master erstmal ein Kommando, liest dann ein Dummybyte,
> wärend dessen der Slave das Kommando parst und die zu sendenden Daten
> bereitstellt.
Und damit hoffenlich rechtzeitig fertig ist. So werden dann zum 
Übertragen eines Bytes mindestens 3 Bytes hin und her geschickt...

Mit der seriellen Schnitte würde der Master die Anfrage senden, der 
Slave würde dann diese Anfrage empfangen, danach irgendwann bearbeiten 
und bei Gelegenheit die Antwort senden. Zetilich komplett entspannt mit 
nur 2 Leitungen.

Und wenn der Slave dem Master was zu sagen hat, dann tut er es einfach 
irgendwann. Er muss ja nicht warten, bis der Master ihm die 
Gelegenheit zur Übertragung bietet, oder den Master per zusätzlicher 
Interrupt-Leitung darum bitten.

Ich verwende SPI gerne. Aber eben für "dumme" Peripheriebausteine wie 
IO-Schieberegister, ADC und DAC...

von c-hater (Gast)


Lesenswert?

echter MSPler schrieb im Beitrag #4187019:

> Wenn ein Slave seine Daten sendet, wenn es ihm zeitlich gefällt, ist er
> kein Slave mehr. :-(

Bei so einer Ansammlung geballter Idiotie kann man eigentlich nur den 
Kopf schütteln.

Der Slave sendet seine Daten im vorgeschlagenen Verfahren keinesfalls, 
wann immer er möchte, sondern immer noch genau dann, wenn der Master sie 
anfordert.

Der springende Punkt ist, dass ich Master und Slave zu jeder Zeit 
darüber einig sind, was der Slave auf zu der gegebenen Zeit auf die 
Anfrage des Masters zu antworten hat. Das nennt man ein Protokoll!

Und sowas ist (ganz unabhängig davon, ob die Übertragung auf dem 
PHY-Level synchron oder asynchron ist), seit einer schier unerfindlichen 
Zahl von Jahren Grundlage jeglicher Technik. Und natürlich grundlegendes 
Fachwissen eines jeden, der diese Technik zum "Zusammenspielen" bewegen 
will oder muss.

An dir ist das wohl völlig vorbei gegangen...

[Hier wurde eine emotionale Aussage vom Moderator gelöscht]

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

echter MSPler schrieb im Beitrag #4187019:
> oder Loddar? :'(
Hör mal, du namenloser Irgendwer. Wenn du es nicht kapieren willst, dann 
lässt du es sein. Aber ich werde jeden deiner Posts löschen, in dem du 
mich so nennst. So einfach ist das.


echter MSPler schrieb im Beitrag #4187019:
> Man kann auch SPI nur halbduplex nutzen, wem s gefällt ... ;-)
Es gibt auch Datenprotokolle jenseits von SPI. Aber wenn einer (wie du 
offenbar) nur einen Hammer hat, für den sieht die ganze Welt wie ein 
Nagel aus.

Offenbar hast du als "echter MSPler" aber nichts zur Sache beizutragen. 
Ich sehe in im gelöschten Post nur Zahnerei und Kleinkrämerei...

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MSPLer schrieb:
> Ich freue mich über jeden Ratschlag, ich habe leider im Moment keine :-(

Marc V. schrieb:
> Weil du 2 Bytes hintereinander in der ISR senden willst ?

 Das mag ich so in diesem Forum - NETIQUETTE über alles.
 TO könnte schreiben:

 A) Nein, deine Antwort war nicht richtig.
 B) Ja, das war es, danke.
 C) Die Antwort half mir zwar nicht gerade viel, ich verstehe auch kein
    bisschen wovon du da schreibst, da du aber ein  Moderator bist,
    muss ich bodentiefe Verbeugungen und unzählige Handküsse machen.
 D) TO bleibt weiter ein A...h und schreibt nichts.

 Nicht, das es einen Unterschied fur mich macht, aber es macht sehr
 wohl einen Unterschied für Leute die vielleicht irgendwann vor einem
 ähnlichem Problem stehen werden.
 Wenn jemand vor einem Problem steht und genügend Zeit hat, rumzuweinen
 und um Hilfe zu bitten, aber wenn sein Problem gelöst ist, nicht mehr
 Zeit findet, um eine einfache Antwort zu schreiben, dann ist er ?

 Genau das.

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


Lesenswert?

echter MSPler schrieb im Beitrag #4187731:
> Sein Problem ist noch nicht gelöst,...
 Ja, es ist gelöst, lies meine Antwort von gestern.

: Bearbeitet durch User
von MSPler (Gast)


Lesenswert?

> Nicht, das es einen Unterschied fur mich macht, aber es macht sehr
> wohl einen Unterschied für Leute die vielleicht irgendwann vor einem
> ähnlichem Problem stehen werden.

Sorry, du hast natürlich Recht, entschuldige bitte meinen Fauxpax :-) 
Ja, zwei Bytes hintereinander zu senden und das auf einmal bei Aufruf 
der ISR ist natürlich Quatsch und macht keinen Sinn. Dummer 
Anfängerfehler. Aber hey, ich bin ja auch ein Anfänger. ;-)

Ich habe mich von dem Gedanken verabschiedet auf einmal 2 Byte senden zu 
wollen. Immerhin ist SPI grundsätzlich gesehen ja auch ein Byte 
basiertes Protokoll, niemand hat was von zwei Byte gesagt.

Meine Aufgabe besteht im Grunde genommen darin einen gemeinsamen 
Addressraum zu definieren, der im Slave Device abgebildet ist. Also der 
Master möchte z.B. die Register der RTC im Slave lesen.

Der Master wird im weiteren Verlauf durch einen FPGA mit SPI-Makro 
ersetzt werden. Da das I2C Modul des MSP schon anderweitig implementiert 
ist, und die Hardware nur über SPI mit dem FPGA verbunden ist, bleibt 
mir hierbei keine andere Wahl.

Ich werde also mit Hilfe von SPI als Grundlage ein eigenes Protokoll 
entwickeln, der Master soll auf diesen Addressraum lesend und schreibend 
zugreifen können.

Ich stelle mir das im Moment so vor:

Master möchte von Slave lesen und spricht ihn mit Adresse z.B 10 an 
(schreiben wäre dann Adresse z.B. 11)

Slave bestätigt mit Status Code OK

Master sendet Register Adresse, von der er lesen möchte

Slave antwortet mit H-Byte

Master bestätigt

Slave antwortet mit L-Byte

Master beendet Kommunikation

Ob das so funktioniert, wird sich in der kommenden Woche zeigen ;-)



>Das mag ich so in diesem Forum - NETIQUETTE über alles.

Oh ja. Letzlich kann niemand alles wissen und was der eine nicht weiß, 
weiß der andere umso besser. Ich bin ursprünglich VHDL-Entwickler und 
beschäftige mich erst seit ein paar Wochen mit dem MSP430 und der µC 
Entwicklung. Ich möchte niemanden anprangern oder kritisieren, meine 
Aussage ist lediglich: Kinder, vertragt euch! :-)

Umso mehr möchte ich mich bei all denjenigen bedanken, die mir bei 
meiner Aufgabe mit konstruktiver Kritik und gewinnbringenden Ratschlägen 
zur Seite stehen, vielen Dank!

Euch allen noch einen schönen Sonntag.

Beste Grüße,
MSPler

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


Lesenswert?

MSPler schrieb:
> Ich stelle mir das im Moment so vor:
>
> Master möchte von Slave lesen und spricht ihn mit Adresse z.B 10 an
> (schreiben wäre dann Adresse z.B. 11)
  OK, geht.

> Slave bestätigt mit Status Code OK
 Slave schreibt bei jeder Statusanderung seinen neuen Status ins
 SendeRegister. Auf diese Weise weiss der Master schon nach dem ersten
 Byte ob er weiter senden soll. Bei jedem SPI_Rcv_Interrupt ( beim
 Slave ) wird entweder der Status neu geschrieben oder das empfangene
 Kommando wird dekodiert.

> Master sendet Register Adresse, von der er lesen möchte
 Aber nur, wenn der vorher empfangene Byte Status_Ready bezeichnet.

> Slave antwortet mit H-Byte
 Kann er nicht, Slave hat gerade Register Adresse empfangen, Master
 muss also zuerst noch etwas senden, damit er auch etwas empfangen kann.

> Master bestätigt
 Master wartet eine gewisse Zeit, sendet z.B. EOC (End Of Command) und
 empfangt H-Byte.

> Slave antwortet mit L-Byte
 Kann er nicht, siehe oben.
 Master sendet z.B. EOR (End Of Request) und empfangt L-Byte.

> Master beendet Kommunikation
 Hat er schon oben mit EOR getan.

> Ob das so funktioniert, wird sich in der kommenden Woche zeigen ;-)
 Wird mit Sicherheit, SPI ist schnell und einfach zu implementieren.

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


Lesenswert?

echter MSPler schrieb im Beitrag #4188796:
> Der Kollege hat immer noch keine Lösung. Und jetzt? :-[ :-[ :-[

 Und du hast immer noch keine Ahnung worum es hier überhaupt geht, nicht
 zu reden davon, dass du keine Ahnung von uC und programmieren
 überhaupt hast.
 Schuster, bleib bei deinen Leisten und misch dich nicht in Sachen ein,
 von denen du nichts versteht...

 P.S.
 Deine Beiträge werden sowieso gelöscht, bemühe dich nicht weiter
 deinen Blödsinn zu senden.
 LOL.

von echter MSPler (Gast)


Lesenswert?

Schuster ...

So isses! Aber warum schreibst du dann hier? Denn ich sehe immer noch 
keinen brauchbaren Code für den MSP. Hast du übererhaupt schon einmal 
so ein Ding von Nahem gesehen? :-*

: Wiederhergestellt durch Moderator
von Walter Tarpan (Gast)


Lesenswert?

Marc V. schrieb:
>> Master bestätigt
>  Master wartet eine gewisse Zeit, sendet z.B. EOC (End Of Command) und
>  empfangt H-Byte.

Tja, für ein derartiges Protokoll wäre ein I2C praktischer. Da kann der 
Slave notfalls clock strechting betreiben, wenn er nicht mitkommt und 
muß nicht immer ein komplettes "status not ready" zurückschicken.

von Peter D. (peda)


Lesenswert?

MSPler schrieb:
> Der Master wird im weiteren Verlauf durch einen FPGA mit SPI-Makro
> ersetzt werden.

In dem Fall würde ich den MC als SPI-Master und den FPGA als SPI-Slave 
benutzen.
Der FPGA muß ja nicht erst etwas anderes unterbrechen und in einen 
Interrupt springen, hat also keinerlei Zeitprobleme, der MC dagegen 
schon.
Als SPI-Master aber gibt der MC den Takt vor, kann sich also soviel Zeit 
lassen, wie er lustig ist.
Und der SPI-Slave-FPGA kann über eine Leitung signalisieren, daß er 
einen Transfer wünscht. Er ist quasi der Daten-Master, da er den 
Transfer startet.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Marc V. schrieb:
> Deine Beiträge werden sowieso gelöscht
Wie dort im Beitrag "Re: SPI 16-Bit Problem" 
angekündigt: gelöscht wird, so lange der "echte MSPler" nur rotzfrech 
rumrotzt und ausser Beleidigungen nichts an den Tag bringt.

echter MSPler schrieb:
> Denn ich sehe immer noch keinen brauchbaren Code für den MSP.
Wie schon lange gesagt, da wäre jetzt mal ein echter "echter MSPler" 
nötig. Der könnte sowas können...

Peter D. schrieb:
> MSPler schrieb:
>> Der Master wird im weiteren Verlauf durch einen FPGA mit SPI-Makro
>> ersetzt werden.
Oha, Salamitaktik...  :-/
> In dem Fall würde ich den MC als SPI-Master und den FPGA als SPI-Slave
> benutzen.
Ich auch, denn das FPGA ist wegen der damit möglichen Parallelität auf 
jeden Fall schnell genug. Wenn nicht, dann ist die Beschreibung 
ungünstig und muss angepasst werden.

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

echter MSPler schrieb:
> Schuster ...
>
> So isses! Aber warum schreibst du dann hier? Denn ich sehe immer noch
> keinen brauchbaren Code für den MSP.
 Aha. Leider wird hier im Forum meistens nur Hilfe geleistet, bei
 Problemen geholfen usw.
 Fertigen Code kriegt keiner.

> Hast du übererhaupt schon einmal so ein Ding von Nahem gesehen? :-*
 Nicht naher als 60cm., muss ich zugeben. Allerdings habe ich bei
 meinen 2 letzten Laptops die CPU auch noch nie gesehen...

von echter MSPler (Gast)


Lesenswert?

Das erklärt deine Unwissenheit zur hardwarenahen Programmierung und 
Kommunikation.

Und natürlich bekommt man hier im Forum fertigen Code. Warum auch nicht?

Der echte MSPler kennt den MSP430 und viele andere uCs. Und daher kann 
er gut vergleichen und dir sagen, dass du dir den MSP einmal von ganz 
Nahem ansehen solltest. Am Besten rein kriechen.

SPI mit der USCI ist einfach und wird natürlich per Interrupt genutzt.

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


Lesenswert?

echter MSPler schrieb:
> Und natürlich bekommt man hier im Forum fertigen Code. Warum auch nicht?
 Da bin ich aber auf deinen Code gespannt.

> Der echte MSPler kennt den MSP430 und viele andere uCs.
 Vom Hörensagen, Internet oder Nachbar Anton ?

> SPI mit der USCI ist einfach und wird natürlich per Interrupt genutzt.
 Wow, das hat dir wer erzählt ?
 Und du hast den ganzen Satz behalten oder musstest du das aufschreiben?
 Hat er dir auch erklärt, was ein Interrupt ist ?

von MSPler (Gast)


Lesenswert?

>> Master sendet Register Adresse, von der er lesen möchte
> Aber nur, wenn der vorher empfangene Byte Status_Ready bezeichnet.

>> Slave antwortet mit H-Byte
> Kann er nicht, Slave hat gerade Register Adresse empfangen, Master
> muss also zuerst noch etwas senden, damit er auch etwas empfangen kann.

>> Master bestätigt
> Master wartet eine gewisse Zeit, sendet z.B. EOC (End Of Command) und
> empfangt H-Byte.

>> Slave antwortet mit L-Byte
> Kann er nicht, siehe oben.
> Master sendet z.B. EOR (End Of Request) und empfangt L-Byte.

>> Master beendet Kommunikation
> Hat er schon oben mit EOR getan.

Korrigiert, sieht es bisher so aus:

Master sendet 1 Byte (Bit 8: R/W, Bit 7-0 Register Adresse)

Slave antwortet mit ACK_READ oder ACK_WRITE

Master sendet H_BYTE_REQUEST

Slave antwortet mit oberen 8-Bit des 16-Bit Wortes

Master sendet L_BYTE_REQUEST

Slave antwortet mit unteren 8-Bit

Master sendet END_OF_REQUEST

Slave bestätigt und geht wieder in den IDLE Mode

Implementiert wird das ganze mit Hilfe einer FSM, die in der ISR 
beschrieben ist.


Ein gewaltiges Problem habe ich nach wie vor:
Es kommt in unregelmäßigen Abständen vor, dass die Daten vom Slave zum 
Master, also über MISO gesendete Worte, um mehrere Bits verschoben beim 
Master ankommen. Also statt 00001101 kommt 00011010 beim Master an.

Ich habe alle Steckverbinderkabel schon ausgetauscht und sicher 
gestellt, dass alles richtig verbunden ist. Das Taktsignal sieht sauber 
aus, so wie man es bei 250 kHz Übertragugnsgeschwindigkeit erwartet.

Hat da Jemand schon mal ähnliche Erfahrungen gemacht?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPler schrieb:
> Hat da Jemand schon mal ähnliche Erfahrungen gemacht?
Es könnte sein, dass du das TX Register des Slave nicht schnell genug 
bedienst.
Wenn die Übertragung immer nur um 1 Bit verschoben ist, dann kann es 
auch einfach ein falscher SPI-Modus sein. Wobei du sicher auf dem Master 
und dem Slave den selben Mode verwendest.

> Korrigiert, sieht es bisher so aus: ...
Sehe ich das richtig: da sind jede Menge Dummy-Bytes unterwegs? Quasi 
Halbduplex-Betrieb: immer nur Senden oder empfangen, aber nicht beides 
gleichzeitig?

> um mehrere Bits verschoben beim Master ankommen.
Immer gleich viele Bits?
Und: renkt sich das dann wieder irgendwie ein?

: Bearbeitet durch Moderator
von MSPler (Gast)


Lesenswert?

Lothar M. schrieb:
> MSPler schrieb:
>> Hat da Jemand schon mal ähnliche Erfahrungen gemacht?
> Es könnte sein, dass du das TX Register des Slave nicht schnell genug
> bedienst.
Das halte ich erst mal für weniger wahrscheinlich, da sind wenige 
if/else Zweige im FSM bis jetzt. Aber ausschließen möchte ich es nicht.

>
>> Korrigiert, sieht es bisher so aus: ...
> Sehe ich das richtig: da sind jede Menge Dummy-Bytes unterwegs? Quasi
> Halbduplex-Betrieb: immer nur Senden oder empfangen, aber nicht beides
> gleichzeitig?
Ja, das sind "jede Menge" Dummy Bytes unterwegs. Ich habe mit dem 
"gleichzeitig" noch so meine Schwierigkeiten. Woher soll der Slave 
wissen was er "gleichzeitig" senden soll, ohne das er weiß, was der 
Master haben will ... ?!
>
>> um mehrere Bits verschoben beim Master ankommen.
> Immer gleich viele Bits?
> Und: renkt sich das dann wieder irgendwie ein?

Nein, ganz und gar nicht, erst nach einem Reset des Devices

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPler schrieb:
> Woher soll der Slave wissen was er "gleichzeitig" senden soll, ohne das
> er weiß, was der Master haben will ...
Ganz einfach: der Master sendet ein Kommando, das der Slave im 
nächsten SPI Zyklus beantwortet. So ist zwischen "Frage" (vom Master) 
und "Antwort" (vom Slave) immer 1 Zyklus Versatz. Aber(!) in jedem 
Zyklus wird eine neue Frage gestellt und die jeweils vorhergehende 
beantwortet.

Sieh dir einfach mal das SPI Protokoll eines mehrkanaligen ADC an. Beim 
ersten SPI Zyklus ist die Antwort Blödsinn, weil zuvor noch keine Frage 
gestellt wurde, aber danach kommt immer gleichzeitig mit dem nächsten 
Kommando ein neuer AD Wert als Antwort.

Und was bringt das Ganze?
Komplette zeitliche Entspannung. Denn wen der Master den SS inaktiv 
setzt muss der Master erst mal den erhaltenen Wert bearbeiten. Und 
solange kann der Slave das eben erhaltene Kommando parsen, bearbeiten 
und die Antwort für den nächsten SPI Zyklus bereitstellen. Ja, er kann 
sogar vorbereitend schon mal das erste Antwortbyte ins TX-Register 
schreiben.

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

MSPler schrieb:
> Es kommt in unregelmäßigen Abständen vor, dass die Daten vom Slave zum
> Master, also über MISO gesendete Worte, um mehrere Bits verschoben beim
> Master ankommen. Also statt 00001101 kommt 00011010 beim Master an.
>
> Ich habe alle Steckverbinderkabel schon ausgetauscht und sicher
> gestellt, dass alles richtig verbunden ist. Das Taktsignal sieht sauber
> aus, so wie man es bei 250 kHz Übertragugnsgeschwindigkeit erwartet.
 Wenn alle Steckverbinder in Ordnung sind und Taktsignal sauber, dann
 liegt es nicht am Master.
 SPI ist reine Hardware, da kann der Empfänger (in diesem Falle Master)
 nichts durcheinanderbringen, der Sender (Slave) aber sehr wohl.
 Es konnte allerdings sein, dass der Master zu schnell die Daten from
 Slave anfordert, das hat der lkmiller gemeint.

MSPler schrieb:
>> Es könnte sein, dass du das TX Register des Slave nicht schnell genug
>> bedienst.
> Das halte ich erst mal für weniger wahrscheinlich, da sind wenige
> if/else Zweige im FSM bis jetzt. Aber ausschließen möchte ich es nicht.
 Das halte ich für sehr wahrscheinlich, aber vielleicht hast du Recht.

> Ja, das sind "jede Menge" Dummy Bytes unterwegs. Ich habe mit dem
> "gleichzeitig" noch so meine Schwierigkeiten. Woher soll der Slave
> wissen was er "gleichzeitig" senden soll, ohne das er weiß, was der
> Master haben will ... ?!
 Deswegen schreibst du ein Protokoll, also eine Art Vereinbarung
 zwischen Master und Slave mit einem Byte Versatz, z.B:

 Master vorbereitet die Anfrage    Slave ist bereit, 0x55 im SPI_TxReg
1
     MASTER                   <====>         SLAVE (Int_Routine)
2
A) Was macht man so?     (0xAA)    Nichts, habe gerade etwas Zeit.(0x55)
3
B) Na, dann lese mal     (0x10)    Ich erwarte dein Kommando.     (0xAA)
4
C) Erst mal die Adresse  (0x38)    Ich warte auf die Adresse.     (0x10)
5
  Falls nötig, wartet MASTER ein bißchen, SLAVE liest Lo_Byte...
6
D) Und bitte noch Adresse(0x39)    Hier kommt Byte aus Adr.0x38 (Lo_Byt)
7
  Falls nötig, wartet MASTER ein bißchen, SLAVE liest Hi_Byte...
8
E) Das war es dann       (0xA0)    Hier kommt Byte aus Adr.0x39 (Hi_Byt)
9
                                              ||
10
                                              ||
11
                                              \/
12
                                        weiter im main()

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Und genau diese viele "Warterei" (in fast jedem Schritt wird da "wenn 
nötig" gewartet) möchte ich beim SPI nicht.
Ich mache eine Übertragung mit Vollgas fertig, werte die aus, mache was 
Anderes und dann kommt wieder ein SPI Transfer mit Vollgas ohne 
Warterei.

Allerdings muss ich eben damit klarkommen, dass ich die Antwort auf mein 
Kommando erst beim nächsten SPI Zyklus bekomme.

Zwei unterschiedliche Strategien, die zum Ziel führen...

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Lothar M. schrieb:
> Und genau diese viele "Warterei" (in fast jedem Schritt wird da "wenn
> nötig" gewartet) möchte ich beim SPI nicht.
 Nun, es kommt auf die Anwendung und SPI Geschwindigkeit an, deswegen
 sage ich auch 'falls notig'...
 Allerdings ist 250KHz extrem langsam fur SPI. Ich fahre nie langsamer
 als 2MHz. Somit bin ich sogar mit warten viel schneller als mit 250KHz
 ohne warten.

> Ich mache eine Übertragung mit Vollgas fertig, werte die aus, mache was
> Anderes und dann kommt wieder ein SPI Transfer mit Vollgas ohne
> Warterei.
 Beim ADC/DAC oder so etwas ist es auch am besten so, beim einfachem
 lesen der Register lohnt sich das wiederum kaum.

: Bearbeitet durch User
von echter MSPler (Gast)


Lesenswert?

Womit wir immer noch hier wären:
Beitrag "Re: SPI 16-Bit Problem"

Ihr seit die Größrten! :-(

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


Lesenswert?

echter MSPler schrieb:
> Womit wir immer noch hier wären:

 Troll dich irgendwo anders rum, Moron.

von MSPler (Gast)


Lesenswert?

Ich frage mich immer mehr, ob es sinnvoll ist, in der ISR eine FSM zu 
implementieren.

Letzlich habe ich mit Hilfe eurer Anregungen nun ein funktionierendes 
Stück Software, dass ein Register ansprechen und dann zwei Bytes 
auslesen kann, aber irgendwie erscheint mir das viel zu kompliziert.

Ich habe nun auf Master Seite einige zeitliche Verzögerungen eingebaut, 
insbesondere nachdem das CS auf low gezogen wird, nach dem Senden eines 
Bytes etc.

Damit bekomme ich zumindest das unnötige Bit-Shifting etwas besser in 
den Griff. Meine CPU läuft mittlerweile mit 8 MHz, statt mit 1 MHz und 
die SPI Kommunikation mit 1 kHz. Meiner Meinung nach ist das alles 
unkritisch.

Nur nochmal zum Verständnis, Senden eines Bytes:
1
while (!(IFG2 & UCA0TXIFG));  // USCI_A0 TX buffer ready?
2
UCA0TXBUF = cmd;

Empfangen eines Bytes:
1
while ((IFG2 & UCA0RXIFG) == 0);      // transfer complete?
2
rx_byte = UCA0RXBUF;                  // Read RXBUFFER
3
while (!(IFG2 & UCA0TXIFG));          // USCI_A0 TX buffer ready?
4
UCA0TXBUF = DUMMY;

Das kann man doch so machen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPler schrieb:
> Ich frage mich immer mehr, ob es sinnvoll ist, in der ISR eine FSM zu
> implementieren.
Merke: schon ein schäbiger Zähler ist eine primitive FSM.
> Ich frage mich immer mehr, ob es sinnvoll ist, in der ISR eine FSM zu
> implementieren.
Wenn schon irgendwas in einer FSM verwaltet werden soll, dann geht das 
nur über eine FSM. Aber es wird eben niemals gewartet, sondern nur 
der aktuelle Zustand ausgewertet und bei Bedarf weitergeschaltet. Wenn 
in einer FSM ein delay() drin ist oder ein while(), dann sind Probleme 
vorprogrammiert...

von MSPler (Gast)


Lesenswert?

Das mit dem "while" in der ISR bzw. FSM habe ich bei TI gesehen. Hat 
mich aber auch stutzig gemacht. Siehe Code:
1
#pragma vector=USCIAB0RX_VECTOR
2
__interrupt void USCI0RX_ISR (void)
3
{
4
  while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
5
  UCA0TXBUF = UCA0RXBUF;
6
}

Wenn ich alle diese "while"-Bedingungen aus der ISR bzw. FSM heraus 
nehme, wird überhaupt nichts mehr gesendet. Man könnte auch eine 
for-Schleife nehmen. Wenn die Bedingung nach z.B. 500 Mal nicht erfüllt 
ist --> break;

Ich halte euch auf dem Laufenden ;-)

Beste Grüße,
MSPler

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPler schrieb:
> Wenn ich alle diese "while"-Bedingungen aus der ISR bzw. FSM heraus
> nehme, wird überhaupt nichts mehr gesendet.
Ja, wer sagt denn, dass man die so einfach herausnehmen kann? Die sind 
in diesem Code sicher nicht zum Zeitvertreib drin (oder besser gesagt 
genau dafür...).

> Das mit dem "while" in der ISR bzw. FSM habe ich bei TI gesehen.
Da hat der Praktikant einfach was hinprogrammiert, was in seinem Fall 
sogar funktioniert haben kann.

Schlauer wäre es, den Interrupt so zu programmieren, dass er nur dann 
kommt, wenn der TX Buffer leer und aufnahmebereit ist...

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


Lesenswert?

MSPler schrieb:
> Das mit dem "while" in der ISR bzw. FSM habe ich bei TI gesehen. Hat
> mich aber auch stutzig gemacht. Siehe Code:#pragma
> vector=USCIAB0RX_VECTOR
> __interrupt void USCI0RX_ISR (void)
> {
>   while (!(IFG2 & UCA0TXIFG));              // USCI_A0 TX buffer ready?
>   UCA0TXBUF = UCA0RXBUF;
> }

 Hättest du ein bisschen aufmerksamer gelesen...
Marc V. schrieb:
> Master vorbereitet die Anfrage    Slave ist bereit, 0x55 im SPI_TxReg
> MASTER                   <====>         SLAVE (Int_Routine)
> A) Was macht man so?     (0xAA)    Nichts, habe gerade etwas Zeit.(0x55)
> B) Na, dann lese mal     (0x10)    Ich erwarte dein Kommando.     (0xAA)
> C) Erst mal die Adresse  (0x38)    Ich warte auf die Adresse.     (0x10)

 Dann hättest du gesehen, das der Slave den zuletzt empfangenen Byte
 immer zurücksendet ( falls es sich um ein Kommando handelt ).

 Nichts anderes wird auch im Beispiel von TI gemacht.

echter MSPler schrieb im Beitrag #4190781:
> Das wird ja immer spaßiger hier. Nachdem sich klein Marc weinend
> verabschiedet hat, ...
 Hat er nicht, nur wenn es dich betrifft, bin ich weg. Ich habe
 viel Verständnis für geistig zurückgebliebene, aber das heißt noch
 lange nicht, dass ich mit denen auch fruchtlose Diskussionen führen
 muss...

: Bearbeitet durch User
von MSPler (Gast)


Lesenswert?

>Schlauer wäre es, den Interrupt so zu programmieren, dass er nur dann
>kommt, wenn der TX Buffer leer und aufnahmebereit ist...

Interessanter Gedanke. Letzlich müsste man in der Hauptroutine das TX 
Buffer durch pollen abfragen und je nach Status den Interrupt frei 
geben. Zumindest verstehe ich deine Aussage so.


> Hättest du ein bisschen aufmerksamer gelesen...
Ich habe das gelesen und (glaube ich) auch so umgesetzt. Irgendwo im 
Source Code verbirgt sich dennoch ein Fehler, der mir heute verborgen 
geblieben ist. Vielleicht sticht er mir morgen früh gleich ins Auge ;-)

Euch allen einen schönen Abend.

von MSPler (Gast)


Lesenswert?

Meine Herren,

nach tagelangem rätseln und suchen habe ich heute morgen ENDLICH die 
fehlerhafte Zeile Sourcecode gefunden. Wer findet den Fehler?!
1
while (!(UCA0IFG & UCTXIFG));  // USCI_A0 TX buffer ready?              
2
UCB0TXBUF = cmd;

Sowas macht man einmal und hoffentlich nie wieder.

Beste Grüße,
MSPler

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Pass in Zukunft auf, wohin du die Strichpunkte machst. Und vor Allem, 
dass es nicht zu viele sind...  ;-)

: Bearbeitet durch Moderator
von Karl H. (kbuchegg)


Lesenswert?

Und gewöhn dich daran, dass in C weniger oft mehr ist
1
                    while ((IFG2 & UCA0TXIFG) == 1);

Ich habb keine Ahnung ob das UCA0TXIFG Bit so angeordnet ist, dass sich 
nach Ausmaskierung eine 1 ergibt, wenn es gesetzt ist.
Ich will es auch gar nicht wissen. Denn ich weiss eines mit Sicherheit. 
Wenn das Bit auf 1 ist dann ist das Ergebnis nach der Verundung nicht 0. 
Und das reicht mir schon
1
                    while ( IFG2 & UCA0TXIFG );

diese Schleife läuft garantiert solange, wie das Bit gesetzt ist. Und 
zwar unabhängig davon, an welcher Bitposition es sich im Register 
befindet.

Manchmal ist es in C schlauer, nicht explizit einen Vergleich zu 
schreiben, sondern auszunutzen, dass alle Ergebnisse ungleich 0 als 
logisch TRUE gewertet werden. Nach der Maskierung mit dem & kommt 
entweder 0 heraus (dann war das Bit auf 0) oder es kommt etwas ungleich 
0 heraus (dann war das Bit 1). Welcher Zahlenwert sich nach der 
Verundung genau ergibt, ist mir völlig schnuppe. Er ist nicht 0, und das 
reicht.

Mit einem expliziten Vergleich auf 1 schiesst man sich in solchen Fällen 
nur selbst ins Knie. Denn dazu muss das bewusste Bit an genau der 
richtigen Stelle im Register sitzen. Tut es das nicht, dann kommt eben 
nicht 1 raus, sondern 2 oder 4 oder 8 ...., und das ist nun mal nicht 1

Das ist eine der Sachen in C, bei denen Übereifer massiv schädlich ist.

: Bearbeitet durch User
von MSPler (Gast)


Lesenswert?

Ich wollte eigentlich darauf hinaus, dass es Blödsinn ist Buffer A0 
abzufragen, wenn man doch über B0 senden möchte.

Aber eure zusätzlichen Punkte treffen natürlich genauso zu.
Das ist eben "learning by doing" :-D

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

MSPler schrieb:
> Blödsinn ist Buffer A0 abzufragen, wenn man doch über B0 senden möchte.
Der ist natürlich auch nicht schlecht...   ;-)

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.