Forum: Mikrocontroller und Digitale Elektronik STM32 HAL UART Mysterium oder bin ich dumm?


von Jana (Gast)


Angehängte Dateien:

Lesenswert?

Hallo nochmal, pünktlich zum Wochenende(eig schon gestern) hat sich mir 
noch ein für mich nicht mehr begreifbares Problem eröffnet. Eig möchte 
ich nur Daten über den UART senden. Das funktioniert nur bedingt.

Hier mein ursprünglicher Code funktioniert nicht (interessanterweise 
werden die ersten beiden Zeichen immer richtig übertragen):
1
void COM_SendNFI(){
2
  char msg2[11] = "NFI(X0001)\n";
3
  while (UART_Transmitting);
4
  UART_Transmitting = 1;
5
  HAL_UART_Transmit_IT(&huart2, (uint8_t*)msg2, strlen(msg2));
6
}
7
//Output: "NF##############" (Output1.png)

Definiere ich den String allerdings wie folgt, funktioniert alles:
1
void COM_SendNFI(){
2
  char* msg2 = "NFI(X0001)\n";
3
  while (UART_Transmitting);
4
  UART_Transmitting = 1;
5
  HAL_UART_Transmit_IT(&huart2, (uint8_t*)msg2, strlen(msg2));
6
}
7
//Output: "NFI(X0001)" (Output2.png)

Nehme ich die blockierende Routine (also ohne Interrupt), funktioniert 
es auch:
1
void COM_SendNFI(){
2
  char msg2[11] = "NFI(X0001)\n";
3
  HAL_UART_Transmit(&huart2, (uint8_t*)msg2, strlen(msg2),500);
4
}
5
//Output: "NFI(X0001)" (Output2.png)

Setze ich hinter meinen ursprünglichen Code ein Delay, funktioniert es 
ebenso:
1
void COM_SendNFI(){
2
  char* msg2 = "NFI(X0001)\n";
3
  while (UART_Transmitting);
4
  UART_Transmitting = 1;
5
  HAL_UART_Transmit_IT(&huart2, (uint8_t*)msg2, strlen(msg2));
6
  HAL_Delay(1);
7
}
8
//Output: "NFI(X0001)" (Output2.png)

Und jetzt, zu meiner völligen Verwirrung, nehme ich wieder meinen 
ursprünglichen Code und sende einfach zwei mal hintereinander, kommt 
einmal der richtige String und einmal der schon bekannte kaputte String 
an. Auch hier werden die ersten beiden Zeichen immer richtig übertragen.
1
void COM_SendNFI(){
2
  char* msg2 = "NFI(X0001)\n";
3
  while (UART_Transmitting);
4
  UART_Transmitting = 1;
5
  HAL_UART_Transmit_IT(&huart2, (uint8_t*)msg2, strlen(msg2));
6
  HAL_Delay(1);
7
}
8
//Output: "FI(X0001)NF##############" (Output3.png)

Hat hier jemand eine Erklärung bzw kann mir einer weiterhelfen. Ich 
würde schon gerne char* und Interrupt nutzen. Aber ohne Delay. Ich 
verwende den STM32G0. Interrupts sind zwar noch weitere eingeschaltet, 
aber alle geringerwertig priorisiert.

von Klaus W. (mfgkw)


Lesenswert?

Dein array ist nicht wirklich lang genug...
strlen() braucht die abschließende \0, die passt aber gar icht mehr ins 
msg2[11].
Wenn du die Länge nicht angibst, nimmt der Compiler genug für den String 
inkl. der \0.

: Bearbeitet durch User
von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

Ich hab dir mal funktionieren Ciode für UART mit HAL angehängt.

von Bernd (Gast)


Lesenswert?

Der Platz für die abschließende 0 fehlt in der 1. Variante

Bernd

von Daniel S. (daniel_s)


Lesenswert?

HI,
schau dir die Gültigkeit der Variable an.
Bsp 1: msg2 liegt auf dem Stack und wird ungültig wenn du die Funktion 
verlässt und wird wieder überschrieben. Der UART ist aber noch nicht 
fertig mit senden.

Bsp 2: Der String liegt als Konstante irgendwo im Speicher und nur der 
Zeiger darauf wurde übergeben. Der Uart kann also weiterhin auf diesen 
String zugreifen und schicken.

