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.