Forum: Mikrocontroller und Digitale Elektronik STM32 "SPI"-Slave 24 Bit ohne Chip Select


von Walter T. (nicolas)


Lesenswert?

Guten Morgen,

ich will meinen digitalen Meßschieber/Meßuhr mit einem STM32 (10x oder 
4xx) auslesen. Der Meßschieber sendet ein 24-Bit-Signal mit Takt mit ca. 
3,6 kHz, ähnlich SPI. Das Ende des Datentelegramms wird einfach mit 
einer Pause von 110 Millisekunden markiert.

Momentan lese ich das in einer flankengetriggerten ISR ein. Jetzt stellt 
sich natürlich die Frage, ob das auch komplett ohne oder mit weitaus 
geringerer Interrupt-Last mit einem USART oder SPI implementierbar ist.

Im Reference Manual RM0008 finde ich bei den SPIs keine Möglichkeit, 
einen Timeout zu setzen. Ansonsten könnte man mit dem unidirectional 
receive-only mode die Anzahl der Interrupts zumindest achteln.

Die Beschreibung der USART erschlägt mich mit der Menge der 
Möglichkeiten. Wenn ich das richtig verstehe, ist die Bitbreite des 
USART immer fest auf 8 Bit. Mit dem DMA kann ich immer 3 Bytes in einen 
Puffer schieben. Aber wie bekomme ich das auf den Anfang/Ende des 
Datentelegramms synchronisiert?

von STK500-Besitzer (Gast)


Lesenswert?

Du könntest doch einen Timer mit einer Pulslänge von ((24/ca. 3,6kHz)+x) 
bei der ersten Flanke starten.
Wenn der Puls abgelaufen ist, sind deine Daten vollsändig.

von Walter T. (nicolas)


Lesenswert?

STK500-Besitzer schrieb:
> Du könntest doch einen Timer mit einer Pulslänge von ((24/ca. 3,6kHz)+x)
> bei der ersten Flanke starten.

Dann brauche ich wieder den Flanken-Interrupt. Den will ich vermeiden, 
weil die Interrupt-Last insgesamt schon recht hoch ist.


Gibt es irgendwo eine gute Übersicht über die Betriebsmodi des USARTs?

Edit: Hoppla - sehe ich das richtig, daß der USART mit Clock-Signal nur 
als Master funktioniert, als Slave also nur ein UART ist?

: Bearbeitet durch User
von (Gast)


Lesenswert?

Walter T. schrieb:
> Guten Morgen,
>
> ich will meinen digitalen Meßschieber/Meßuhr mit einem STM32 (10x oder
> 4xx) auslesen. Der Meßschieber sendet ein 24-Bit-Signal mit Takt mit ca.
> 3,6 kHz, ähnlich SPI. Das Ende des Datentelegramms wird einfach mit
> einer Pause von 110 Millisekunden markiert.
>
> Momentan lese ich das in einer flankengetriggerten ISR ein. Jetzt stellt
> sich natürlich die Frage, ob das auch komplett ohne oder mit weitaus
> geringerer Interrupt-Last mit einem USART oder SPI implementierbar ist.
>
> Im Reference Manual RM0008 finde ich bei den SPIs keine Möglichkeit,
> einen Timeout zu setzen. Ansonsten könnte man mit dem unidirectional
> receive-only mode die Anzahl der Interrupts zumindest achteln.
>

Um den Timeout kann man sich ja "zu fuss" kümmern. SPI kann man auch per 
DMA auslesen.

Also in der Art

1) Sync auf 110ms Pause-Impuls abwarten
2) SPI und DMA aktivieren (3 bytes)
3) auf DMA transfer complete warten bzw. interrupt auslösen lassen bzw. 
wegen zeitüberschreitung doomsday device (while(1);) aktivieren.

von Walter T. (nicolas)


Lesenswert?

facepalm

