Forum: Mikrocontroller und Digitale Elektronik HAL UART Fragen zum Grundverständnis


von An F. (hallofrage)


Lesenswert?

Hallo,

ich bin autodidaktischer Hobby-Programmierer und steige seit einiger 
Zeit vom AVR auf den STM32 um (ich programmiere in C) und habe seit 
Tagen Probleme, den UART in den Griff zu bekommen. Obwohl ich viel 
gelesen habe, habe ich den Eindruck, als ob mir da noch was vom 
Grundverständnis fehlt.

ich möchte bei einer 8-bit-Übertragung ein ganzes Byte empfangen und 
dann auswerten.

mein bisheriges Vorgehen:

Ich habe einen Buffer definiert:
uint8_t byte;

UART init: Das mache ich mit CubeMX und habe den Eindruck, dass ich da 
alles passend eingestellt habe. In die main.c kommt dann:

HAL_Init();
MX_USART2_UART_Init();

Den Interrupt aktivieren:
HAL_UART_Receive_IT (&huart2, &byte, 1);

Dann muss nach meinem bisherigen Verständnis mein Code für den Interrupt 
in folgende Funktion: HAL_UART_RxCpltCallback

Es gehört sich natürlich nicht, das in einem Interrupt zu tun, aber ich 
habe zum ersten Testen jetzt nicht mit Flags und Buffern gearbeitet, 
sondern versuche die eingehenden Daten direkt im Interrupt auszuwerten 
(nur zum Testen). Am Ende aktiviere ich den Interrupt wieder für den 
nächsten Durchgang.
Sieht im Ergebnis etwa so aus:

void HAL_UART_RxCpltCallback (UART_HandleTypeDef *huart){

  HAL_GPIO_TogglePin (LED1);

  if( byte==0x90){
    HAL_GPIO_TogglePin (LED2);
    }

  HAL_UART_Receive_IT (&huart2, &byte, 1);
}

Mein bisheriges Ergebis:
Immer, wenn Daten beim Uart ankommen, toggelt LED1, LED2 toggelt nie, 
auch wenn ein "0x90" an den UART gesendet wird.

Was mache ich falsch?

Würde mich über Anregungen sehr freuen.
Vielen dank.

Beste Grüsse
OG

von karadur (Gast)


Lesenswert?

An F. schrieb:
> HAL_UART_Receive_IT (&huart2, &byte, 1);

Sollte das nicht vor die Abfrage?

von Johannes S. (Gast)


Lesenswert?

falsche Bitrate? Gerade beim Testen von Neuer/Fremder Software ist ein 
Debugger hilfreich. Breakpoint setzen und gucken was im byte (blöder 
Variablenname) ankommt.
Bitrate evtl. falsch wegen falscher Clock Configuration, die sollte man 
sich in CubeMX genau ansehen.

von Johannes S. (Gast)


Lesenswert?

karadur schrieb:
> Sollte das nicht vor die Abfrage?

das ist ok, damit wird gleich wieder der nächste Empfang gestartet.

von hochladen (Gast)


Lesenswert?

>auch wenn ein "0x90" an den UART gesendet wird.

Dumme Frage: Sendest Du ein Byte mit dem numerischen Wert 0x90 oder
einen String "0x90"?

Warum benutzt Du keinen Debugger, um herauszufinden, was tatsächlich im 
UART Datenregister ankommt?

von hochladen (Gast)


Lesenswert?

>Bitrate evtl. falsch wegen falscher Clock Configuration,

Zur Klärung dieser und ähnlicher Fragen holt  man seinen 5EUR Logic 
Analyzer in der Kiste.

Ja, vielleicht viel zu lernen auf einmal, aber früher oder später 
braucht man das halt.

von An F. (hallofrage)


Lesenswert?

Hallo,

vielen Dank für die schnellen Antworten.

@karadur: Ich aktivieren den Interrupt einmal in der main.c beim Starten 
und dann kann er das erste mal empfangen und immer, wenn er empfangen 
hat, kommt die ISR und darin wird er (ganz am Ende) fürs nächste mal neu 
gestartet.
So habe ich das bisher verstanden - keine Ahnung, ob das stimmt.

@johannes: Die Clock ist ein guter guter Hinweis. Beim Testen der Timer 
habe ich zwar alles eingestellt und die Zeiten auch mal gestoppt und es 
stimmte, aber vielleicht hat sich das was verstellt - werde ich mir 
nochmal mit Ruhe anschauen.
Bisher habe ich nicht mit Debugger gearbeitet - vermutlich ist es jetzt 
an der Zeit, sich das mal anzuschauen.

