Hallo guten Tag,
warum wird mein UART-Interrupt zwei mal ausgelöst wenn ich etwas
eintippe und Enter drücke? Der Buffer hat dann einmal den ersten
Buchstaben und einmal den Rest.
Mein Programm soll bei scanfx in eine while(1) Schleife gehen bis eine
Eingabe erfolgt und ein Empfang-Flag auf 1 setzt.
1
cmd0
2
cmd1
3
scanfx->while(1)<--EingabedurchInterrupt
4
nutzedaseingelesene
5
cmd2
6
cmdn
7
scanfx->while(1)<--EingabedurchInterrupt
Was mir aufgefallen ist:
Wenn ich in der while-Schleife bin, etwas eintippte und enter drücke
wird meine Interrupt Funktion 2 mal hintereinander aufgerufen..
Wenn ich eingebe: "test"
wird zuerst das "t" als Eingabe verwendet.
direkt danach scheint die Funtkion nochmal "est" zu erhalten.
Das sehe ich auch an der Ausgabe von "est" und "t"...
hier setze ich den handler:
normalerweise müsste jedes Zeichen einen Int auslösen welcher dann in
den Buffer geschrieben wird, scheint ja auch zu funktionieren nur das
wohl bei SCANFX als Routine evtl was schiefläuft aber was genau wird
schwierig...
Aber wenn ich dann "test" eingebe,
dann wird direkt das "t" erkannt und der Interrupt ausgelöst?
Wird dabei "est" reingeschrieben und dann ebenfalls ein weiterer
interrupt auslöst?
Will ja nur dass er test komplett einliest.
liegt das "MSS_UART_FIFO_SINGLE_BYTE" ?
Dass der da schon interrupted?
scanfx soll nur eine Ersatz sein für while(1)
So sieht die etwa aus:
1
intflag=0;// global
2
3
boolscanfx(){
4
5
while(1){
6
7
if(flag==1){
8
returntrue}
9
else{}
10
}
11
}
DerEinzigeBernd schrieb:> Du rufst printf IM Interrupt-Handler auf.
Warum? weil diese Funktion viel Zeit kostet?
Ist das ok für einen ersten Debug?
Ein paar weitere Salamiescheiben werden hilfreich.
Was für einen Microcontroller benutzt du, was für eine API ist das
MSS_*...
Wo tippst du eine? Auf dem PC mittels Terminal.
Läuft das dann über ein USB-UART-Adapter?
Schickt deine Terminal-Anwendung den Text Zeichenweise raus, oder erst
wenn Enter gedrückt wird? Aus deiner Beobachtung vermute ich letzteres.
Des weiteren gehe ich davon aus das du einen USB-UART Adapter benutzt.
USB ist paketorientiert und hat auf PC Seite einen Input Buffer.
Deine Terminal Anwendung schickt den gesamten String in einem Rutsch in
den USB-Input Buffer. Sobald da das erste Zeichen rein kommt, wird
bereits das erste USB-Packet abgesendet, und der Adapter schickt das
erste Zeichen aus. [Dein erster Interrupt auf deinem Microkontroller]
Die Restlichen Zeichen liegen im USB-Input Buffer, und werden im
nächsten USB-Packet an den Adapter gesendet. der dann die Zeichen ohne
weitere Pause per UART aussendet. [2. Interrupt, bis du den Buffer
ausliest, sind bereits die restlichen Zeichen angekommen]
USB-Pakete haben ein Timing von 1ms. Da kannst du nichts ändern.
chris schrieb:> normalerweise müsste jedes Zeichen einen Int auslösen welcher dann in> den Buffer geschrieben wird,
Wahrscheinlich sind nach der 1. IRQ-Behandlung alle restlichen Zeichen
schon eingegangen und zum Glück gepuffert worden. Folge der viel zu
langsamen printf Aufrufe.
In der Tat. Komplett übersehen und deshalb wird immer der IRQ gesetzt
weil das nächste Byte ansteht wird zwar zwischen gespeichert aber da die
Ausgabe im ertsen Moment recht lang ist wird erst nur das T ausgegeben
und zwischen durch wird der Rest dann beim zweiten durchlauf im Buffer
abgelegt und als EST ausgegeben.
Bergsfrau schrieb:> DerEinzigeBernd schrieb:>> Du rufst printf IM Interrupt-Handler auf.>> Warum? weil diese Funktion viel Zeit kostet?
Sieh mal, wie viele einzelne Zeichen Du hier für jeden einzelnen
Interrupt-Aufruf ausgibst:
> printf("\n------------------------- [UART RX HANDLER]");> uart_calls_cnt++;> printf("\n-call cnt: %d", uart_calls_cnt);> printf("\n * Size RX char: %d", rx_size);> printf("\n *Your input: ");> printf(" [I]%s[/I]", (char *)g_rx_buff);
Selbst wenn diese printf()-Aufrufe nicht blockieren (d.h. erst
zurückkehren, bis sie alles ausgegeben haben), dauert die ISR ziemlich
lange. Es kann also sein, daß beim Einlaufen des nächsten Zeichens bei
der UART die ISR noch nicht beendet ist, und direkt der nächste
Interrupt ausgelöst wird.
Und wenn die Aufrufe blockieren (weil Deine Umgebung keinen
interruptgesteuerten Ausgabehandler mit ausreichend großem Sendepuffer
hat), dann geht richtig viel Zeit in der ISR drauf; sofern die
UART-Hardware nicht mehrere empfangene Bytes puffern kann, gehen diese
unweigerlich verloren.
Also: Nein, das ist auch für "ein erstes Debug" eine ganz schlechte
Idee.
das hat mir schon mal weiter geholfen.
Ich konnte jetzt schon die ersten Eingaben machen die funktionieren wenn
sie verglichen werden.
Ist noch ein bisschen holprig mit den Interrupts aber werde mir das noch
mal genauer anschauen :D
Lothar M. schrieb:> Naja, ein wenig musst du schon noch selber machen. Das nennt sich> programmieren. Du musst den Strin einlesen, bis du (d)ein> Terminierungszeichen erkennst (z.B. CR/LF), und kannst dann den> empfangenen String parsen.
Ok, also wenn ein Interrupt geschieht werde ich mal alle vorhandenen
Zeichen einlesen.
Die Anzahl der einzulesenden Zeichen werde ich aus dem Rückgabewert von
MSS_UART_get_rx nehmen.
Bei jedem Element was ich reinschreibe werde ich vergleichen ob '\n'
vorhanden ist.
Wenn ja ist das das Ende des Strings und ich kann ihn verwenden.
Wenn ein Interrupt kommt stehen die Daten ab Index 0 im Buffer.
Ich muss diese dann an die bereits ausgelesenen Daten anhängen.
Dafür muss die vorherige Position bekannt sein.
1
for(inti=0;i<(int)rx_size;i++){
2
command[index]<=g_rx_buff[i]
3
}
4
index+=(int)rx_size;
Udo S. schrieb:> Wahrscheinlich sind nach der 1. IRQ-Behandlung alle restlichen Zeichen> schon eingegangen und zum Glück gepuffert worden. Folge der viel zu> langsamen printf Aufrufe.
Wenn ich printf weglasse geschieht das gleiche.
Wenn ich einen Breakpoint in die ISR setze ist einmal 't' drin und
einmal 'e' 's' 't' '\n'