Mist. Manchmal kommt man auf die einfachen Dinge nicht. Du hast Recht. 
Wenn irgendwo mindestens 50 Millisekunden Pause waren, ist das, was als 
nächstes kommt, (wenn etwas kommt), auf jeden Fall ein vollständiges 
Telegramm. Ich kann den SPI also einfach nach 50 Millisekunden Pause auf 
die Lauer legen und mich erst wieder dann um den DMA-Interrupt kümmern, 
wenn 3 Bytes empfangen wurde.

Danke für den Anstoß.

von Thomas F. (igel)


Lesenswert?

Walter T. schrieb:
> Der Meßschieber sendet ein 24-Bit-Signal mit Takt mit ca.
> 3,6 kHz, ähnlich SPI.

Ist das das Protokoll mit 6 Paketen zu je 4 Bit?

Ein SPI-Slave sollte eigentlich gehen, habe es aber noch nie 
ausprobiert. Ich arbeite auch noch mit Flanken-Interrupts.
In meiner Software prüfe ich in einem festen Zeitintervall (50ms?) ob 
neue Daten eingetroffen sind. Falls nein dann ist ein Datenpaket 
komplett und der Bit/Bytezähler wird wieder auf null gesetzt. Das 
funktioniert eigentlich sehr gut.
(Projekt ist in asm auf einem Atmega64 umgesetzt, der Sourcecode also 
nur begrenzt STM32-tauglich;-)

Edit: Während ich noch tippe hast du es selbst hreausgefunden

: Bearbeitet durch User
von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Thomas F. schrieb:
> Ist das das Protokoll mit 6 Paketen zu je 4 Bit?

Ja, genau (siehe Bild).

Thomas F. schrieb:
> (Projekt ist in asm auf einem Atmega64 umgesetzt, der Sourcecode also
> nur begrenzt STM32-tauglich;-)

Naja, bis auf die Einstellung des Flanken-Interrupts ist das ja auch 
halbwegs plattformunabhängig und funktioniert so einfach wie gut. Was 
ein wenig nervt, ist eben der Interrupt alle 0,3 Millisekunden. Wenn das 
auf einen Interrupt alle 100 Millisekunden reduziert wird, wäre das eine 
feine Sache.

von Sherlock Holmes (Gast)


Lesenswert?

Walter T. schrieb:
> Ja, genau (siehe Bild).

Wenn ich weiss dass 24 Bit kommen dann kann ich einfach die
Flanken zählen (zählen tut man mit einem Zähler, gell), da
brauche ich keine Interrupts für jede Flanke.

Walter T. schrieb:
> Naja, bis auf die Einstellung des Flanken-Interrupts

von Walter T. (nicolas)


Lesenswert?

Sherlock Holmes schrieb:
> zählen tut man mit einem Zähler

Was nützt mir das, außer daß ich den Gleichanteil und die Parität des 
Signals berechnen kann?

von Sherlock Holmes (Gast)


Lesenswert?

Walter T. schrieb:
> Was nützt mir das,

Du weisst wann dein SPI Telegramm vollständig eingetrudelt ist.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Das Problem am uSart ist, dass der ja noch start+stop Bit sehhen will 
und der USART XCK taktet nur bei den Datenbits.
Der ist daher nicht nutzbar für diese Schnittstelle.

Der SPI Slave hat ein Bit für ein internes CS, damit er immer denkt, 
dass er selektiert wurde.
Im SPI_CR1 SSM auf 1 setzen (=SSI Bit = nCS) und SSI auf 0 (nCS LOW).

Das Problem ist jetzt das Einrasten in die 24Bit Frames.
Dazu muss man dann wohl wirklich einmal nen Timer starten und abtasten 
wielange da Ruhe ist auf dem Portpin und dann nach x ms den DMA 
scharfschalten.

von Thomas F. (igel)


Lesenswert?

Walter T. schrieb:
> Was ein wenig nervt, ist eben der Interrupt alle 0,3 Millisekunden.

Hm, ja.
Ich lese 4 Messschieber auf einem Atmega ein. Klappt auch, habe aber 
sonst nur noch einen Interrupt am laufen. Aber der STM32 hätte ja sogar 
INT-Prios, damit sollte es doch eigentlich gehen.
Aber die Lösung per SPI und nur noch Bytes statt Bits lesen ist 
natürlich eleganter. Auf meinem Atmega hatte ich leider nicht genug 
SPIs, deshalb fiel das gleich mal weg.