In den anderen Beispielen wird die Gültigkeit der Variable verlängert 
bis der String draussen ist.

DAniel

Natürlich fehlt auch die abschließende 0.

: Bearbeitet durch User
von Jana K. (jana-k)


Lesenswert?

Klaus W. schrieb:
> Dein array ist nicht wirklich lang genug...
> strlen() braucht die abschließende \0, die passt aber gar icht mehr ins
> msg2[11].
> Wenn du die Länge nicht angibst, nimmt der Compiler genug für den String
> inkl. der \0.

Da hast du Recht, dummerweise ist mir hier ein Fehler beim Abschreiben 
passiert. Das X gehört nicht rein. Aber auch mit der richtigen Länge 
funktioniert es nicht.

von Jana K. (jana-k)


Lesenswert?

Daniel S. schrieb:
> Bsp 1: msg2 liegt auf dem Stack und wird ungültig wenn du die Funktion
> verlässt und wird wieder überschrieben. Der UART ist aber noch nicht
> fertig mit senden.
>
> Bsp 2: Der String liegt als Konstante irgendwo im Speicher und nur der
> Zeiger darauf wurde übergeben. Der Uart kann also weiterhin auf diesen
> String zugreifen und schicken.
>
> In den anderen Beispielen wird die Gültigkeit der Variable verlängert
> bis der String draussen ist.

Ahhhhhhhhh, Danke <3

Dann könnte ich die Gültigkeit mit static doch erhalten, oder?

: Bearbeitet durch User
von Klaus W. (mfgkw)


Lesenswert?

Jana K. schrieb:
> ... Aber auch mit der richtigen Länge
> funktioniert es nicht.

Dann kommt noch der Tipp von Daniel S. ins Spiel...

von Klaus W. (mfgkw)


Lesenswert?

Jana K. schrieb:
> Dann könnte ich die Gültigkeit mit static doch erhalten, oder?

ja, aber natürlich darf die Funktion dann nur einmal laufen zu jedem 
Zeitpunkt.

Beitrag #6855658 wurde vom Autor gelöscht.
von A. S. (Gast)


Lesenswert?

Klaus W. schrieb:
> Dein array ist nicht wirklich lang genug...

Also auch wohl die meisten Warnungen aus. Das sollte immer der erste 
Schritt sein, die (ignorierten) Warnungen mindestens einmal 
durchzugehen, bevor man Vodoo versucht.

von W.S. (Gast)


Lesenswert?

Jana schrieb:
> Hier mein ursprünglicher Code funktioniert nicht (interessanterweise
> werden die ersten beiden Zeichen immer richtig übertragen):

Irgedwie habe ich immer den Eindruck, daß HAL und Konsorten keine andere 
Funktion haben, als deren Anwendern das Leben möglichst schwer zu 
machen.

Bei mir würde das Ganze etwa so aussehen:
1
void COM_SendNFI (void)
2
{ String_Out(toUART1, "NFI(X0001)\n"); }

Aber ich benutze ja auch mein eigenes Zeugs und nicht sowas wie die HAL.
Mein Rat wäre, sich die HAL zu verkneifen und stattdessen sich seine 
eigene Sammlung an Lowlevel-Treibern zu schreiben. OK, das macht am 
blutigen Anfang etwas mehr Arbeit, aber dann zahlt es sich aus. Nebenbei 
gesagt: ein kleines Beispiel-Projekt zu so etwas hatte ich vor Jahren 
hier schonmal gepostet.

W.S.

von Cyblord -. (cyblord)


Lesenswert?

W.S. schrieb:
> Irgedwie habe ich immer den Eindruck, daß HAL und Konsorten keine andere
> Funktion haben, als deren Anwendern das Leben möglichst schwer zu
> machen.

Das ist leider wirklich so. Ich habe immer gerne mit der StdPerihpLib 
auf STM32 gearbeitet. Das waren recht klare Funktionen und Definitionen. 
Man wusste was da passiert.
Jede Funktionalität aus dem Datenblatt war mehr oder weniger 1:1 dort 
abgebildet.

Bei HAL weiß man das nicht.
z.B. HAL_TIM_Base_Start() vs. HAL_TIM_Base_Start_IT().

Da wird der Timer gestartet. Mit und ohne Interrupt. Welcher Interrupt? 
Tja. Erschließt sich nicht direkt. Muss man nachgucken. Es ist der 
Update Interrupt. Für die HAL bedeutet das "Den Timer im Interrupt Modus 
starten". Das ist eine völlig willkürliche Festlegung.

