Hallo Leute! ICh habe das Prob das mein Atmeg32 keine Zeichenkette länger als 4 Zeichen (3Buchstaben + \0) speichert. Ab dem vierten Zeichen fehlt ihm das Schlusszeichen, was zu einem Wirrwarr am Display führt. Dass es die SPeicherung ist habe ich herausgefunden indem ich eine Funktion geschrieben habe die eine STring zerstückelt und jedes Zeichen extra ausgibt. DAs funktoiniert auch nicht. Könnt ihr mir helfen?! Ps: Atmeg32 3,6864 Mhz
Zeig doch mal etwas Code. Das Problem ist mit 100% Sicherheit irgendwo in Deinem Code zu suchen und nicht im Mega oder im Compiler.
Man sollte dazu sagen, dass das Programm einfach nur einen gespeicherten String auf dem Display ausgeben sollte Das steht im main file char text[]="Keb"; print(text); im header File steht folgendes: void print(char buffer []) { for ( int i = 0; buffer [i] !='\0'; i++) data(buffer[i]); } void data(unsigned char data) { buisy(); unsigned char data1 = data; // daten geseichert portx = (0x1f & (data>>4)|(1 << rs)); // rechtschieben enable(); portx = (0x1f & ((data1))|(1 << rs)); // ausgabe sicherung enable(); } der Befehl busy ist einfach nur dazu da, um zu warten, genau wie enable ;) MfG Saschisch
void print(char buffer []) { for ( int i = 0; buffer [i] !='\0'; i++) data(buffer[i]); } ^... mach mal anstatt '\0' einfach "\0" (oder 0x00 oder so^^). Ich weiß zwar nicht, ob Single- und Doublequotes so gesondert behandelt werden, aber n Versuch ist es ja wert.
C - Grundkurs, 3. Tag: mit " werden C-strings eingeschlossen, also eine Sequenz von Zeichen die mit einem '\0' character endet. mit ' werden einzelne Zeichen eingeschlossen, also ein ganz simpler einfacher char. Das ist 'keinen Versuch wert' der '\0' stimmt schon.
Das wies ich nicht. Ich benutze nicht Deinen Compiler, daher kann ich Dein Program auch nicht ausprobieren. Beim reinen durchschauen durch den Code ist mir nichts Grossartiges aufgefallen, was diesen Effekt erklaeren koennte. (Code aus einem anderen Thread geholt).
Naja ok trotzdem danke WEnn ich das PRoblem gelöst habe schreibe ich dir wie es funktioniert hat
Hi @Karl Heinz >mit ' werden einzelne Zeichen eingeschlossen, also ein ganz simpler >einfacher char. Das ist so nicht ganz richtig (um mal einen richtig schlechten Film mit W. Smith zu zitieren) :-) int i = '34'; ist durchaus gültiges C und equvivalent mit int i = 0x3334; Matthias
Wie hast du festgestellt, dass du nur 3 Zeichen lange Strings speichern kann? Compilierst Du jedes mal neu oder änderst Du die Zeichenkette in text[] im Laufe des Programms? Falls letzteres, Das Feld text[] ist nur 4 Bytes lang ( entspricht 3 Zeichen + \0).
Ich bin bei den Compiler Geschichten eher schwach auf der Brust muss ich zugeben... Was ist ein avr-objcpy?? Ich habe das herausgefunden indem ich versucht habe vor dem compilieren 4 Zeichen bzw 5 auszugeben und es geht einfach nicht er zeigt nur unwillkürliche Zeichenfolgen am Display an MFG Saschisch
Wie ich es schon geschrieben hat: "char text[]="Keb";" ist falsch. Mach daraus: char text[xx]; mit xx zum Beispiel 10 oder wie lang Du das halt brauchst. Dann passt das.
Hi nö. Der Compiler ermittelt aus der Länge des Strings die nötige Größe des Arrays automatisch. Matthias
Ohne mir das ganz genau anzuschauen, aber was macht denn diese Zeile in deinem Code: unsigned char data1 = data; // daten geseichert data ist doch ein Zeiger auf den Funktionsaufruf.
@Birger: Nein, data ist ein char (das dann auf unsigned gecastet wird). @Matthias: Das ist für char text[]="Keb"; richtig. Wenn ich das aber richtig verstanden habe, wird danach versucht sowas wie text[4] = 'b'; text[5] = 'l'; text[6] = 'a'; text[7] = '\0'; zu machen. Und das geht dann schief. Oder hab' ich das was falsch verstanden?
Hi ich kann in dem was saschisch gepostet hat nicht entdecken wo sowas gemacht wird. Aber evtl. bin ich heute morgen auch etwas blind auf den Augen. Matthias
> Was ist ein avr-objcpy?
avr-objcopy ist das Kommando, mit dem aus dem ELF-File, das der
Linker ausgibt, ein Intel-Hex-File zum Laden in den Prozessor
gebaut wird.
Saschisch Ich hab mir nochmal Deinen anderen Thread angesehen. Du schreibst darin, dass Du den Text "Servas" ausgeben moechtest und am Display aber der Text evs!$%"&/&_ kommt. Gilt das noch? Bei Vergleich der beiden Strings fallt naemlich auf, dass da nicht wie du hier behauptest, die ersten 3 Zeichen ausgegeben werden, sondern immer jeder 2.te. Das ist aber eine andere Diagnose und man muss damit nach anderen Ursachen suchen. Bitte bestaetige!
Poste auch noch mal den kompletten Code. Speck ihn aber ab, so dass nur noch die tatsaechlich gebrauchten Funktionen drin vorkommen (inklusive aller Hilfsfunktionen). Allerdings wichtig: bitte vollstaendigen Code. Theoretisch muss jemand anders in der Lage sein, Deinen Code von hier zu kopieren, ihn in seinen Compiler zu stecken und das ganze dann ausfuehren koennen.
Danke nochmal! Hier die main.c: #include<avr/io.h> #include<avr/delay.h> #include "lcd.h" // eigene lcd lib getester mit atm16 alle ports int main (void) { char text[]="Keb"; init(); pos(1,1); print(text); // ausgabe string pos(2,1); run(20); print("Servas Text") // ausgabe string run(20); for(;;){ } //endlosschleife } hier die lcd.c: #include<avr/io.h> #include<avr/delay.h> #include<string.h> #define ddrx DDRA #define portx PORTA #define db4 PINA0 #define db5 PINA1 #define db6 PINA2 #define db7 PINA3 #define rs PINA4 #define rw PINA5 #define en PINA6 #define led PINA7 void delay(void); // 3 takte verzvgerung void delay5ms(void); // 5 ms verzögerung void enable(void); // erzeugen des enable puls void buisy(void); // warten bis bereit(nur durch zeitverzvgerung) void comm(unsigned char comm); // schreibt commando void data(unsigned char data); // schreibt daten void init(void); // initialisiert display void clear(void); // löscht display void pos(unsigned char l,unsigned char p); // zeile spalte 1/2 1-24 void print(char buffer []); // gibt string aus void drucken(char buffer2 [],int x,int y); void boot(unsigned char zeichen,unsigned char zahl ,unsigned char zeile,unsigned char sp); //zeichen anzahl durchgänge zeile / spalte) void run(char ms100); // drei takte warten void delay(void) { asm volatile( "nop\n\t" "nop\n\t" "nop\n\t"::);} //enable ein aus void enable(void) { portx |= (1 << en); // setzt bit delay(); portx &= ~(1 << en); // lvscht Bit } void delay5ms(void) { // inline asm warteschleife asm volatile( "push R16" "\n\t" "push R17" "\n\t" "ldi R16, 0x25" "\n\t" "WGLOOP0:""\n\t" "ldi R17, 0xA5" "\n\t" "WGLOOP1:""\n\t" "dec R17" "\n\t" "brne WGLOOP1" "\n\t" "dec R16" "\n\t" "brne WGLOOP0" "\n\t" "pop R16" "\n\t" "pop R17" "\n\t"::);} // wartet bis lcd bereit void buisy(void) { _delay_ms(15); } // sendet comando --- rs nicht gesetzt void comm(unsigned char comm) { buisy(); unsigned char comm1 = comm; portx = (0x0f & (comm>>4)); enable(); portx = (0x0f & (comm1)); enable(); } // sendet daten -- rs gesetzt void data(unsigned char data) { buisy(); unsigned char data1 = data; // daten geseichert portx = (0x1f & (data>>4)|(1 << rs)); // rechtschieben enable(); portx = (0x1f & ((data1))|(1 << rs)); // ausgabe sicherung enable(); } void init(void){ ddrx = 0xff; portx = 0xff; // 15 ms warten unsigned char d= 10; do{ --d; delay5ms(); }while(d != 0 ); // drei mal 8 bit initialisieren portx = (0b00000011); enable(); delay5ms(); enable(); delay5ms(); enable(); // 4 bit modus aktivieren delay5ms(); portx = (0b00000010); enable(); delay5ms(); // sachen einstellen comm(0b00101000); //2zeilig 5*8 delay(); comm(0b00001000); delay(); comm(0b00000001); delay(); comm(0b00000010); delay(); comm(0b00001100); // display lvschen } void clear(void) { comm(0b00000001); pos(1,1); } void pos(unsigned char l,unsigned char p) { unsigned char pos = 0b10000000; if(l==1){ pos |= p-1; } if(l==2){ p =+40; pos |= p; } comm(pos); } // void print(char buffer []) { for ( int i = 0; buffer [i] !='\0'; i++) data(buffer[i]); } void boot( unsigned char zeichen,unsigned char zahl, unsigned char zeile,unsigned char sp) { do{ unsigned char spalte= sp; zahl = zahl-1; _delay_ms(100); pos(zeile, spalte); print(" "); pos(zeile,spalte); _delay_ms(100); data(zeichen); _delay_ms(100); data(zeichen); _delay_ms(100); data(zeichen); _delay_ms(100); data(zeichen); _delay_ms(100); data(zeichen); }while(zahl != 0); } void drucken(char buffer2 [],int x,int y) { pos(x,y); int i=0; while(i<=strlen(buffer2)) { print(buffer2[i]); y=y+1; pos(x,y); i=i+1; } } /*void drucken(unsigned char *p) { do { data(*p); p++; } while (*p!='\0'); } */ void run(char ms100) { unsigned char d= ms100; do{ --d; _delay_ms(100); }while(d != 0 ); portx |= (1 << led); // setzt bit d= ms100; do{ --d; _delay_ms(100); }while(d != 0 ); portx &= ~(1 << led); // löscht Bit } Das sollte so wie es ist keinen Compiler Fehler auswerfen bzw. gibt es bei mir keinen aus:) MfG Saschisch
Deine Funktion "print(char buffer [])" erwartet die Adresse einer Zeichenkette. Beim zweiten Aufruf hilft Du ihr aber eine Zeichenkettenkonstante über. Stichwort: Übergabe eines Feldes als Parameter an eine Funktion. kbuchegg oder Matthias kennen sich mit diesen feinheiten sicher besser aus als ich.
Hi das passt schon. Ich kann jetzt so auf Anhieb keinen Fehler erkennen, hab den Code aber auch nicht compiliert. Das Verhalten das nur jedes zweite Zeichen ankommt hatte ich mal als die Verzögerungsschleife für das LCD zu kurz war. Ich sehe in dem Code z.B. nicht wo die CPU Frequenz der AVRlibc bekannt gemacht wird. Matthias
Das passt schon. Ich hab den Code mitlerweile im Simulator mit Hapsim am laufen und kann das geschilderte Verhalten so nicht beobachten. Der Text kommt wie erwartet mit einer kleinen Feinheit: Nach dem Pos(2,1) wird das erste 'S' von "Servus Text" nicht richtig ausgegeben(*), alles andere kommt so wie erwartet. Fuer dieses Verhalten hab ich zur Zeit noch keine Erklaerung. Benutze den avr-gcc (*) Anstelle des S kommt einfach ein Leerzeichen. Kann ich nicht erklaeren. Ich habs bis auf Portebene im Simulator nachvollzogen, die Ausgabe duerfte stimmen. Hmm. So wies aussieht, wird nachdem das Display auf die 2.-te Zeile gesetzt wird, das erste ausgegebene Zeichen verschluckt. Koennte auch ein Fehler im Hapsim sein. Wie gesagt: prinzipiell funktioniert der Code. Zumindest tritt das beschriebene Verhalten bei mir nicht auf.
@ KArl Heinz: Die erste Zeile wird bei dir korrekt ausgegeben? Hast du keine Compiler Warnungen? Das mit dem S ist wieder bei mir nicht ;) Ich sehe die zweite Zeile perfekt und ohne Probleme ): Aber das Übergeben von diesen verdammten verrückten Strings bösewerd Naja ich muss das bald fertig haben... also werde ich halt nicht schlafen :) OK, ich gebe in meinem MAKE File die Taktfrequenz an. MfG Saschisch
Compiler-Warnungen hab ich 3 2 davon kannst Du ignorieren (musst Du aber nicht). Die 3.te ist allerdings schwerwiegend. Keine von den 3-en hat allerdings mit Deinem Problem zu tun: ../LCD.c:74: warning: suggest parentheses around arithmetic in operand of | ../LCD.c:76: warning: suggest parentheses around arithmetic in operand of | ../LCD.c:189: warning: passing arg 1 of `print' makes pointer from integer without a cast Die ersten beiden beziehen sich auf: portx = (0x1f & (data>>4)|(1 << rs)); // rechtschieben gcc schlaegt vor, dass mit Klammern eindeutig festgelegt wird in welcher Reihenfolge & und | abgearbeitet werden. Die 3-te schwerwiegende: void drucken(char buffer2 [],int x,int y) { ... print(buffer2[i]); Da hat er recht. Das wird so nichts. Da wirst Du nochmal druebergehen muessen.
"Drucken" ist eine Verzweiflungfunktion^^ um das Ding endlich zum laufen zu bringen. Diese haben wir nachträglich dazugegeben. Wird also nicht mehr verwendet.
Könnt ihr mir eine gute Simulationssoftware für den AVR nennen? Möchte es einmal simulieren. Danke für die bisherigen Posts mfg saschisch
Warum beantwortest du die Frage nach dem avr-objcopy nicht mal? Ich könnte ja fast wetten, dass da der Pfeffer im Hasen liegt... Da kannst du simulatieren, wie du willst.
Ich benutze den avr-gcc als Compiler (WinAvr) und die Simulation mach ich mit dem AVR-Studio. Der WinAvr integriert sich dabei wunderbar ins AVR-Studio.
Ich tipp mal darauf, dass im Timing irgendwas faul ist. Vor allem, da die 'buisy' Funktion nicht, wie der Name verspricht, des LCD befragt ob es noch busy ist, sondern einfach nur ne zeitlang wartet. Warum benutzt Du nicht einfach die LCD Funktionen von Peter Fleury. Die sind quasi sowas wie Standard und funktionieren. http://jump.to/fleury
Hi! OK, danke ich werde das von FLeury probieren und hoffe dass das dann geht. MfG Saschisch
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.