Nehme gerne weitere Hinweise entgegen ;-)
Vielen Dank.

Beste Grüsse
OG

von An F. (hallofrage)


Lesenswert?

Hallo,

@hochladen: Vielen Dank für die Hinweise.

Ich sende den nummerischen Wert 0x90 (es handelt sich genau genommen um 
MIDI-Daten).

Mit dem Debugger habe ich ja eben schon gechrieben: es scheint wohl an 
der Zeit zu sein, sich das anzuschauen.

Beste Grüsse
OG

von stinkywinky (Gast)


Lesenswert?

Die Abfrage von if( byte==0x90) bringt nichts, da byte ja nirgends 
gesetzt wird

von georg (Gast)


Lesenswert?

An F. schrieb:
> immer, wenn er empfangen
> hat, kommt die ISR und darin wird er (ganz am Ende) fürs nächste mal neu
> gestartet.

Normalerweise wird ein Interrupt einmal eingerichtet und tritt dann 
jedesmal auf, wenn das Ereignis eintritt, sprich ein Byte empfangen 
wurde. Solange bis man ihn gezielt wieder abschaltet, was oft nicht 
notwendig ist, bis das Programm beendet wird.

Was passiert wenn ein schon gestarteter Interrupt erneut initialisiert 
wird kann man ohne nähere Analyse nicht sagen.

Georg

von Stefan F. (Gast)


Lesenswert?

Unabhängig von dem akuten Problem:

Wir hatten das Thema erst vor einigen Wochen. Dein Vorhaben ist mit der 
HAL nicht ganz unproblematisch. Die Routinen der HAL sind toll, wenn man 
Datenpakete mit fester Größe empfangen will. Bei einzelnen Bytes läuft 
es aber auf einen gewaltigen Overhead hinaus. Damals wurden zwei 
Lösungsvorschläge erarbeitet:

a) Die HAL nicht benutzen, eine eigene ISR schreiben.

b) Die HAL soll immer abwechselnd zwei Puffer (mit einigen Bytes) via 
DMA befüllen, die beim Auslesen wie ein zusammenhängender Puffer 
behandelt werden.

Ich möchte Dir empfehlen, darüber nachzudenken, ob die HAL hier für 
deinen Anwendungsfall überhaupt geeignet ist. Nicht dass du da viele 
Stunden Zeit versenkst um am Ende zu bemerken, dass du die Zeichen (mit 
HAL) gar nicht schnell genug empfangen und verarbeiten kannst.

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Die Routinen der HAL sind toll, wenn man
> Datenpakete mit fester Größe empfangen will. Bei einzelnen Bytes läuft
> es aber auf einen gewaltigen Overhead hinaus.

Ach was!
Das ist kein Problem, und der Ansatz des TO ist vollkommen korrekt.
Im Anhang einer funktionierender Code inkl. Beispiel, der das genau so 
macht.

von Johannes S. (Gast)


Lesenswert?

Es ging doch um einen ersten Test und dafür sieht der Code korrekt aus.
Auch das im Callback gleich wieder das nächste Lesen angestoßen wird ist 
ok. Die Funktion ist nicht blockierend und startet einen Empfang für n 
Byte, danach ist Schluss. Nicht effizient, muss aber laufen.
Für effizienten Empfang kann man sich das hier ansehen: 
https://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

An F. schrieb:
> mein bisheriges Vorgehen:
>
> Ich habe einen Buffer definiert:
> uint8_t byte;
>
> UART init: Das mache ich mit CubeMX und habe den Eindruck, dass ich da
> alles passend eingestellt habe. In die main.c kommt dann:
>
> HAL_Init();
> MX_USART2_UART_Init();
>
> Den Interrupt aktivieren:
> HAL_UART_Receive_IT (&huart2, &byte, 1);
>
> Dann muss nach meinem bisherigen Verständnis mein Code für den Interrupt
> in folgende Funktion: HAL_UART_RxCpltCallback

Naja, typisch ST eben. Viel Aufwand für wenig Ergebnis, dafür aber sehr 
ST-spezifisch und unportierbar.

Vermutlich weißt du nicht, was im Detail all dieses Cube- und HAL-Zeugs 
intern veranstaltet - weiß ich auch nicht, aber ich mache da ja auch 
einen großen Bogen drum herum.