Es gibt im DB keine Funktion "Timer Start" oder "Timer Start mit 
Interrupt". Diese Funktionalität erfindet die HAL. Und da fangen die 
Probleme an. Die HAL abstrahiert mir deutlich zu weit. Bis hin zum 
Ratespiel was da passiert.

Bei diesem Beispiel hier: HAL_UART_Transmit_IT

Da passiert jede Menge. Dieser Aufruf benötigt im Hintergrund das ganze 
HAL Zeug zum Interrupt Handling. Dann kann die HAL Daten selbständig bei 
jedem Interrupt senden. So läuft das Senden im Hintergrund. Die HAL 
puffert die Daten, zählt, horcht auf den Interrupt, setzt irgendwelche 
UART States. Das ist zu heftig.

Bei der StdPeriphLib haben solche Aufrufe ein Byte in den TDR Register 
geschoben und das wars.


Leider gibt es die StdPeriphLib nicht mehr für viele neuere STM32. Also 
bleibt nur HAL oder selber Registerbits setzen rein mit CMSIS.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Cyblord -. schrieb:
> Die HAL abstrahiert mir deutlich zu weit. Bis hin zum
> Ratespiel was da passiert.

Naja, ich verstehe, was du meinst. Allerdings ist das, was diese HAL 
tut, aus meiner Sicht keine Abstraktion, sondern eher Herumgelaber. Bei 
meinem Beispiel weiter oben wird abstrahiert: ob man nun toUART1 oder 
toUSB oder toSTRING, toFILE usw. angibt, und ob dieser Aufruf nun auf 
einem ARM oder einem 8051 oder sonstwo stattfindet, ist egal. Ich sehe 
das so, daß sich die Ebene der Algorithmen in einer Firmware nicht mit 
den Befindlichkeiten irgendwelcher Standard-Peripherie herumschlagen 
muß. Da ist ein Kanal zur Zeichenausgabe so gut wie jeder andere.

Nebenbei zum vom TO geäußerten Mysterium: Wer das Manual lesen kann (und 
tut), ist da im Vorteil: der in den meisten Peripheriecores dem 
eigentlichen Ausgaberegister vorgeschaltete Speicher macht es möglich. 
Das allererste Zeichen wird sofort in das Ausgaberegister durchgereicht, 
wo es Bit für Bit herausgeschoben wird. Das zweite Zeichen landet in dem 
vorgeschalteten Vorrats-Register, von dem aus es erst nach dem Senden 
des ersten Zeichens ins eigentliche Ausgaberegister transportiert wird. 
Und da die Ausgaberoutine offenbar solange ausgibt, wie der 
Peripherie-Core kein 'Bin voll' meldet, werden von dem ursprünglichen 
Thread genau die beiden ersten Zeichen korrekt gesendet, nicht jedoch 
die wohl auf dem Stack befindlich gewesenen weiteren Zeichen, denn die 
sind inzwischen von dem Zeugs anderer inzwischen aufgerufenen Funktionen 
überschrieben worden.

W.S.

von Cyblord -. (cyblord)


Lesenswert?

W.S. schrieb:
> Naja, ich verstehe, was du meinst. Allerdings ist das, was diese HAL
> tut, aus meiner Sicht keine Abstraktion, sondern eher Herumgelaber.

Die Benamung von Funktionen ist das Eine.
Dazu kommt dann noch der lustige Mix aus Funktionen und Makros. Warum 
werden alle RCC Clocks und einzelne Interrupts mit Makros eingeschaltet, 
statt auch mit Funktionen?

Aber damit hört es bei HAL ja nicht auf. HAL bringt ja richtig Code mit 
um genau solche Sachen wie Interrupt-Gesteuertes Senden oder DMA selbst 
abzukaspern. Beim UART kümmert sich dieser Code auch um den FIFO, der 
ein paar Byte lang sein kann, wenn man will.

Damit kann man super Demos machen um zu zeigen wie schnell und einfach 
man Dinge erledigen kann. Bei echten Aufgaben stört das allerdings, weil 
es, innerhalb von HAL, auch keine Alternative gibt.

von Johannes S. (Gast)


Lesenswert?

haben sich Statler und Waldorf wieder gefunden?

von Alex -. (alex796)


