Forum: Compiler & IDEs Speichermanagement


von saschisch (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Zeig doch mal etwas Code.
Das Problem ist mit 100% Sicherheit irgendwo in Deinem
Code zu suchen und nicht im Mega oder im Compiler.

von saschisch (Gast)


Lesenswert?

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

von Nico S. (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von saschisch (Gast)


Lesenswert?

@KArl Heinz Buchegger

Was kann ich denn dan machen?

von Karl H. (kbuchegg)


Lesenswert?

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).

von saschisch (Gast)


Lesenswert?

Naja ok trotzdem danke

WEnn ich das PRoblem gelöst habe schreibe ich dir wie es funktioniert
hat

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

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

von ich (Gast)


Lesenswert?

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).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wie sieht dein avr-objcopy aus, mit dem du das Hexfile
erzeugst?

von saschisch (Gast)


Lesenswert?

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

von Stephan (Gast)


Lesenswert?

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.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

nö. Der Compiler ermittelt aus der Länge des Strings die nötige Größe
des Arrays automatisch.

Matthias

von Birger* (Gast)


Lesenswert?

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.

von Ingo (Gast)


Lesenswert?

@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?

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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.

von saschisch (Gast)


Lesenswert?

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

von ich (Gast)


Lesenswert?

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.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von saschisch (Gast)


Lesenswert?

@ 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

von Karl H. (kbuchegg)


Lesenswert?

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.

von saschisch (Gast)


Lesenswert?

"Drucken" ist eine Verzweiflungfunktion^^ um das Ding endlich zum
laufen zu bringen. Diese haben wir nachträglich dazugegeben.

Wird also nicht mehr verwendet.

von saschisch (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von saschisch (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.