Ist das ganze für die ELS? Da bin ich auch gerade dran mit einem ATXmega 
etwas zusammenzufrickeln.

von Beo Bachta (Gast)


Lesenswert?

Mw E. schrieb:
> Das Problem ist jetzt das Einrasten in die 24Bit Frames.

Nach definierter Aus-Zeit den SPI-Slave zurücksetzen damit
man garantiert das erste Bit richtig mitbekommt. Und
zählen, bis 24, mit Timeout.

von Walter T. (nicolas)


Lesenswert?

Mw E. schrieb:
> Im SPI_CR1 SSM auf 1 setzen (=SSI Bit = nCS) und SSI auf 0 (nCS LOW).

Mit dem Timeout den Chip Select beeinflussen. Die Idee klingt gut. Dann 
ist immer direkt alles richtig ausgerichtet. Als Timeout-Bedingung 
sollte die Bedingung "im Empfangspuffer steht schon seit 50 
Millisekunden das Gleiche" ausreichen.

Thomas F. schrieb:
> Ist das ganze für die ELS?

Ja. Momentan sind zwar keine Anbaumeßschieber geplant, aber ich will mir 
die Option offenhalten.

von Thomas F. (igel)


Lesenswert?

Walter T. schrieb:
> Als Timeout-Bedingung
> sollte die Bedingung "im Empfangspuffer steht schon seit 50
> Millisekunden das Gleiche" ausreichen.

Naja, es könnte ja einfach derselbe Wert wie vorher empfangen worden 
sein.

Ich kenne mich zwar mit den STM32 nicht so aus, aber wäre das RXNE-Flag 
da nciht das Richtige dafür?

von Walter T. (nicolas)


Lesenswert?

Thomas F. schrieb:
> Naja, es könnte ja einfach derselbe Wert wie vorher empfangen worden
> sein.

Wo ist das Problem? Wenn sich die Position nicht geändert hat, ist er ja 
genauso gültig.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

UART mit doppelter Baudrate und 4bit als Byte einlesen? Hab mir das 
Timing nicht supergenau angesehen.

von Gerd E. (robberknight)


Lesenswert?

Abdul K. schrieb:
> UART mit doppelter Baudrate und 4bit als Byte einlesen? Hab mir das
> Timing nicht supergenau angesehen.

wenn in dem oszi-screenshot die clock das obere signal ist, dann sieht 
mir das nicht sehr gleichmäßig aus. Das dürfte für eine UART eher 
schlecht funktionieren.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Das ist so ein mieses TDS220, die Samplerate ist da relativ schlecht. 
Könnnte also Jitter/Aliasing des Scopes sein.

von Gerd E. (robberknight)


Lesenswert?

Abdul K. schrieb:
> Das ist so ein mieses TDS220, die Samplerate ist da relativ schlecht.
> Könnnte also Jitter/Aliasing des Scopes sein.

wenn das alleine der Jitter von dem Scope ist, dann wäre das Ding ja 
komplett für die Tonne.

Bei den kurzen Pulsen im oberen Trace sieht man in dem Screenshot 2 
verschiedene Breiten. Das könnte gut der Jitter sein. Aber z.B. der 
dicke Block nach der 4. steigenden Flanke dürfte nicht vom Scope 
stammen.

von Sebastian S. (amateur)


Lesenswert?

Komisch, die letzten drei Messschieber, die ich in der Mache hatte, 
hatten kein so kompliziertes Protokoll. Einfach, blind RS232. Konnte man 
auch gut mit einem Terminal überprüfen.

von Abdul K. (ehydra) Benutzerseite


Lesenswert?

Gerd E. schrieb:
> Abdul K. schrieb:
>> Das ist so ein mieses TDS220, die Samplerate ist da relativ schlecht.
>> Könnnte also Jitter/Aliasing des Scopes sein.
>
> wenn das alleine der Jitter von dem Scope ist, dann wäre das Ding ja
> komplett für die Tonne.
>
> Bei den kurzen Pulsen im oberen Trace sieht man in dem Screenshot 2
> verschiedene Breiten. Das könnte gut der Jitter sein. Aber z.B. der
> dicke Block nach der 4. steigenden Flanke dürfte nicht vom Scope
> stammen.