Lesenswert?

Cyblord -. schrieb:
> Also bleibt nur HAL oder selber Registerbits setzen rein mit CMSIS.

Hi,

Ich selbst habe mich nie richtig mit HAL beschäftigt, weil es für mich 
immer in ein Ratespiel geendet hat. Deshalb CMSIS.

Aber, rein aus Interesse:
Hast du dich mal mit den LL Bibliotheken von ST beschäftigt? Wie stehst 
du dazu, im Vergleich zu der ursprünglichen StdPeriphLib?

Gruß,

von Cyblord -. (cyblord)


Lesenswert?

Alex -. schrieb:
> Aber, rein aus Interesse:
> Hast du dich mal mit den LL Bibliotheken von ST beschäftigt?

Tatsächlich nicht.
Werde ich aber tun.

von Harry L. (mysth)


Lesenswert?

Kleiner Tip:

Die HAL-Doku wird ständig gepflegt, und es gibt zieml. regelmäßig neue, 
überarbeitete Versionen.

Am Anfang war ja die Doku der grösste Kritikpunkt - nicht zu unrecht!

Inzwischen haben die aber nen guten Job gemacht, und mit der aktuellen 
Version der Doku kann man arbeiten.

Also immer mal wieder bei ST vorbeischauen, und die aktuelle Version 
herunterladen!

Gemeint sind diese Docs - Bsp. für STM32F1xx:
https://www.st.com/resource/en/user_manual/dm00154093-description-of-stm32f1-hal-and-lowlayer-drivers-stmicroelectronics.pdf

just my2cent

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Man sollte auf Controllern auch nicht Null-terminierte C-Strings 
verwenden, sondern besser Pascal Strings, welche die Laenge zuerst 
haben. Die haben ausschliesslich Vorteile.

von c-hater (Gast)


Lesenswert?

Pandur S. schrieb:

> Man sollte auf Controllern auch nicht Null-terminierte C-Strings
> verwenden, sondern besser Pascal Strings, welche die Laenge zuerst
> haben. Die haben ausschliesslich Vorteile.

Nein, natürlich nicht. Sie haben den Nachteil einer "unnatürliche" 
Grenze für die maximale Länge. Nullterminierte Strings sind hingegen in 
der maximalen Länge nur durch die natürliche Grenze des verfügbaren 
Speichers begrenzt.

Ganz allgemein kann man übrigens immer davon ausgehen, dass, wenn es 
irgendwelche Varianten der Implementierung irgendeiner Sache gibt, keine 
dieser Varianten frei von irgendwelchen Nachteilen ist.

Weil: Wäre es anders, gäbe es keine Varianten. Jedenfalls nicht auf 
lange Sicht, da würde sich immer die durchsetzen, die tatsächlich 
keine objektiven Nachteile hat.

von W.S. (Gast)


Lesenswert?

c-hater schrieb:
> Nein, natürlich nicht. Sie haben den Nachteil einer "unnatürliche"
> Grenze für die maximale Länge.

Wie lange Strings willst du denn auf deinem µC machen?

Also gerade auf einem µC ist deutlich weniger Platz als am PC. Das führt 
also nicht zum Vorteil der nullterminierten Zeichenketten. Der 
eigentliche Knackpunkt ist, daß gerade für µC am häufigsten C zum 
Programmieren benutzt wird und daß C keine Strings (mit Längenangabe) 
kennt. Da sind Behauptungen und Gegenbehauptungen ein bissel 
gegenstandslos. Ich sag's mal so: Wir haben hier in Berlin zwar keine 
Gebirge, aber wenn wir hier welche hätten, dann wären sie viel höher als 
die Alpen. So. Nur als Verdeutlichung der Gegenstandslosigkeit.

W.S.

von c-hater (Gast)


Lesenswert?

W.S. schrieb:

> Wie lange Strings willst du denn auf deinem µC machen?

Auf jeden Fall kommen auch auf relativ kleinen µC recht häufig Strings 
vor, die länger als 255 Zeichen sind.

von Bauform B. (bauformb)


Lesenswert?

Harry L. schrieb:
> Die HAL-Doku wird ständig gepflegt, und es gibt zieml. regelmäßig neue,
> überarbeitete Versionen.

Toll. Gestern lief mein Programm doch noch? Was ist jetzt wieder anders?

