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.
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.
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?
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?
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.
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.
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
volatileuint8_tIstWasPassiert=0;
2
3
charrxString[100];
4
uint8_trxCount;
5
6
7
intmain(){
8
9
uint8_tbyte;
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
voidHAL_UART_RxCpltCallback(uint8_tbyte)
25
{
26
// jedes zeichen was emfangen wird landet hier nacheinander drin !!!