Läßt sich ja leicht nachprüfen. Einfach am Timing-Knopf zwei Stufen 
weiter drehen und Jitter beobachten...


Der ASIC Designer war eh behindert oder es sollte ein 
Spezialempfängerchip gleich mit auf den Markt gedrückt werden.

......
Das TDS220 ist definitiv für die Tonne. Wir hatten so eines in der 
Firma, deren Chef gerne sparte. War immer ein Graus mit dem Ding. Der 
Samplespeicher hat glaub ich nur 400 Samples Speichertiefe. lach

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

das funktioniert auch komplett ohne ISR. Man sucht sich das richtige 
Pausenfenster und liest dann alles ein. Man schiftet die Bits in eine 
Variable rein. Bis zum nächsten Pausenfenster usw. Hatte ich mal mit 
2x24Bit Meßschiebern gemacht. Hast du auch eine Pegelanpassung davor 
geschalten?

von Gerd E. (robberknight)


Lesenswert?

Abdul K. schrieb:
> Der ASIC Designer war eh behindert oder es sollte ein
> Spezialempfängerchip gleich mit auf den Markt gedrückt werden.

Sieht mir eher nach etwas knapp dimensioniertem Mikrocontroller aus, der 
das per Bitbang nebenher mit ausgibt und halt hin und wieder in 
irgendwelche Interrupts springen muss.

von Thomas F. (igel)


Lesenswert?

Walter T. schrieb:
> Thomas F. schrieb:
>> Naja, es könnte ja einfach derselbe Wert wie vorher empfangen worden
>> sein.
>
> Wo ist das Problem? Wenn sich die Position nicht geändert hat, ist er ja
> genauso gültig.

Viellecht reden wir gerade aneinander vorbei:
Es ging mir um die Erkennung ob die 24Bit nun komplett sind um für die 
nächste Botschaft wieder von vorne zu beginnen. Ich habe es so 
verstanden du willst die vorhergehende Botschaft mit der aktuellen 
Botschaft vergleichen. Das scheint mir irgendwie zu unsicher im 
Vergleich zu einer Abfrage der SPI-Hardware ob innerhalb einer 
bestimmten Zeitspanne neue Daten eingetroffen sind.


Abdul K. schrieb:
> Das ist so ein mieses TDS220, die Samplerate ist da relativ schlecht.
> Könnnte also Jitter/Aliasing des Scopes sein.

Das Protokoll sieht tatsächlich so aus: Nach 4 Clocks/Bits kommt immer 
eine kurze Pause, dann gehts weiter.

von Walter T. (nicolas)


Lesenswert?

Thomas F. schrieb:
> du willst die vorhergehende Botschaft mit der aktuellen
> Botschaft vergleichen.

Nö, die Vorgehensweise ist: Immer 3 Bytes werden in eine 
(24)32-Bit-Variable gespeichert. Wenn diese Variable in den letzten 50 
Millisekunden nicht geändert wurde (wobei das in einem Abstand abgefragt 
werden muß, der kürzer als die Telegrammlänge ist), ist sie gültig, wird 
in eine statische Variable kopiert und der SPI wird zurückgesetzt und 
ist bereit für den nächsten Wert.

Das funktioniert, wenn der Meßschieber wechselne Werte sendet, ständig 
die gleichen Werte sendet oder gar nicht sendet.

Nachteil: Ich weiß erst 50 Millisekunden später, daß der Wert gültig 
ist. Da das aber nur eine Anzeige für Menschen und nicht Teil einer 
geschlossenen Regelschleife ist, ist das nicht weiter schlimm.

: Bearbeitet durch User
von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Guten Morgen,

falls jemand mit einem ähnlichen Anwendungsfall konfrontiert ist, habe 
ich jetzt mal meine Version wahlweise als Anregung oder abschreckendes 
Beispiel angehängt.

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.