> Also immer mal wieder bei ST vorbeischauen, und die aktuelle Version
> herunterladen!

Beschäftigungstherapie für Rentner? Warum sollte ich mir das antun?
Egal, wie gut oder schlecht die Doku ist, ich müsste das alles erstmal 
lesen, zusätzlich zum Reference Manual. Wo ist da der Vorteil?

W.S. schrieb:
> Bei mir würde das Ganze etwa so aussehen:void COM_SendNFI (void)
> { String_Out(toUART1, "NFI(X0001)\n"); }

warum nicht gleich so, dann braucht man garkeine extra Doku?
1
void COM_SendNFI (void)
2
{ printf ("NFI(X0001)\n"); }
3
// oder
4
{ fprintf (uart1, "NFI(X0001)\n"); }

von Johannes S. (Gast)


Lesenswert?

haha, W.S. und printf...

der Wrapper um die HAL Funktion war doch schon im Eröffnungspost ok, 
wenn der Buffer den man ausgeben möchte zu klein ist, bekommt man in 
jeder Variante Probleme.

von Kevin M. (arduinolover)


Lesenswert?

Ich weiß echt nicht was ihr alle gegen die HAL Funktionen habt, die sind 
recht eindeutig und verständlich. Klar hat sie einen gewissen Overhead, 
aber verständlich sind die allemal, wenn man mal Nachdenkt, statt 
einfach zu sagen nein ich mach das seit 30 Jahren anders und deshalb ist 
alles neue und andere Böse. Dann kommt man ohne viel gelese drauf was 
die Funktionen tun, allein über die Funktionsbeschreibung im Code 
selbst. Wegen Leuten wie euch gibt es hier zu wenige schnelles Internet, 
da kommt der Anbieter und macht eine Umfrage um auszubauen und alle 
älteren Menschen meine nein dieses Neuland brauchen wir nicht.

Selbst low level Funktionen zu schreiben ist ja gut und schön, wenn man 
aber z.B. viele verschiedene µC hat wird das sehr schnell aufwendig. 
Allein für die Initialisierung ist die HAL schon gut ob man die 
Peripherie nachher mit HAL oder anders anspricht, kann man dann immer 
noch entscheiden.

von Alex -. (alex796)


Lesenswert?

Kevin M. schrieb:
> die sind recht eindeutig und verständlich.

Du könntest ja mal das genannte Beispiel von Cyblord anwenden und 
zeigen, wir man anhand der Beschreibung von HAL Funktionsnamen aus dem 
Unklaren herauskommt.

Beitrag "Re: STM32 HAL UART Mysterium oder bin ich dumm?"

Gruß,

von Kevin M. (arduinolover)


Lesenswert?

Alex -. schrieb:
> Du könntest ja mal das genannte Beispiel von Cyblord anwenden und
> zeigen, wir man anhand der Beschreibung von HAL Funktionsnamen aus dem
> Unklaren herauskommt.

Du meinst den Timer?

Das eine startet einfach den Timer und das andere eben noch den 
entsprechenden Interrupt zum Timer. Welche Interrupts dieser unterstützt 
muss man natürlich nachschaun, das ist aber immer so egal HAL oder 
nicht. Idr. ist es aber der Update Interrupt, auch wenn Timer wie 1 und 
8 noch weitere haben.

von W.S. (Gast)


Lesenswert?

Kevin M. schrieb:
> Ich weiß echt nicht was ihr alle gegen die HAL Funktionen habt, die sind
> recht eindeutig und verständlich.

Die Funktionalität der HAL von ST ist keine HardwareAbstraktion. Bei all 
diesem Zeug ist drauf geachtet worde, daß die Schnittstellen 'nach oben' 
nicht plattformneutral sind, sondern möglichst fest an den Hersteller ST 
gebunden sind. Das ist keine Abstraktion, sondern eine Art 
Kundenbindung. Abgesehen davon sehe ich, daß alle hier in diesem Forum 
gezeigten Beispiele imer wieder einen Code-Aufwand in main.c nach sich 
ziehen, der den geneigten Prohgrammierer wirklich nicht entlastet, 
sondern ihm zusätzlichen Streß macht.

Das ist es, was ich gegen die HAL von ST habe.

Wenn du hingegen nur bei den Produkten von ST bleiben willst und in 
jedem Projekt all das schreiben willst, was man braucht, um die 
Standard-Sachen mit der HAL zu tun, dann ist das alles für dich 
natürlich nicht wichtig.

