möchte mit dem USART auf ein bestimmtes Zeichen warten, bespielsweise auf '#' kann man das so machen oder habt ihr bessere vorschläge: while(USART_Receive()!='#'); //verweile in dieser Schlaufe bis # ankommt USART_Receive liefert das empfange char zurück
Hari wrote:
> kann man das so machen oder habt ihr bessere vorschläge:
Das kommt drauf an, ob der4 µC in der Zwischenzeit noch
andere Aufgaben zu erledigen hat.
Meistens vermeidet man solche Warteschleifen, wie der Teufel
das Weihwasser. Üblicherweise ist der µC Code ja in eine
Hauptschleife eingebunden.
while( 1 ) {
... Programmlogik
}
Wenn jetzt etwas passieren soll, wenn ein # empfangen wird,
dann schreibt man das auch genau so
while( 1 ) {
...
id( USART_Receive() == '#' ) {
... mach was wenn # empfangen wird
}
}
Aus dem gleichen Grund ist es auch oft nicht ratsam, die
USART_Receive Funktion als wartende Funktion auszuführen.
Die USART_Receive sollte auch in dem Fall in dem kein
Zeichen empfangen wurde sofort zurückkehren und diesen
Umstand (kein Zeichen empfangen) durch einen Returncode
mitteilen.
Wenn es darum geht, dass von der Gegenstelle eine Empfangssequenz
kommt, in der das # irgendetwas kannzeichnet, dann ist es meist
besser, zb mittels einer Interrupt Steuerung das komplette
Kommando zu empfangen (als String) und erst dann, wenn die
komplette Befehlssequenz empfangen wurde, mit der Auswertung
zu beginnen.
ja ich empfange eine ganze Seqeunz, wobei eben das '#' den Startpunkt kennzeichnet. das ganze sieht dann folgendermassen aus: Bsp: #0558,1067,0844 #0168,0937,0359 ... diese Sequenz gibt mir die Beschleunigungen in alle drei Richtungen wieder. Diese Zeichenfolge wird dann mit einer bestimmten Frequenz ständig wiedergegeben, so alle 50HZ. Was ich schlussendlich will sind die Zahlenwerte natürlich und ich dachte ich könnte es eben folgendermassen machen: while(1){ while(USART_Receive()!='#'); USART_Receive(); xAcc[0]=USART_Receive(); xAcc[1]=USART_Receive(); xAcc[2]=USART_Receive(); xAcc[3]=USART_Receive(); USART_Receive(); // Komma empfangen yAcc[0]=USART_Receive(); yAcc[1]=USART_Receive(); yAcc[2]=USART_Receive(); yAcc[3]=USART_Receive(); USART_Receive(); zAcc[0]=USART_Receive(); zAcc[1]=USART_Receive(); zAcc[2]=USART_Receive(); zAcc[3]=USART_Receive(); ...auswerten usw... } Nebenbei will ich ja eigentlich ja gar nichts anderes tun, deshalb denke ich kann ich gut in dieser schlaufe verweilen und auf # warten. Was meint ihr zum restlichen Programmstück, sollte das so klappen(leider konnte ich es noch nicht ausprobieren)?
@ Hari (Gast) >Was ich schlussendlich will sind die Zahlenwerte natürlich und ich >dachte ich könnte es eben folgendermassen machen: Prinzipiell möglich, aber praktisch bisweilen problematisch. Du solltest ERST den String koplett empfangen, dann prüfen und dann erst die Zahlen ind die Variablen schreiben. Ist nicht nur übersichtlicher sondern auch sicherer. >Nebenbei will ich ja eigentlich ja gar nichts anderes tun, deshalb denke >ich kann ich gut in dieser schlaufe verweilen und auf # warten. Was Und was ist, wenn das Startzeichen durch einen Übertragungsfehler verfälscht wird? MFG Falk
>(leider konnte ich es noch nicht ausprobieren)?
Und was möchtest du jetzt ? Eine Funktionsgarantie ?
Probier deinen Kram bitte selber aus bevor du Fragen stellst.
Wenns irgendwo klemmt dann fragst du nochmal nach.
holger wrote: > Und was möchtest du jetzt ? Eine Funktionsgarantie ? > Probier deinen Kram bitte selber aus bevor du Fragen stellst. Für einen Gast bist du aber ziemlich unhöflich! > Wenns irgendwo klemmt dann fragst du nochmal nach. Und du bist dann auch bestimmt der Erste, der einen hilfreichen Tipp abgibt, oder? Gruß, Magnetus
>> Probier deinen Kram bitte selber aus bevor du Fragen stellst. >Für einen Gast bist du aber ziemlich unhöflich! Warum ? Es war ein "bitte" in der Antwort. >Und du bist dann auch bestimmt der Erste, der einen hilfreichen Tipp >abgibt, oder? Sicher, warum nicht.
> Und was ist, wenn das Startzeichen durch einen Übertragungsfehler > verfälscht wird? @OP ... Muss ja nicht nur das Startzeichen sein. Was, wenn auf der UART zb dieses empfangen wird #5300,786,z9u&&% Das Problem: Die ersten beiden Variable hat bereits die neuen Werte erhalten, während die dritte Kombinationh ganz offensichtlich einer Störung zum Opfer gefallen ist. Schon aus dem Grund ist es vernünftiger die ganze Zeile zunächst mal als String zu empfangen, danach Plausibilitätstests durchzuführen und erst dann die Werte tatsächlich zu übernehmen. Damit stellt sich aber die Frage *Ich will auf ein '#' warten' gar nicht mehr. Du willst auf den Erhalt einer kompletten Zeile warten. In dieser Zeile muss das erste Zeichen ein '#' sein, gefolgt von 3 Zahlen, die durch ',' getrennt sind. Erst wenn diese Bedingungen erfüllt sind, werden die erhaltenen Zahlen weiterverteilt. Das Leben als Programmierer kann man sich so viel einfacher machen, wenn man sich an die Reihenfolge: Eingabe Eingabe prüfen, wenn gültig, dann Verarbeitung Ausgabe hält.
Der Standardansatz ist eine Zustandsmaschine im main oder im interrupt. interrupt rx; rxb:=UARTRx; rxcame:=true; end; state:=0; main : .. while true do if rxcame then case state of 0: if rxb='#' then ... state:=1; | 1: if rxb=............ state:=2; | .. end; rxcame:=false; end; // rxcame
> Schon aus dem Grund ist es vernünftiger die ganze Zeile zunächst > mal als String zu empfangen, danach Plausibilitätstests > durchzuführen und erst dann die Werte tatsächlich zu übernehmen. Leider bin ich mit dem USART noch nicht ganz so vertraut, deshalb meine Frage: Wie kann ich die ganze Zeile zuerst als String empfangen? War bisher immer eher zeichenorientiert damit umgegangen.
Hari wrote: >> Schon aus dem Grund ist es vernünftiger die ganze Zeile zunächst >> mal als String zu empfangen, danach Plausibilitätstests >> durchzuführen und erst dann die Werte tatsächlich zu übernehmen. > > Leider bin ich mit dem USART noch nicht ganz so vertraut, deshalb meine > Frage: Wie kann ich die ganze Zeile zuerst als String empfangen? War > bisher immer eher zeichenorientiert damit umgegangen. Die Gegenstelle sendet ein bestimmtes Zeichen, das als 'Ende der Zeile' gilt. Genau dieses Zeichen wird zb übertragen, wenn du in einem Terminal auf Return (Die grosse Taste mit dem Haken) drückst. In C schreibt sich dieses Zeichen als '\r'. Du sammelst also Zeichen in einem Array, bis von der Gegenstelle ein '\r' daherkommt. Dann hast du eine komplette Zeile empfangen und kannst dich daran machen, diese Auszuwerten. Beitrag "ASCII Verarbeitung optimieren"
ok angenommen dieser Programmabschnitt funktioniert soweit: while(initialCharacter!='#'){ initialCharacter=USART_Receive(); } xAcc[0]=USART_Receive(); xAcc[1]=USART_Receive(); xAcc[2]=USART_Receive(); xAcc[3]=USART_Receive(); USART_Receive(); yAcc[0]=USART_Receive(); yAcc[1]=USART_Receive(); yAcc[2]=USART_Receive(); yAcc[3]=USART_Receive(); USART_Receive(); zAcc[0]=USART_Receive(); zAcc[1]=USART_Receive(); zAcc[2]=USART_Receive(); zAcc[3]=USART_Receive(); xRate[4]='\0'; //für String Nullcharakter setzen, richtig??? yRate[4]='\0'; zRate[4]='\0'; xAcc[4]='\0'; yAcc[4]='\0'; zAcc[4]='\0'; hier wandle ich jetzt die strings in integer um, geht das so? /*** process signals ***/ xAcceleration=atoi(xAcc); yAcceleration=atoi(yAcc); zAcceleration=atoi(zAcc); und hier will ich die x-beschleunigung wieder zurück in einen string wandeln (nur für debugging zwecke, um zu schauen ob itoa und atoi das amchen was ich will) diesen string sende ich dann an den PC der jetzt den richtigen Wert erhalten sollte, tut er aber nicht :-( irgendwo steckt noch der Wurm drin. itoa(xAngularRate,xAngStr,10); USART_Transmit(xAngStr[0]); USART_Transmit(xAngStr[1]); USART_Transmit(xAngStr[2]); USART_Transmit(xAngStr[3]); Bin dankbar für eure Hilfe!
Hari wrote: > itoa(xAngularRate,xAngStr,10); > USART_Transmit(xAngStr[0]); > USART_Transmit(xAngStr[1]); > USART_Transmit(xAngStr[2]); > USART_Transmit(xAngStr[3]); Schreib dir als allererstes mal eine Funktion, mit der du einen String ausgeben kannst. Dieses ständige Rumhantieren mit einzelnen Charactern ist ja nicht zum aushalten.
1 | void USART_Transmit_String( const char* String ) |
2 | {
|
3 | while( *String ) { |
4 | USART_Transmit( *String ); |
5 | String++; |
6 | }
|
7 | }
|
Jetzt probierst du diese Funktion mal aus:
1 | int main() |
2 | {
|
3 | ....
|
4 | |
5 | while( 1 ) { |
6 | USART_Transmit_String( "Hallo" ); |
7 | }
|
8 | }
|
Wenn das soweit in Ordnung ist, gehts weiter:
1 | int main() |
2 | {
|
3 | char xAngStr[20]; |
4 | int xAngularRate = 25; |
5 | |
6 | while( 1 ) { |
7 | itoa( xAngularRate, xAngStr, 10); |
8 | USART_Transmit_String( xAngStr ); |
9 | }
|
10 | }
|
Und dann überprüfst du als allererstes mal, ob dein µC die Texte auch so empfängt wie du sie abschickst:
1 | char xAcc[5]; |
2 | char yAcc[5]; |
3 | char zAcc[5]; |
4 | |
5 | ....
|
6 | |
7 | while(initialCharacter!='#'){ |
8 | initialCharacter=USART_Receive(); |
9 | }
|
10 | |
11 | xAcc[0] = USART_Receive(); |
12 | xAcc[1] = USART_Receive(); |
13 | xAcc[2] = USART_Receive(); |
14 | xAcc[3] = USART_Receive(); |
15 | xAcc[4] = '\0'; |
16 | |
17 | USART_Receive(); |
18 | yAcc[0] = USART_Receive(); |
19 | yAcc[1] = USART_Receive(); |
20 | yAcc[2] = USART_Receive(); |
21 | yAcc[3] = USART_Receive(); |
22 | yAcc[4] = '\0'; |
23 | |
24 | USART_Receive(); |
25 | zAcc[0] = USART_Receive(); |
26 | zAcc[1] = USART_Receive(); |
27 | zAcc[2] = USART_Receive(); |
28 | zAcc[3] = USART_Receive(); |
29 | zAcc[4] = '\0'; |
30 | |
31 | USART_Transmit_String( "Received X:#" ); |
32 | USART_Transmit_String( xAcc ); |
33 | USART_Transmit_String( "# Y:#" ); |
34 | USART_Transmit_String( yAcc ); |
35 | USART_Transmit_String( "#Z: #" ); |
36 | USART_Transmit_String( zAcc ); |
37 | USART_Transmit_String( "#\r" ); |
38 | |
39 | ....
|
Du musst dir angewöhnen alles und jeden zu überprüfen.
Wenn du einen String empfängst, dann wird als allererstes
gecheckt, ob das auch funktioniert. Es ist sinnlos mit
falschen Daten weiterzurechnen und hinterher sich zu beschweren,
dass da was falsches rauskommt.
Ob einzelne Character korrekt übertragen werden, hast du hoffentlich
schon getestet.
> ok angenommen dieser Programmabschnitt funktioniert soweit:
**********
Dieses Wort musst du auf jeden Fall vermeiden. Entweder etwas
funktioniert oder es funktioniert nicht. Aber 'angenommen dass'
ist ein Schuss der öfter als dir lieb ist nach hinten losgeht.
Besten Dank für die tolle Hilfe, bin wirklich dankbar! jetzt läufts mal grob, und morgen gehts dann noch darum das Programm "schön" zu machen mit Interrupts und Charakterprüfung usw. Aber nochmals vielen Dank an alle und speziell an Karl Heinz!
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.