Hallo zusammen, im Rahmen meines Projektes bin ich gerade auf ein neues Problem gestoßen. Mein MSP430 hört auf dem CAN-Bus mit, was alles so gesendet wird. Dabei achtet er auf ungefähr eine handvoll CAN-Botschaften identifiziert durch die entsprechende ID. Die IDs werden dabei von einer SD Karte gelesen und sind im aktuellen Fall Fünf an der Anzahl. Der Controller soll nun den Bus abhören und Alarm schlagen, sobald eine ID innerhalb einer Sekunde nicht empfangen worden ist (fast alle Botschaften werden dabei alle 40ms gesendet). Gerade wollte ich eine Ausgabe implementieren, welche einige Messwerte per UART über USB an den Computer sendet (Das Board wird als USB Serial Converter am PC erkannt). Gesagt, getan und es funktioniert. Allerdings wird das Board dadurch scheinbar so stark belastet, dass meine Menüführung quasi gar nicht mehr möglich ist (Software-Debouncing in while-Schleife in der main). Kann das sein? Ist das Senden via UART so anspruchsvoll? Oder sind es eher meine String-Operationen (1x strcpy, 8x strcat, 1x itoh, 1xitoa, 2x ftoa, Routinen aus numtostr-Paket hier aus dem Forum: Beitrag "C-Umwandlungsfunktionen für double/int/long nach String"), die zuviel Rechenzeit benötigen? Eine Nachricht sieht zum Beispiel so aus: "Fehlende CAN-Nachricht: ID: 0x123; Temp: 12.123; Hum: 12.123, Spannung: 0\r\n" Im Moment ist der CAN-Bus abgeklemmt und das Board soll auf 5 Nachrichten reagieren. Demnach wird die obige Nachricht 5mal pro Sekunde (mit unterschiedlichen IDs) gesendet. Was meint ihr? Woran wird es am wahrscheinlichsten liegen?
:
Bearbeitet durch User
@ Roland M. (eroli) >Gesagt, getan und es funktioniert. Allerdings wird das Board dadurch >scheinbar so stark belastet, dass meine Menüführung quasi gar nicht mehr >möglich ist (Software-Debouncing in while-Schleife in der main). Aua! Das macht man mit einem TIMER! Siehe Entprellung >Kann das sein? Ist das Senden via UART so anspruchsvoll? Oder sind es Nein. >Was meint ihr? Woran wird es am wahrscheinlichsten liegen? An deiner unpassenden Programmierung.
Das kommt darauf an (tm). Ohne Blick auf den Sourcecode wird man keine vernünftige Aussage treffen können.
Sorry für den Doppelpost, aber ich habe gerade mal probiert alle Umwandlungen (itoh, itoa und ftoa) auszukommentieren und dann funktioniert es wunderbar. Auch mit itoh und itoa läuft es gut. Scheinbar braucht die ftoa-Funktion sehr viel Rechenzeit. Diese sieht bei mir so aus
1 | void ftoa(char * buf, double f, char d, char pad, char padchar) |
2 | {
|
3 | char * p; |
4 | const double powers[] = {1.0,10.0,100.0,1000.0,10000.0,100000.0}; |
5 | |
6 | /* round */
|
7 | f = f>=0.0 ? (f*powers[d]+0.5)/powers[d] : (f*powers[d]-0.5)/powers[d]; |
8 | |
9 | /* special case */
|
10 | if (f<0.0 && f > -1.0) { |
11 | p = ltoa(buf,-1,pad,padchar); |
12 | *(p-1) = '0'; |
13 | }
|
14 | else
|
15 | p = ltoa(buf,f,pad,padchar); |
16 | |
17 | *p++ = '.'; |
18 | |
19 | if (f<0.0) |
20 | f = -f; |
21 | |
22 | f -= (long) f; |
23 | f *= powers[d]; |
24 | ltoa(p,(long)f,d,0); |
25 | }
|
26 | |
27 | char * ltoa(char * buf, long val, char pad, char padchar) |
28 | {
|
29 | char i; |
30 | char neg = 0; |
31 | char tmp_buf[21]; |
32 | |
33 | if(val<0) { |
34 | val = -val; |
35 | neg = 1; |
36 | }
|
37 | |
38 | for(i=0; val>0; val/=10) |
39 | tmp_buf[i++] = (val % 10) + '0'; |
40 | |
41 | if(i==0) |
42 | tmp_buf[i++] = '0'; |
43 | |
44 | if(neg) { |
45 | if(padchar) { |
46 | tmp_buf[i++] = '-'; |
47 | while(i<pad) |
48 | tmp_buf[i++] = ' '; |
49 | }
|
50 | else { |
51 | while(i<pad-1) |
52 | tmp_buf[i++] = '0'; |
53 | tmp_buf[i++] = '-'; |
54 | }
|
55 | }
|
56 | else
|
57 | while(i<pad) |
58 | tmp_buf[i++] = padchar ? ' ' : '0'; |
59 | |
60 | while(i>0) |
61 | *buf++ = tmp_buf[--i]; |
62 | |
63 | *buf = 0; |
64 | |
65 | return buf; |
66 | }
|
Gibt es da vielleicht effizientere Wege? @ Falk Brunner: Sicher ist das per Timer eleganter, aber das ist hier an dieser Stelle nicht das Problem. Dennoch werde ich das wohl auf einen neuen Timer umstellen. Danke für den Hinweis.
:
Bearbeitet durch User
Roland M. schrieb: > eher meine String-Operationen (1x strcpy, 8x strcat, 1x itoh, 1xitoa, 2x > ftoa, Da kommt allerdings dann schon einiges zusammen. > "Fehlende CAN-Nachricht: ID: 0x123; Temp: 12.123; Hum: 12.123, Spannung: > 0\r\n" Muss das wirklich so geschwätzig sein? Je nach Baudrate, dauert eine Übertragung dann schon seine Zeit. Und auch (speziell bei Floating Point) die Aufbereitung von Werten in eine ASCII Repräsentierung kriegt man nicht gratis. Klar ist mir zb nicht, wozu du die ganzen strcpy und strcat brauchst. Am Terminal kannst du sowieso nicht unterscheiden, ob das Programm zuerst ala
1 | strcpy( buffer, "Hallo " ); |
2 | strcat( buffer, "World!\n" ); |
3 | |
4 | uart_string( buffer ); |
den Text zuerst in einen String zusammengebaut hat, oder ob du mittels
1 | uart_string( "Hallo " ); |
2 | uart_string( "World!\n" ); |
2 String-Übertragungen hattest. Der einzige Unterschied: du belastest deinen µC mit einem zusätzlichen Buffer, in dem erst mal alles 20 mal umkopiert werden muss, ehe es dann tatsächlich per UART auf die Reise geht.
:
Bearbeitet durch User
Hallo Karl Heinz, du hast natürlich Recht... Da habe ich gar nicht drüber nachgedacht. Ich habe es nun wie du vorgeschlagen hast abgeändert und die einzelnen Konvertierungsergebnisse direkt an den UART zum Senden übergeben. Es ist ein wenig besser, aber es braucht immer noch tierisch lange. Ich denke das wesentliche Problem hierbei ist die ftoa-Geschichte... Baudrate ist übrigens 38400. Zuerst war ich bei 9600 und dachte das Problem mit einer Erhöhung entschärfen zu können. Hat aber zu keiner merklichen Verbesserung beigetragen...
:
Bearbeitet durch User
@ Roland M. (eroli) >Umwandlungen (itoh, itoa und ftoa) auszukommentieren und dann >funktioniert es wunderbar. Auch mit itoh und itoa läuft es gut. Das ist ja schon mal ein wichtiger Hinweis. >Scheinbar braucht die ftoa-Funktion sehr viel Rechenzeit. Diese sieht >bei mir so aus Wozu postest du denn Quelltext? Das sind doch normalerweise Funktionen, die in deiner Compilerbilbiothek mit drinstecken. Wahrscheinlich auch deutlich besser optimiert. Möglicherweise musst du die (optimierte) Bibliothek zu deinem Code linken, damit die (langsamen) Standardfunktionen ersetzt werden. Beim avr gcc ist das jedenfalls so.
Roland M. schrieb: > Ich denke das wesentliche Problem hierbei ist die ftoa-Geschichte... Flaoating Point ist für einen µC ohne FPU schon recht aufwändig. Brauchst du wirklich die Temperatur auf 2 Nachkommastellen. Und: wenn ja, brauchst du sie wirklich in der Form 89.50 oder reicht dir zum Debuggen nicht auch ein 8950 und du weißt ganz einfach, dass zwischen Zeher und Hunderter ein Dezimalpunkt rein muss. Das könnte zb auch ein Programm mit viel weniger Aufwand erledigen. Funktionen werden meistens umfangreicher und aufwändiger, wenn sie so allgemein wie möglich sein müssen. Braucht man diese Allgemeingültigkeit nichtm, dann vereinfacht sich vieles. Eine Ausgabe, die einen 16 Bit int immer in ein Feld der Größe 7 Zeichen (inkl. abschliessendes 0-Byte) reinschreibt und zwar immer mit führenden 0-en, ist ein trivial und wird kaum länger als ein paar Zeilen. Verglichen mit deinem Monster für ltoa ist das schon recht heftig. Nicht aus den Augen lassen, solltest du aber die Baudrate. Bei zb 9600 Baud, kriegst du gerade mal ca. 1000 Zeichen pro Sekunde rüber. D.h. pro Zeichen dauert die Übertragung 1ms. Der Unterschied zwischen "Fehlende CAN-Nachricht: ID: 0x123; Temp: 12.123; Hum: 12.123, Spannung: 0\r\n" und "miss ID 123; T 12 H 12 V 0\r\" siond alleine aus dem Grund schon mal 46ms bei 9600 Baud. Und das nur dadurch, dass dein Programm nicht so geschwätzig ist.
:
Bearbeitet durch User
Hallo zusammen, da ich wirklich nicht gedacht hätte, dass die Konvertierung einer float-Variablen in einen String so anspruchsvoll ist, habe ich mich dazu entschieden die Variable auf einen int zu casten und dann mittels itoa zu konvertieren. Die vielen strcat-Funktionen habe ich quasi durch meine UART_Transmit-Funktion ersetzt, sodass auch der große Buffer wegfällt. Jetzt läuft es für mich akzeptabel schnell. Vielen Dank für eure Erfahrungen ;-) EDIT: Übrigens gibt es in der stdlib vom MSPGCC keine ftoa-Funktionen und dergleichen ;-) Daher hatte ich weiter oben das Quelltext-Monster gepostet ;-)
:
Bearbeitet durch User
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.