Forum: Compiler & IDEs probleme bei Portierung von einem Konsolen Programm auf den AVR
Hallo ich habe da ein kleines Problem bei einem programm von mir.
Das Problem ist folgendes: Ich bin gerade dabei, eine Art Konsole für
den AVR zu schreiben. Dafür wollte ich ein paar String Manipulatoren
schreiben sprich einer der mir in einem String bei entsprechenden
Trennzeichen zB. bei set_date 05.09.09 dann in drei unsigned char Werte
umwandelt so das ich mit dem zB. 0x05 usw. weiter rechnen kann.
Ausserdem gibt es eine Funktion, die dann die ersten chars im String
untersucht so das ich dann weiß um welchen Befehl es sich handelt in
diesem Fall um set_date.
So ich habe angefangen zu schreiben und habe dieses dann direkt auf dem
PC getestet. Dieses Funktionen funktionieren auf dem PC wunderbar ohne
Probleme. Nur auf dem ATMega 32 nicht.
Folgende Dinge habe versucht um das Problem besser eingrenzen zu können:
* den test String direkt als konstante im prog. Speicher zu speichern um
zu schauen, ob die FUnktion den Befehl erkennt
* per USART den String übertragen und auch den String selbst über UART
zurück übertragen lassen um evtl. Verbindungsprobleme erkennen zu
können.
Der string den ich ausgeben lasse ist immer richtig (laut terminal
programm kommen auch keine versteckten Zeichen wie zB. Steuerbefehle wie
\n oä an) nur das Ergebnis in den betreffenden Funktionen ist Falsch
obwohl auch in den Funktionen der String per USART richtig übertragen
wird.
Daher ist meine Frage, hat evtl. jemand eine Idee an was das liegen
könnte?
(die betreffende Funktionen findet ihr im Anhang)
Die Aufrufe waren im AVR wie folgt: 1 | //per USART empfangen: (fragmentfree)
| 2 | if(read_usart_stream(inc_buffer,Buffersize-offset, &recieved_bytes, offset)==0){
| 3 | if(recieved_bytes>=11){ //11 für 11 Bytes die benötigt werden
| 4 | get_instruction(inc_buffer, offset+recieved_bytes);
| 5 | offset=recieved_bytes;
| 6 | }
| 7 | else{
| 8 | offset=0;
| 9 | }
| 10 | //... empfangenen stream ausgeben usw. usw.
| 11 | }
| 12 | //per konstante:
| 13 | char tst_val[]="set_time 18:03:06";
| 14 | get_instruction(tst_val,11);
|
zugehörige Funktionen: 1 | void change_char(char *string, char comp_val, char ref_val){
| 2 | for(unsigned char i=0; i<255 && string[i]; i++){
| 3 | if(string[i]==comp_val) string[i]=ref_val;
| 4 | }
| 5 | }
| 6 |
| 7 | unsigned char comp_string( char * comp_string, char * ref_string){
| 8 | for(unsigned char i =0; i<0xFF && ref_string[i];i++)
| 9 | if(comp_string[i]!=ref_string[i]) return 0xff;
| 10 |
| 11 | return 0x00;
| 12 |
| 13 | }
| 14 |
| 15 | unsigned char str_to_int (char * ref_string, unsigned char position, unsigned char values){
| 16 | unsigned char buffer[3]={0,0,0}; //max 3 stellen sind erlaubt...
| 17 | unsigned char value=0;
| 18 | for(unsigned char pos_tmp=(position+1); pos_tmp<=(position+values); pos_tmp++){
| 19 | buffer[pos_tmp-position-1]=ref_string[pos_tmp]-'0';
| 20 | }
| 21 | for(unsigned char i=1; i<=values; i++){
| 22 | value+=buffer[i-1];
| 23 | if(i!=values)value*=10;
| 24 | }
| 25 | return value;
| 26 | }
| 27 |
| 28 | unsigned char get_information(char * string,char f_sep,char n_sep, unsigned char values,unsigned char length, unsigned char * res_vect){
| 29 | unsigned char result=0, v_counter=0;
| 30 | for(unsigned char i=0; i<0xFF && string[i];i++){
| 31 | if(v_counter==0 && string[i]==f_sep){
| 32 | res_vect[v_counter]=str_to_int(string, i, length);
| 33 | v_counter++;
| 34 | }
| 35 | if(v_counter!=0 && string[i]==n_sep){
| 36 | res_vect[v_counter]=str_to_int(string, i, length);
| 37 | v_counter++;
| 38 | }
| 39 | if(v_counter>=values) return 0x00;
| 40 | }
| 41 | return 0xFF;
| 42 | }
|
Björn Cassens schrieb:
> 1 | > //per USART empfangen: (fragmentfree)
| 2 | > if(read_usart_stream(inc_buffer,Buffersize-offset, &recieved_bytes,
| 3 | > offset)==0){
| 4 | > if(recieved_bytes>=11){ //11 für 11 Bytes die benötigt
| 5 | > werden
| 6 | > get_instruction(inc_buffer, offset+recieved_bytes);
| 7 | > offset=recieved_bytes;
| 8 | > }
| 9 | > else{
| 10 | > offset=0;
| 11 | > }
| 12 | > //... empfangenen stream ausgeben usw. usw.
| 13 | > }
| 14 | > //per konstante:
| 15 | > char tst_val[]="set_time 18:03:06";
| 16 | > get_instruction(tst_val,11);
| 17 | >
|
Wieso 11?
Ich kann in deinem Code bzw in den Testdaten keine Begründung für 11
finden.
> 1 | > void change_char(char *string, char comp_val, char ref_val){
| 2 | > for(unsigned char i=0; i<255 && string[i]; i++){
| 3 | > if(string[i]==comp_val) string[i]=ref_val;
| 4 | > }
| 5 | > }
| 6 | >
|
Verzichte darauf, mittels Index-Variablen durch einen String
durchzulaufen. Du brauchst sie nicht und es gibt keinen Grund da jetzt
eine künstliche Beschränkung auf 255 Zeichen maximal einzuführen
1 | void change_char(char *string, char comp_val, char ref_val){
| 2 | while( *string ) {
| 3 | if( *string == comp_val )
| 4 | *string = ref_val;
| 5 | string++;
| 6 | }
| 7 | }
|
> unsigned char comp_string( char * comp_string, char * ref_string){
> for(unsigned char i =0; i<0xFF && ref_string[i];i++)
> if(comp_string[i]!=ref_string[i]) return 0xff;
>
> return 0x00;
>
> }
Warum erfindest du hier das Rad neu?
Die Standardfunktion dafür heisst strcmp() und ist in string.h enthalten
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F
> unsigned char str_to_int (char * ref_string, unsigned char position,
> unsigned char values){
> unsigned char buffer[3]={0,0,0}; //max 3 stellen sind erlaubt...
> unsigned char value=0;
> for(unsigned char pos_tmp=(position+1); pos_tmp<=(position+values);
> pos_tmp++){
> buffer[pos_tmp-position-1]=ref_string[pos_tmp]-'0';
> }
> for(unsigned char i=1; i<=values; i++){
> value+=buffer[i-1];
> if(i!=values)value*=10;
> }
> return value;
> }
Ziemlich umständlich. Warum benutzt du nicht atoi?
> unsigned char get_information(char * string,char f_sep,char n_sep,
> unsigned char values,unsigned char length, unsigned char * res_vect){
> unsigned char result=0, v_counter=0;
> for(unsigned char i=0; i<0xFF && string[i];i++){
> if(v_counter==0 && string[i]==f_sep){
> res_vect[v_counter]=str_to_int(string, i, length);
> v_counter++;
> }
> if(v_counter!=0 && string[i]==n_sep){
> res_vect[v_counter]=str_to_int(string, i, length);
> v_counter++;
> }
> if(v_counter>=values) return 0x00;
> }
> return 0xFF;
> }
Aus der Funktion werde ich nicht richtig schlau.
In Summe denke ich, dass du das alles viel zu kompliziert angehst.
> Dafür wollte ich ein paar String Manipulatoren
> schreiben sprich einer der mir in einem String bei entsprechenden
> Trennzeichen
Kennst du die Funktion strtok()? Ich denke, dass strtok schon 70% dessen
erledigt, was du da so mühsam zusammenschreibst.
Mittels strtok den kompletten String an den Leerzeichen in Einzelteile
aufsplitten. Damit hast du dann Pointer auf die Einzelteile
set_time
und 18:03:06
set_time ist das Kommando bei dessen Erkennung wird der erste
Argumentstring an den : in 3 Einzelteile aufgesplittet (zb wieder mit
strtok()) und jeder Einzelteil mittels atoi in eine Zahl umgewandelt.
Fertig.
hmm naja ich dachte das ich mit meinem Code ein wenig kleiner werde...
und naja ich dachte darüberhinaus, dass gerade die Funktionen, die in
string.h wären dann dohc ein bissl groß wären für ein uC.
Aber alles in allem habe ich grad mal meinen Code ein wenig aufgeräumt
und naja ich habe einige potenzielle Fehlerquellen gefunden. Das werde
ich gleich mal ausprobieren. Aber du hast recht mit den Funktionen die
du mir genannt hast, ist es wahrscheinlich leichter naja - gut dann halt
ein paar Stunden Arbeit (Fehlersuche) für die Tonne und um ein paar
Erfahrungen und Überlegungen reicher.
Danke für deine Ausführliche Antwort.
Björn Cassens schrieb:
> hmm naja ich dachte das ich mit meinem Code ein wenig kleiner werde...
Solange du Stringverarbeitung darauf aufbaust, mit einer Indexvariable
alle Zeichen durchzugehen und nicht mit Pointer arbeitest, wird es
ziemlich schwierig sein, etwas noch langsameres und größeres als deinen
jetzigen Code zu schreiben.
> und naja ich dachte darüberhinaus, dass gerade die Funktionen, die in
> string.h wären dann dohc ein bissl groß wären für ein uC.
Ähm. Die meisten Funktionen in string.h sind in C-Quellcode
ausgeschrieben einfache 3-Zeiler. strtok ist eine der Ausnahmen, das ist
in der Tat etwas umfangreicher. So in der Gegend von 15 Zeilen.
Was ich damit sagen will:
Es ist sinnlos Dinge wie Stringverarbeitungsfunktionen in C selbst zu
schreiben. Es sei denn, du benötigst Funktionalität, die du so nicht in
string.h vorhanden hast bzw. nicht einfach daraus zusammensetzen kannst.
Manchmal kann man auch die Funktionalität 2-er string Funktionen in eine
einzige Schleife zusammenfassen, dann bringt das ein bischen was.
Aber gerade am Anfang ist das Wichtigste was du in C lernen kannst:
welche Funktionen habe ich in der Standard-Library zu meiner Verfügung
und wie kann ich sie benutzen bzw. wie kann ich aus diesen Funktionen
komlpexere Funktionalität zusammensetzen. Dazu muss man aber den
Funktionsvorrat kennen.
Nimm zb deine Funktion comp_string 1 | unsigned char comp_string( char * comp_string, char * ref_string){
| 2 | for(unsigned char i =0; i<0xFF && ref_string[i];i++)
| 3 | if(comp_string[i]!=ref_string[i]) return 0xff;
| 4 |
| 5 | return 0x00;
| 6 |
| 7 | }
|
und dagegen eine Standardimplementierung von strcmp 1 | int strcmp( const char * str1, const char * str2 )
| 2 | {
| 3 | while( *str1 && *str1 == *str2 ) {
| 4 | str1++;
| 5 | str2++;
| 6 | }
| 7 | return *str2 - *str1;
| 8 | }
|
Nicht nur ist der Returnwert universeller (er verrät mir neben
Ungleichheit auch noch welcher String den der Größere war) sondern er
hat auch keine Längenbeschränkung auf 255 Zeichen.
Ob hingegen deine Version schneller oder kleiner ist, wage ich mal zu
bezweifeln.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|