Forum: Mikrocontroller und Digitale Elektronik Strings aus int. EEPROM lesen >Pointer<


von rene (Gast)


Lesenswert?

bei meinem Programm ist es nötig die Textdaten aus dem interenen EEPROM 
meines MEGA8535 auzulesen.

Ich schreib in C mit ICC die Daten folgendermaßen in das EEPROM:

#pragma data:eeprom

 char ms11[20] ="Zeile 1 weiter mit A";
 char ms12[20] ="Zeile 1 weiter mit B";

#pragma data:data

               in meinen Routinen rrufe ich dan

lcd_line(*ms11);

               auf um damit dies abzuarbeiten


void lcd_line(char *adr)
 {
 u08 zeichen;
 u08 x;
 for ( x=1; x<19 ; x++ )
  {
  zeichen = read_eep(0,(*adr+x)); // übergabe des Hig und Lowbytes
  if (( zeichen != 0))
   { // noch keine String-End marke erkannt
   lcd_char(zeichen);
   }
  else
   {
   x=21; // Aussprung bei Stringende
   }
  }
 }


Auf dem LCD erscheint dann:

 in Zeile 1 "weiter mit A        "
und Zeile 2 "el  etrmtAZie2WIE   "

gibt es was besonderes beim Auslesen des EEPROM´s was ich hier falsch 
mache, oder bin ich für das EEPROM nutzen zu doof ;-((

rene

von Karl H. (kbuchegg)


Lesenswert?

rene wrote:
> gibt es was besonderes beim Auslesen des EEPROM´s was ich hier falsch
> mache, oder bin ich für das EEPROM nutzen zu doof ;-((

Fürs EEPROM nicht, aber für Stringbehandlung in C :-)
(du hast es herausgefordert)

char ms11[20] ="Zeile 1 weiter mit A";

Dieser String hat keine 20 Zeichen, sondern 21
(Du hast das abschliessende '\0' Zeichen vergessen)

Lass doch den Compiler das Zeugs abzählen, der macht das
zuverlässiger als du:

char ms11[] ="Zeile 1 weiter mit A";

-----

 for ( x=1; x<19 ; x++ )
  {
  zeichen = read_eep(0,(*adr+x)); // übergabe des Hig und Lowbytes
  if (( zeichen != 0))

String Inidizierung beginnt in C, genauso wie
Arrayindizierung (da Strings ja nichts anderes als
Arrays sind) mit 0 und nicht mit 1.

Ausserdem: Warum zählst du da mit? Jeder String endet
in C mit einem '\0' Zeichen. Das ist dein Aufhänger
für die Schleife:

  x = 0;
  do {
     zeichen = read_eep(0,(*adr+x)); // übergabe des Hig und Lowbytes
     if( zeichen != '\0' ) {
       ...
     }
     x++;
  } while( zeichen != '\0' );


Den Mambo Zambo, den du da mit den Pointer aufführst
versteh ich nicht. Liegt aber wohl daran, dass ich nicht
weiss wie dein Compiler Pointer ins EEPROM behandelt.

von rene (Gast)


Lesenswert?

Hallo kbuchegg

wie so Mombo zambo mit Pointern... Geht das den einfacher ist bin für 
alles was einfacher geht offen.

Mit deinem Sourcevorschlag, ging nicht so ganz ;-|

habe nun noch mehr "Müll" auf dem LCD....

mit der Suche im Forum bin ich bis dato auch nicht viel weiter gekommen.

Ich weiß nicht mehr weiter...


was meinst Du mit .....
>String Inidizierung beginnt in C, genauso wie
>Arrayindizierung (da Strings ja nichts anderes als
>Arrays sind) mit 0 und nicht mit 1.


sind Die anfänge von Strings im EEPROM auch markiert?? mein EEPROM sieht 
in Ponyprog ganz normal aus.
zwar ist die erste zelle leer (0xff), aber dan kommen auch gleich die 
Daten.

rene

von Karl H. (kbuchegg)


Lesenswert?

rene wrote:
> Hallo kbuchegg
>
> wie so Mombo zambo mit Pointern... Geht das den einfacher ist bin für
> alles was einfacher geht offen.
>

Es geht um das hier:
1
lcd_line(*ms11);
2
3
               auf um damit dies abzuarbeiten
4
5
6
void lcd_line(char *adr)
7
 {
8
 u08 zeichen;
9
 u08 x;
10
 for ( x=1; x<19 ; x++ )
11
  {
12
  zeichen = read_eep(0,(*adr+x)); // übergabe des

lcd_line kriegt die Adresse eines Strings. Dieser
String steht im EEPROM.
Nur: Warum wird dann die Funktion so aufgerufen:

lcd_line(*ms11);

In normalem C ergibt *ms11 den ersten Charcater der in
ms11 gespeichert wurde.

Das passt alles nicht richtig zusammen, es sei denn auf
deinem System werden Pointer ins EEPROM speziell behandelt.
Das weiss ich aber nicht.

  zeichen = read_eep(0,(*adr+x)); // übergabe

Das kommt mir auch etwas Spanisch vor.
Eine Funktion wie read_eep müsste doch eigentlich
die Adresse kriegen von der sie lesen soll.
Wenn adr jetzt aber bereits die Adresse im Speicher
ist, von der gelesen werden soll, wieso wird dann
der Pointer dereferenziert?

> Mit deinem Sourcevorschlag, ging nicht so ganz ;-|

Das kann ich mir vorstellen. Deine Pointerverrenkungen
in diesem Code sind so nicht durchschaubar.

>
> habe nun noch mehr "Müll" auf dem LCD....

Auch das glaub ich. Meiner Meinung nach stopfst du
alles mögliche in die read_eep Funktion hinein, nur
nicht die Speicheradresse von der read_eep lesen soll.

> was meinst Du mit .....
>>String Inidizierung beginnt in C, genauso wie
>>Arrayindizierung (da Strings ja nichts anderes als
>>Arrays sind) mit 0 und nicht mit 1.
>
>
> sind Die anfänge von Strings im EEPROM auch markiert?? mein EEPROM sieht
> in Ponyprog ganz normal aus.
> zwar ist die erste zelle leer (0xff), aber dan kommen auch gleich die
> Daten.

Und. Wen kümmerst.
Der Compiler gibt dir die Adresse an der der String anfängt in
ms11. Von dort beginnt der String. Und er endet mit einem '\0'
Byte. Wo auch immer das im EEPROM Speicher sein mag.

Du übergibst diese Adresse an die Funktion lcd_line

  ....
  lcd_line(ms11);
  ...

Die Funktion lcd_line holt sich diese Adresse

void lcd_line( char* adr )

und benutzt sie um mittels read_eep genau von dieser
Stelle ein Zeichen zu holen

   read_eep( 0, adr );

(was macht der 0 hier als erstes Funktionsargument? Ich kenne
die Funktion read_eep nicht)

von rene (Gast)


Lesenswert?

Danke für die Antwort... hat mir viel neues gelernt...

read_eep(0,xx);

Ist eine eigene Funktion, mit der ich eine Adresse im High und Lowbyte 
übergebe, den diese muss ja auch bei aufruf getrennt dem System 
übergeben werden.

Werde mir die genannten Themen mal genauer anschauen und es noch mal 
versuchen..... Danke erst mal für die Ausführliche Erklärung.

rene

von Karl H. (kbuchegg)


Lesenswert?

rene wrote:
> Danke für die Antwort... hat mir viel neues gelernt...
>
> read_eep(0,xx);
>
> Ist eine eigene Funktion, mit der ich eine Adresse im High und Lowbyte
> übergebe, den diese muss ja auch bei aufruf getrennt dem System
> übergeben werden.

Alles klar.

Ich hab mir das auf dem Heimweg noch mal durch den Kopf gehen lassen.

(Ich rate jetzt ein bischen, da ich wie gesagt nicht sicher
bin, wie dein Compiler mit Pointern im EEPROM umgeht. Ich geh
halt davon aus, wie ich als Compilerbauer das machen würde).

Meiner Ansicht nach, müsste die Funktion so aussehen:
1
void lcd_line(char *adr)
2
{
3
  u08 zeichen;
4
5
  while( ( zeichen = read_eep( adr >> 8, adr & 0xFF ) ) != '\0' )
6
  {
7
    lcd_char(zeichen);
8
    adr++;
9
  }
10
}

und aufgerufen wird das
1
#pragma data:eeprom
2
3
 char ms11[] = "Zeile 1 weiter mit A";
4
 char ms12[] = "Zeile 1 weiter mit B";
5
6
#pragma data:data
7
8
int main()
9
{
10
   ...
11
12
   lcd_line( ms11 );
13
   lcd_line( ms12 );
14
}

  

von rene (Gast)


Lesenswert?

hi kbuchegg,
Das sieht ja super aus und auch kompakt...aber

bei der Zeile:

  while( ( zeichen = read_eep( adr >> 8, adr & 0xFF ) ) != '\0' )

kommt folgendes als Meldung vom Compiler

(50): operands of >> have illegal types `pointer to char' and `int'
(50): operands of & have illegal types `pointer to char' and `int'

woher kommt das `int' soll das vieleicht die 8 und das 0xff sein. Diese 
habe ich aber nicht als solche Def. Oder übersehe ich hier noch was

rene

von Karl H. (kbuchegg)


Lesenswert?

rene wrote:
> hi kbuchegg,
> Das sieht ja super aus und auch kompakt...aber
>
> bei der Zeile:
>
>   while( ( zeichen = read_eep( adr >> 8, adr & 0xFF ) ) != '\0' )
>
> kommt folgendes als Meldung vom Compiler
>
> (50): operands of >> have illegal types `pointer to char' and `int'
> (50): operands of & have illegal types `pointer to char' and `int'
>

Ich dachte mir schon, dass da ein cast notwendig sein wird :-)

> woher kommt das `int' soll das vieleicht die 8 und das 0xff sein.

Exakt.
adr ist ein pointer to char
und das  adr >> 8  passt ihm nicht.

Am besten wäre es, wenn du das Aufteilen der Adresse in
ein High Byte und ein Low Byte überhaupt in die Funktion
verlagern würdest.

Dann würde die Funktion so aussehen:

char read_eep( char* Addr )
{
  u08 HighByte = (u08)(((u16)Addr) >> 8);
  u08 LowByte  = (u08)(((u16)Addr) & 0xFF );

  ...
  weitermachen mit LowByte, Highbyte
}

Sieht ein bischen wild aus. Die Idee dahinter ist es,
aus dem Pointer einen unsigned int zu machen. Damit
kann ich dann Bitschieben soviel ich will.

Dafür wird dann allerdings der Aufruf viel einfacher:

   while( ( zeichen = read_eep( adr ) ) != '\0' )

und das ist schliesslich das entscheidende: Das eine
Funktion ein Interface zur Verfügung stellt, dass einfach
zu benutzen ist. Und noch einfacher als einfach eine
Adresse hineinstopfen geht wohl kaum :-)


von rene (Gast)


Lesenswert?

bin noch nicht zum Testen gekommen, werde es noch machen und dan 
berichten, aber erst mal vielen Dank für die Müh...

rene

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.