Normalerweise muß man so etwa folgendes tun: Pins einrichten, Takt für 
den UART freigeben, UART aufsetzen, passende ISR im Code vorhalten, im 
NVIC den Interrupt freigeben. Anschließend sollte man mit den 
Interface-Funktionen des UART-Treibers den UART nach Belieben benutzen 
können.
Ich hänge dir mal ein Beispiel zum Lesen dran, ist für den STM32F302RBT6 
und schon ein paar Jahre alt. Da kannst du dir das Prinzip anschauen: 
Der UART wird nach seiner Initialisierung nur per ISR bedient und 
diese schaufelt die Daten von bzw. in einen Ringpuffer. Die Funktionen 
zum Benutzen fassen den UART nicht an (mit einer Ausnahme: zum Senden 
wird der Sendeinterrupt eingeschaltet), sondern verkehren nur mit dem 
Ringpuffer.
Ach ja: die Pin-Funktionalität (also kein GPIO, sondern UART) und der 
generelle Takt müssen vorher woanders erledigt werden. In dem Treiber 
sind alle UARTS des o.g. Chips drin, also müßtest du alles, was du nicht 
brauchst, einfach rausschmeißen. Aber man kann daran die Funktionalität 
erkennen, die zu einem herstellerunabhängigen Interface in der Firmware 
führt.

Nochwas: Ein UART soll 8 Bit Zeichen befördern. Also ist dort ein 
schlichter char angesagt und kein uint8_t. Es sollen ja Zeichen und 
keine Rechengrößen sein.

W.S.

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


Lesenswert?

Mal wieder ein typischer W.S. mit dem 5 fachen an nötigen Code.
Wieso schreibt/kopiert man 5 mal den selben Code hin anstatt eine 
Funktion aufzurufen?
Das sind C Grundlagen!

Deine Magic Numbers kannste auch behalten.
Im Vergleich zu deinem Code wirkt der HAL ja sogar bugfrei und 
aufgeräumt!

von Pandur S. (jetztnicht)


Lesenswert?

Wenn man mit Interrupt arbeitet sollte man solchen blockierenden Mist 
vergessen.
   HAL_UART_Receive_IT (&huart2, &byte, 1);

Was soll das ?

Man verwendet eine Statusmaschine ausserhalb des Interrupts.

var rxcame:boolean;
    myrxbuffer:byte;   // sofern ein byte genuegt.

procedure processrx;
 switch myrxbuffer {
  0x01 : ..
 }

interrupt receiveuart;
 myrxbuffer:=UARTRx; // lesen des UARTs
 rxcame:=true;
end interrupt;

im main dann

 main()
  loop
   if rxcame { processrx; }
   ..
  endloop;

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

Joggel E. schrieb:
> Wenn man mit Interrupt arbeitet sollte man solchen blockierenden Mist
> vergessen.
>    HAL_UART_Receive_IT (&huart2, &byte, 1);

Wer keine Ahnung hat, sollte einfach mal....
...und statt dessen besser mal die Doku lesen und verstehen!

Da blockiert nix!

: Bearbeitet durch User
von An F. (hallofrage)


Lesenswert?

Hallo,

vielen Dank für die vielen Antworten!

Ich habe jetzt keine Zeit, aber werde mir das bei nächster Gelegenheit 
mal alles in Ruhe anschauen.
Dann werde ich weiter nachfragen oder Erfolg berichten.

Beste Grüsse
OG

von Zeno (Gast)


Lesenswert?

Mw E. schrieb:
> Mal wieder ein typischer W.S. mit dem 5 fachen an nötigen Code.
> Wieso schreibt/kopiert man 5 mal den selben Code hin anstatt eine
> Funktion aufzurufen?
> Das sind C Grundlagen!
> Deine Magic Numbers kannste auch behalten.