W.S.

von c-hater (Gast)


Lesenswert?

W.S. schrieb:

> Die Funktionalität der HAL von ST ist keine HardwareAbstraktion. Bei all
> diesem Zeug ist drauf geachtet worde, daß die Schnittstellen 'nach oben'
> nicht plattformneutral sind, sondern möglichst fest an den Hersteller ST
> gebunden sind.

Genau so ist das.

von Johannes S. (Gast)


Lesenswert?

W.S. schrieb:
> sondern möglichst fest an den Hersteller ST
> gebunden sind

und warum sollte ST das anders machen? Code für NXP schreiben?

Für Plattformunabhängigkeit gibt es genügend andere OS, aber auch da 
sind ST mit ihrem Support weit vorne um ihre Controlle zu pushen. Es 
reicht heute nicht mehr nur ein Stück Silicon und Papier dazu zu 
verkaufen.

von Kevin M. (arduinolover)


Lesenswert?

Johannes S. schrieb:
> und warum sollte ST das anders machen?

Sehe ich auch so, das ganze drumherum ist mit ein Grund warum ich zu ST 
gewechselt bin.

ST bietet dahingehend einfach einen Mehrwert in verschiedenen Dingen. 
Man kann von der Cube Umgebung halten was man will, aber CubeMX ist ein 
sehr mächtiges Tool allein um einen passenden µC auszuwählen und die 
Belegung im Schaltplan zu machen, ohne dass man Seitenweise Datenblätter 
lesen muss. Natürlich ersetzt es nicht das Lesen von Reference Manuals 
oder Datenblättern, aber es ist eine große Unterstützung.

von Stefan F. (Gast)


Lesenswert?

Bauform B. schrieb:
> ich müsste das alles erstmal
> lesen, zusätzlich zum Reference Manual. Wo ist da der Vorteil?

Das habe ich auch gefragt, und bekam eine plausible Antwort: Die HAL 
hilft dir dabei, Programmteile zu schreiben, die auf mehreren STM32 
Modellen laufen können.

Für meine wenigen Hobby-Projekte reicht das nicht als Rechtfertigung mir 
die HAL anzutun.

von Kevin M. (arduinolover)


Lesenswert?

Stefan ⛄ F. schrieb:
> Für meine wenigen Hobby-Projekte reicht das nicht als Rechtfertigung mir
> die HAL anzutun.

Aktuell muss ich in verschiedenen Projekten mit 8 verschiedenen uC 
Modellen arbeiten die sich teilweise Funktionalität teilen. Wenn ich da 
für jeden Controller nochmal auf Register Ebene anfangen muss die LL 
Treiber zu schreiben hätte ich viel zu tun.

von The A. (the_a343)


Angehängte Dateien:

Lesenswert?

Hallo, ich wollt euch mal meinen Code zeigen.

Der basiert auf der HAL von STM und benutzt optional einen Ringbuffer 
beim Senden.
Der Empfang ist mittels DMA und verpflichtenden Ringbuffer 
implementiert.

Ich finde es sinnvoll die Hersteller-API zu benutzen in der Hoffnung, 
dass damit alle "Tricks" der Hardware angegangen werden.
Die Konfiguration erfolgt mittels CubeMX.

beispielsweise sieht das dann so aus:
1
UART_HandleTypeDef huart2;
2
uint8_t rx2_buffer[100];
3
uint8_t tx2_buffer[100];
4
serial_ctx_t serial2;
5
6
int main(void)
7
{
8
    ...
9
    MX_DMA_Init();
10
    MX_USART2_UART_Init();
11
12
    ...
13
    uint8_t tx_buffer[100];
14
15
    serial_init(&serial2, &huart2, rx2_buffer, sizeof(rx2_buffer), tx2_buffer, sizeof(tx2_buffer));
16
    while(1) {
17
        ...
18
        // senden
19
        sprintf((char *)tx_buffer, "hallo.");
20
        serial_write_buf(&serial2, tx_buffer, strlen((char *)tx_buffer));
21
        //empfangen
22
        if(serial_status(&serial3, false) != false) {
23
            uint8_t c;
24
            while(serial_read(&serial3, &c) != 0) {
25
                ...
26
            }
27
        }
28
    }
29
}
HTH, Adib.

: Bearbeitet durch Moderator
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.