Servus zusammen, ich versuche gerade auf meinem Nucleo F767ZI Daten über die HAL_UART_Receive_IT() Funktion zu empfangen. Leider kommt im Speicher nur das erste Bit an welches versende. Hier der Quellcode: In der main.c: uint8_t a = 0; char docklight[10]; int main(void){ while(1){ HAL_UART_Receive_IT(&huart3,&docklight,strlen(docklight)); if(a == 1){ a = 0; ptr = strtok(docklight,","); while(ptr != NULL){ HAL_UART_Transmit(&huart3,(uint8_t*)ptr,strlen(ptr),10); ptr = strtok(NULL,","); } } } } In der stm32f7xx_it.c: extern a; void USART3_IRQHandler(void) { a = 1; HAL_UART_IRQHandler(&huart3); } Die Variable a soll nur den Transmit Code aus der main auslösen. Ich wollte den Interrupt so kurz wie möglich halten, die Daten werden in der main später noch weiterverarbeitet. Wenn ich mit dem Debugger durchgehe wird nur das erste Zeichen meines gesendeten Strings gespeichert obwohl ich mehrere versende. Wenn ich das Programm ohne Breakpoints ausführe, sendet er mir den gesamten String zurück was ich ja möchte. Ich hab keine Ahnung warum er das im Debug Modus nicht macht. Ich kann so den String nicht weiterverarbeiten weil er immer nur das erste Zeichen des gesendeten Strings speichert. Ich verwende zum Senden und zum Anzeigen der Daten Docklight.
Marco D. schrieb: > Wenn ich mit dem Debugger durchgehe wird nur das erste Zeichen meines > gesendeten Strings gespeichert obwohl ich mehrere versende. Wenn der STM direkt beim ersten Zeichen, das er empfängt anhält, dann kann der Interrupt auf alle weiteren Zeichen nicht mehr reagieren. Dein PC sendet ja den restlichen String, auch wenn der STM sich im Breakpoint befindet. Gruß, Stefan
In der _*_it.c brauchst du nichts zu ändern. Füge im die main.c die Funktion HAL_UART_RxCpltCallback ein. In dieser kommt jedes Zeichen einzeln an und du kannst auf Zeilenende auswerten oder einen Puffer mit einer Anzahl Zeichen füllen.
Inwiefern muss die Callback Funktion in der main eingebaut werden ? Ich werde aus der Funktion nicht wirklich schlau.
Marco D. schrieb: > Inwiefern muss die Callback Funktion in der main eingebaut werden ? Ich > werde aus der Funktion nicht wirklich schlau. In welcher Datei du diese Funktion implementierst ist letztendlich egal. Entscheidend ist, daß der Linker die findet. Es gibt im HAL bereits eine leere Funktion mit diesem Namen, die als "weak" deklariert ist, und die überschreibst du so.
Die Funktion macht scheinbar nicht wirklich was. Ich weiß daher nicht was ich mit genau dieser soll wenn ich sie sowiso überschreiben soll.
Marco D. schrieb: > Die Funktion macht scheinbar nicht wirklich was. Ich weiß daher > nicht > was ich mit genau dieser soll wenn ich sie sowiso überschreiben soll. Die Funktion wird aus der Interrupt-Routine heraus aufgerufen und bekommt das Handle der Schnittstelle übergeben. So kommst du an die empfangenen Daten. Weiter verarbeiten mußt du diese Daten natürlich selber.
Kann es sein das es eher an Docklight liegt und ich, wenn ich eine Sequenz sende nur einzelne chars mit entsprechendem Nullterminator nach jedem Zeichen versende ?
Marco D. schrieb: > Kann es sein das es eher an Docklight liegt und ich, wenn ich eine > Sequenz sende nur einzelne chars mit entsprechendem Nullterminator nach > jedem Zeichen versende ? Nein! Wenn du die Interrupt-gestützten Funktionen nutzen willst, brauchst du zwingend die zugehörige Callback-Funktion. Woher willst du sonst wissen, daß etwas empfangen wurde?
1 | char docklight[10]; |
2 | |
3 | int main(void){ |
4 | while(1){ |
5 | HAL_UART_Receive_IT(&huart3,&docklight,strlen(docklight)); |
strlen gibt 0 zurueck, da dein Array global ist und damit automatisch mit 0 initialisiert wird. Waere das Array nicht global (und nicht initialisiert), wuerde strlen zaehlen, bis im Speicher irgendwann mal eine 0 steht. Willst du das? Oder wolltest du eher sizeof nehmen?
1 | #include <iostream> |
2 | #include <string.h> |
3 | |
4 | using namespace std; |
5 | |
6 | char docklight[10]; |
7 | |
8 | int main(void) |
9 | {
|
10 | cout << "strlen is: " << strlen(docklight) << endl; |
11 | cout << "sizeof is: " << sizeof(docklight) << endl; |
12 | |
13 | return 0; |
14 | |
15 | }
|
1 | $ c++ -Wall -Wextra -o main main.cpp && ./main |
2 | strlen is: 0 |
3 | sizeof is: 10 |
Wenn ich die Funktion HAL_UART_RxCpltCallback(...) in der main aufrufe wird doch nicht die ISR dadurch aufgerufen. Ich blicke überhaupt nicht mehr durch. Mit Handle meinst du das &huart3 welches ich übergebe ? wie soll ich daraus die empfangenen Daten herausbekommen ? Ich müsste ja auf die Variable docklight zugreifen können um mit den Daten was anzufangen was ich aber nicht kann.
Marco D. schrieb: > Wenn ich die Funktion HAL_UART_RxCpltCallback(...) in der main aufrufe > wird doch nicht die ISR dadurch aufgerufen. Ich blicke überhaupt nicht > mehr durch. Mit Handle meinst du das &huart3 welches ich übergebe ? wie > soll ich daraus die empfangenen Daten herausbekommen ? Ich müsste ja auf > die Variable docklight zugreifen können um mit den Daten was anzufangen > was ich aber nicht kann. Du rufst die Callback-Funktion NIEMALS selber auf! Die wird aufgerufen, sobald 1 Zeichen über die UART empfangen wird. Und Ja! huartx ist das Handle. Die erste Aktion in dem Callback ist es, zu überprüfen ob das Handle zu deiner gewünschten UART gehört.
Also ich hab jetzt nochmal nachgeschaut wie die Interrupt Funktion arbeitet. Schein, was ich nicht wusste, wird die Callback Funktion aufgerufen, nachdem der Buffer für die empfangenen Dateien leer ist. Also muss ich doch nicht die Callback Funktion in der main aufrufen sondern sie da nur überschreiben oder ? Mich stört nur das in stm32f7xx_hal_uart.c darauf hingewiesen wird, dass HAL_UART_RxCpltCallback möglichst nicht verändert werden sollte.
Marco D. schrieb: > Mich stört nur das in > stm32f7xx_hal_uart.c darauf hingewiesen wird, dass > HAL_UART_RxCpltCallback möglichst nicht verändert werden sollte. Natürlich nicht! Du sollst ja auch deine eigene Funktion schreiben.
Wie albern ist das denn ! Ich will nur ganz simpel einen String einlesen und muss dafür eine eigene Funktion schrieben ?!
Du willst Interrupts nutzen und dazu gehört nun mal eine Callback-Funktion. Offenbar fehlen dir sämtliche grundlagen dazu. Fang erstmal ohne Interrupt an und nutz HAL_UART_Receive()! (ohne _IT) Dann musst du allerdings warten bis ein Zeichen empfangen wurde.
Ich möchte einfach nur einen String empfangen und, wenn dieser dann eingelesen wurde, mit diesem String weiterarbeiten. Es kann doch nicht sein, dass das so kompliziert ist. Die Interrupt Funktion habe ich nur verwendet weil ich nicht wusste wie ich sonst dafür sorge, dass nach einmaligem senden der Daten im main programm der empfangene String weiterverarbeitet werden kann. Es geht auch sicherlich dann noch einfach ohne, nur weiß ich nicht wie. Ich wäre für jeden Hinweis sehr dankbar. Es kann mir aber doch niemand erzählen das ich für so einen Generalfall eine eigene Funktion schreiben muss !
Es war auch mein Plan jetzt nur die reguläre FUnktion ohne Interrupt zu verwenden. Nur hab ich da keine Ahnung wie ich in der while(1)-Schleife dafür sorge, dass nur einmal etwas versendet wird. Packe ich da die Transmit-Funktion in die Callback-Funktion ? Da wiederum kann ich aber nicht auf meinen empfangenen String zugreifen weshalb das nicht geht.
Fang mal hiermit an! Sonst wird das nix.... STM32Cube basics MOOC with hands-on exercises: https://www.youtube.com/playlist?list=PLnMKNibPkDnGtuIl5v0CvC81Am7SKpj02 Moving from 8 to 32 bits workshop - first steps in STM32: https://www.youtube.com/playlist?list=PLnMKNibPkDnHXgWV0h36LQDGrEuT2r5I4 Danach gehts dann hier weiter: https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs.html
Also ich hab jetzt den Code auf folgendes reduziert: int main(void){ char daten[10] = "Hallo\n"; while(1){ HAL_UART_Receive(&huart3,(uint8_t*)daten,strlen(daten),100); HAL_UART_Transmit(&huart3,(uint8_t*)daten,strlen(daten),100); HAL_Delay(500); } Ich bekomme auch mit dem "normalen" Receive nur 1 Bit geladen. D.h. wenn ich etwas einlese, dann ändert sich nur das 1. Bit. Ich benutze nur default settings und hab ein komplett neues Projekt erstellt. Ich habe einzig die Baudrate vom Uart3 auf 9600 gestellt damit ich etwas über meinen USB Port versenden kann. Habe auch schon etliche Tutorials gesehn und die machens auch nicht anders.
Also ich brauche für meinen Zweck definitiv die Interrupt Funktion. Ich bekomme es mittlerweile hin Daten mit festgelegter Größe zu empfangen. Ich habe aber keine Ahnung wie ich eine Routine schreibe, die mir Daten variabler Länge einliest. Ich habe am Schluss der Nachricht einen Nullterminator womit ich es schaffen sollte variable Längen einzulesen. Hat jemand einen Tipp für mich wie ich da vorgehe ?
Ich müsste meiner Meinung nach irgendwie auf den Pointer, der auf das eingelesene Zeichen zeigt zugreifen und abfragen ob dieser == "NULL" ist. Sehe ich das richtig ?
Ich habe eine Variante die Text von der seriellen Schnittstelle einliest und nach Eingabe von New Line (0x0a) den gleichen Text in Grossbuchstaben gewandelt wieder zurück sendet. Interesse?
eine callback ist eine "rückruf-funktion " .. sie wird irgendwo anders aufgerufen ... frei nach dem motto: wenn was passiert sag mir bescheid!!! bescheidgesagt wird hier über diese funktion ... wenn du also deine :
1 | volatile uint8_t IstWasPassiert = 0; |
2 | |
3 | char rxString[100]; |
4 | uint8_t rxCount; |
5 | |
6 | |
7 | int main(){ |
8 | |
9 | uint8_t byte ; |
10 | HAL_UART_Receive_IT(&huart3, &byte , 1 ); |
11 | |
12 | while(1) |
13 | {
|
14 | if( IstWasPassiert == 1 ) |
15 | {
|
16 | IstWasPassiert = 0; |
17 | printf( rxString ); |
18 | }
|
19 | }
|
20 | }
|
21 | |
22 | |
23 | |
24 | void HAL_UART_RxCpltCallback( uint8_t byte ) |
25 | {
|
26 | // jedes zeichen was emfangen wird landet hier nacheinander drin !!!
|
27 | rxSring[rxCount] = byte; |
28 | rxCount++; |
29 | |
30 | if( byte == '\n' ) |
31 | {
|
32 | rxCount = 0; |
33 | IstWasPassiert = 1; |
34 | }
|
35 | |
36 | if( rxCount > 100 ) |
37 | rxCount = 0; |
38 | |
39 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.