Warum muß Du nun schon schon wieder rum motzen, bloß weil Du die 4 
Zeichen W.S. liest?
Er ist doch hier ganz sachlich geblieben und hat's erklärt, wie er an 
die Sache ran geht und damit sollte es gut sein. Du kannst darfst es 
gern anders machen, es zwingt Dich auch keiner Magicnumbers zu verwenden 
(übrigens lese ich in W.S.'s Post nicht eine Magicnumber).
Der Tip von W.S. ist doch nicht ganz verkehrt, wenn er vorschlägt das 
Ganze soweit es geht hardwareunabhängig, damit unabhängig von irgend 
welchen Herstellerbibliotheken und damit portierbar zu machen.

W.S. hat das ja nicht zum ersten Mal hier gepostet. Auch wenn es hier 
keiner hören mag, er verwendet diesen Code ja auch in der berühmt 
berüchtigten Lernbetty und dort funktioniert es. Ich habe diesen Code 
auf einem MSP430 und auch dort funktioniert er anstandslos.

> Im Vergleich zu deinem Code wirkt der HAL ja sogar bugfrei und
> aufgeräumt!
Tja der Unterschied scheint ja offensichtlich zu sein, das es mit der 
bugfreien und aufgeräumten HAL nicht so wie gewünscht funktioniert. 
Wenn's so problemlos wäre würde der TO nicht tagelang mit diesem Problem 
zu bringen und hier nicht anfragen.

von Johannes S. (Gast)


Lesenswert?

der W.S. Post war sein übliches ST/HAL bashing, schon im ersten Satz. 
Ohne sich damit näher damit beschäfftigt zu haben wie er selber zugibt.
Das der Code vom TO prinzipiell richtig ist wurde hier doch oft genug 
geschrieben, es gibt aber noch andere Fehlerquellen und die werden die 
Ursache sein.
Im HAL Code werden auch Fehler abgehandelt, darauf verzichten viele 
andere Beispiele. Man muss nur die entsprechenden Callbacks erstellen 
und aktivieren, das liefert für erste Tests auch gleich viel mehr Infos.
Und Portierbarkeit ist immerhin innerhalb der ST Familien gegeben, und 
das ist mittlerweile ein ganzes Universum an Controllern. Auch die 
Umstellung auf DMA ist nicht kompliziert weil das in der HAL immer nach 
dem gleichen Schema läuft. Man muss sich nur damit beschäfftigen und es 
verstehen.

von Zeno (Gast)


Lesenswert?

Johannes S. schrieb:
> der W.S. Post war sein übliches ST/HAL bashing, schon im ersten Satz.

Mein Gott bist Du empfindlich.
Den ersten Absatz im Post überliest man geflissentlich, obwohl ja dieser 
Teil "ST-spezifisch und unportierbar" definitiv richtig ist.

Johannes S. schrieb:
> Und Portierbarkeit ist immerhin innerhalb der ST Familien gegeben, und
> das ist mittlerweile ein ganzes Universum an Controllern.
Ja für einige ist ST offenbar wirklich das ganze Universum. Und auch 
wenn es diese Leute nicht wahr haben wollen das Universum ist deutlich 
größer.
Wer gewillt ist ab und an über dieses Universum hinaus zu schauen, der 
tut eben gut daran, die Herstellerbibliotheken, egal ob von ST oder TI 
oder ..., so sparsam wie nur irgend möglich einzusetzen und sich seine 
eigene Codebasis zu schaffen, die halt portierbar und auf möglichst 
vielen Controllern einsetzbar ist. Ist am Anfang vielleicht etwas 
steiniger, beschert aber einem am Ende wiederverwendbaren Code ohne das 
man das Rad jedes mal neu erfinden muß.
Das die Bibliotheken des Herstellers eben auch ihre Tücken habe beweist 
eben dieser Thread.

Letztendlich ist es egal wie man zum Ziel gelangt und dem der die 
Hardware benutzt ist es am Ende auch egal ob da im Code 
Herstellerbibliotheken, eigener Gehirnschmalz, Magicnumbers oder sonst 
was verwendet wird - es muß funktionieren.

Letztendlich muß sich hier der TO entscheiden, welchen Lösungsweg er am 
Ende einschlägt und da ist der Weg des W.S. einer von mehreren.

von Johannes S. (Gast)


Lesenswert?

Zeno schrieb:
> Mein Gott bist Du empfindlich.

ich habe genug Posts von W.S. gelesen. Da gibt es immer nur zwei 
Lösungen: seine und die Falsche.

von Zeno (Gast)


Lesenswert?

Johannes S. schrieb:
> ich habe genug Posts von W.S. gelesen. Da gibt es immer nur zwei
> Lösungen: seine und die Falsche.

Halt nur gelesen.

von Matthias (Gast)


Lesenswert?

Also die peripheral libraries von ST sind schon seit Jahren gut und 
werden immer besser. Ich arbeite gerne damit. Aber es gibt natuerlich 
immer noch genug Programmierer mit dem "Not invented by me" Syndrom. 
Wers mag...

Davon abgesehen:
UARTS muessen natuerlich NICHT per Definition 8bit transportieren, da 
gibt es exotische Abweichungen, und uint8_t zu benutzen is gar kein 
Problem und wuerde ich auch empfehlen. Eindeutig, gut lesbar, prima. 
uint8_t ist unter Wasser sowieso einfach nur wieder ein typedef Richtung 
char. So what...

Ich verstehe die Interrupt Konstruktion allerdings auch nicht so ganz, 
ich seh nicht wo "byte" gesetzt wird. Du gibst einen Pointer zu "byte" 
an die Funktion die den Interrupt setzt, was da drin passiert kan ich 
nicht sehen.

von Johannes S. (Gast)


Lesenswert?

Matthias schrieb:
> Du gibst einen Pointer zu "byte" an die Funktion die den Interrupt
> setzt, was da drin passiert kan ich nicht sehen.

Das ist eine HAL Funktion, die bekommt einen Zeiger auf einen Buffer und 
die Anzahl Elemente die gelesen werden sollen. Nicht Anzahl Byte, bei 
einer 9 Bit Schnittstelle würden n 16 Bit Worte gelesen. Das passiert in 
der ISR die auch im HAL Code liegt. Der gezeigte Callback wird 
aufgerufen wenn die gewünschte Anzahl komplett ist. Es gibt weitere 
Callbacks für HalfComplete (bei der DMA Version) und Fehler.

@TO: ein billiger Fehler wäre noch wenn die simple Diagnose mit LED2 
nicht funktioniert, hast du mal die LED vertauscht oder getestet ob die 
LED2 überhaupt toggelt?

von allesKäse (Gast)


Lesenswert?

W.S., warum nutzt du keine Structübergabe an Funktionen für den UART?
ARM gibt das auch so vor.

von W.S. (Gast)


Lesenswert?

Johannes S. schrieb:
> ich habe genug Posts von W.S. gelesen. Da gibt es immer nur zwei
> Lösungen: seine und die Falsche.

Ja. Genau. Hier haben wir immer wieder das gleiche Szenario: Jemand 
macht es auf seine Weise, benutzt Cube und Hal oder sonstwas - und es 
funktioniert nicht, das ist also die falsche Lösung. Nun wird hier um 
Hilfe nachgesucht. Tja und das, was ich hier poste, das funktioniert 
eben. Zumindest sollte es jedem, der hier nachfragt, genug zum Lesen 
geben, damit er ne Anregung bekommt um es aus eigener Kraft besser zu 
machen als sein erster Versuch, der nicht funktioniert. Das ist eben 
meine Lösung.

Nochwas: Genau obiger Unterschied macht's: es gibt meine Lösung die geht 
und es gibt viele andere Lösungsversuche, die eben nicht gehen. 
Selbstverständlich gibt es auch gefühlte 1000 andere Lösungen, die 
funktionieren - aber deren Autoren landen hier nicht mit einem Hilferuf, 
sondern machen einfach ihr Ding.

Fazit:
Wer keine Hilfe will, soll es gefälligst selber machen.
Wer alles besser weiß, soll es gefälligst besser machen und hier posten, 
damit Andere daraus was lernen können.
Wer hier bloß herumlabert, weil er "genug Posts" gelesen hat, soll 
einfach was Anderes lesen und die Klappe halten.

Ich habe jedoch ernste Bedenken, wenn jemand hier sowas schreibt:
Johannes S. schrieb:
> Portierbarkeit ist immerhin innerhalb der ST Familien gegeben, und
> das ist mittlerweile ein ganzes Universum an Controllern...

Jaja: "DU SOLLST KEINEN GOTT AUSSER ST HABEN" oder so ähnlich. Mit 
meinen Worten heißt das Scheuklappen.

W.S.

von Walt N. (belayason)


Lesenswert?

Hätte auch noch eine Frage die passen zu diesem Thema passt.
Ich möchte meine Sensor daten die wie folgt definiert sind
1
typedef struct {
2
    uint8_t  sensor_id;
3
    int16_t x;
4
    int16_t y;
5
    int16_t z;
6
    int16_t w;
7
    int16_t estimated_accuracy;
8
} bhy_data_quaternion_t;

diese habe ich versucht so zu übertragen.
1
  HAL_UART_Transmit(&huart2,(uint8_t*)&sensor_data->data_quaternion.x, strlen(sensor_data->data_quaternion.x), HAL_MAX_DELAY);
2
  HAL_UART_Transmit(&huart2,(uint8_t*)&sensor_data->data_quaternion.y, strlen(sensor_data->data_quaternion.y), HAL_MAX_DELAY);
3
  HAL_UART_Transmit(&huart2,(uint8_t*)&sensor_data->data_quaternion.z, strlen(sensor_data->data_quaternion.z), HAL_MAX_DELAY);
4
  HAL_UART_Transmit(&huart2,(uint8_t*)&sensor_data->data_quaternion.w, strlen(sensor_data->data_quaternion.w), HAL_MAX_DELAY);
mit putty lese ich aus der seriellen schnittstelle aber nur unbekannte 
zeichen. Stimmt der typecast von uint_t 16 zu uint_t 8 ?

von Harry L. (mysth)


Lesenswert?

Walt N. schrieb:
> strlen(sensor_data->data_quaternion.x)

Das ist Mist!
Versuchs mal mit sizeof!

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

allesKäse schrieb:
> W.S., warum nutzt du keine Structübergabe an Funktionen für den UART?
> ARM gibt das auch so vor.

An welcher Stelle sollten Structs denn da nützlich sein?

Ich halte die Funktionen schlichtweg separat und das hat gute Gründe: 
zum einen hat damit der Linker eine Chance, im konkreten Projekt 
unbenutzte Funktionen wegzulassen und zum anderen ist das Verzweigen auf 
verschiedene Datenkanäle mit Structs viel zu eingeengt und umständlich - 
da arbeitet man besser mit Handles und einer über der Lowlevel-Schicht 
liegenden Verteilerschicht.

Obendrein braucht ein Handler, der nur für genau einen Kanal zuständig 
ist, auch weniger Logik und damit Platz, als einer der für alle UART's 
zuständig ist.

Sowas hab ich auch, siehe Anhang. Damit kann man vom Prinzip her UARTs, 
CDC-USB, Textfiles auf SD-Karte und anders unter einen Hut kriegen, ohne 
daß man dazu in den einzelnen Lowlevel-Treibern herumwühlen müßte. Die 
Quellen im Anhang enthalten nur die Ansätze (CharToFileStream und 
CharToCommandWindow) und je nach Controllerfamilie gibt es auch nicht 
alle angedachten UART's etc. Insofern ist das als generisch anzusehen 
und muß einmal an den jeweiligen µC angepaßt werden. Aber dieser Ansatz 
ist eben viel universeller als jeder Ansatz per Struct - und das Ganze 
ist portabel im Gegensatz zu Structs.

Mit meinem Ansatz kann man auf unterschiedliche Weise arbeiten: entweder 
man benutzt gio.c und schreibt z.B. String_Out("Hallo", toUART1) oder 
man verzichtet auf gio.c, wenn zu wenig Platz im Flash ist und benutzt 
den betreffenden LL-Handler direkt.

W.S.

von W.S. (Gast)


Lesenswert?

Walt N. schrieb:
> typedef struct {
> ...
> } bhy_data_quaternion_t;
> diese habe ich versucht so zu übertragen.

Das ist ein ausgesprochen schlechter Ansatz, denn das ganze soll ja über 
eine Kommunikationsstrecke gehen. Bei sowas sollte man jedoch wenigstens 
irgend etwas zum Synchronisieren dazu tun.

Entweder man sendet das alles in Textform, was sich leicht 
synchronisieren läßt (denke mal an die Zeile, die man bei einem 
GPS-Empfänger hat) oder man müßte all die Blöcke wenigstens mit UU 
codieren oder als allererstes im Struct einen Kenner (z.B. const char[4] 
= "0815"; oder so) anordnen. Möglichst so einen Kenner, daß er 
garantiert nicht zufällig als Sequenz im restlichen Struckt vorkommen 
kann.

W.S.

von Johannes S. (Gast)


Lesenswert?

W.S. schrieb:
> Tja und das, was ich hier poste, das funktioniert eben.

Nein, auch nicht immer. Und das der  Code falsch sein soll oder HAL nix 
taugt behaupten die die sich nicht damit beschäftigen. Die müssen es ja 
wissen.

von An F. (hallofrage)


Lesenswert?

Hallo,

Problem gelöst - Johannes hatte den entscheidenden Tipp:

Johannes S. schrieb:
> Bitrate evtl. falsch wegen falscher Clock Configuration, die sollte man
> sich in CubeMX genau ansehen.

Vielen Dank nicht nur an ihn, sondern Euch alle für die Hinweise. Ich 
werde mir die auch noch alle in Ruhe anschauen, weil da steckt ja mehr 
drin, als die reine Problemlösung in diesem konkreten Fall.

Beste Grüsse
OG

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.