Forum: Compiler & IDEs EEPROM mit Bytetokens füllen + auslesen


von Thomas (Gast)


Lesenswert?

Halli hallo an Alle,

also ich experimentiere jetzt das erste Mal mit dem EEPROM von meinem
ATMega16. Um später mal einen Interpreter zu schreiben, dessen Code vom
PC aus in den EEPROM geladen werden soll, wollte ich einfach mal
anfangen ein paar Bytetokens in den EEPROM zu schreiben und mit einer
Schleife auslesen.Ungefähr so:

void main(void)
{
  SetPorts();
  USART_INIT(BAUD);
  Start=0;

  eeprom_write_byte( &eeprom_var1, 0x00 );EEPROM addr 0002
  eeprom_write_byte( &eeprom_var2, 0x01 );EEPROM addr 0003
  eeprom_write_byte( &eeprom_var3, 0x02 );EEPROM addr 0004

  for(;;)
  {
    int i=2;
    BYTE token;
    sbi(PORTB, LED);
    USART_Receive();

    if (Start=='1')
    {
    //for(i=2;i<5;i++) {

      token = eeprom_read_byte(i);
      switch (token) {
            case 0x00: // FUNKTION1 aufrufen
                funktion1();
                //break;
            case 0x01: // FUNKTION2 aufrufen
                funktion2();
                //break;
       case 0x02: // FUNKTION3 aufrufen
    funktion3();
    // break;
     default:  //   KONTROLLLED
                cbi(PORTB, LED);
    break;
        }
      //}
    }
    else
    {
      sbi(PORTB, LED);
    }

  }
}

Dabei sind folgende Fragen aufgetreten:

1.Kann man beim Flashen des µC gleich die Bytetokens in den EEPROM
schreiben? Habe mir das Beispiel dazu angesehen, was aber erst über
Variablen geht. Geht das irgendwie auch direkt?

2.Wieso treten alle Fälle ein, obwohl ich die Schleife mit der Adresse
auskommentiert habe?

3.Wie kann man solch eine Schleife am besten realsieren?

Vielen Dank für alle die sich bemühen,

Ciao Thomas

von Jörg Wunsch (Gast)


Lesenswert?

> 1.Kann man beim Flashen des µC gleich die Bytetokens in den EEPROM
> schreiben? Habe mir das Beispiel dazu angesehen, was aber erst über
> Variablen geht. Geht das irgendwie auch direkt?

Das hängt von Deiner Programmiersoftware ab, aber es können wohl alle.

Du mußt halt ein Ladefile für Deinen Programmer erzeugen (iHex, raw
binary, S-Record -- was immer Dein Programmer verträgt).

> 2.Wieso treten alle Fälle ein, obwohl ich die Schleife mit der
> Adresse auskommentiert habe?

Weil Du auch die breaks auskommentiert hast?

> 3.Wie kann man solch eine Schleife am besten realsieren?

uint16_t i, len;
uint8_t *ee_addr;

len = eeprom_read_word(0);
for (i = 0, ee_addr = 2; i < len; i++, ee_addr++)
  switch (eeprom_read_byte(ee_addr)) {
  case ... ;
  }

von Thomas (Gast)


Lesenswert?

Hi Jörg,

schön, dass Du Dich wieder mal meldest * freu

vielen Dank. Klar die Breaks müssen rein. Die Schleife habe ich auch
mal getestet und funktioniert auch supi. Doch kannst Du mir bitte mal
die Besonderheit der Adresse 0 des EEPROMs erklären?
Ich nehmen an Du benutzt sie, um die Länge der Daten zu bestimmen.Hab
das mal auch mal versucht:

eeprom_write_byte( &laenge,      0x0002 );

aber so kommen mehr als drei Schleifendurchgänge heraus.Wieso?

Das mit dem File ist mir im Prinzip klar, aber wie realsiert man das
denn? Ich benutze WINAVR auch zum programmieren.
Später will ich mal die Daten über die RS232 einlesen und in den EEPROM
speichern.Das müßte ja dann mit einem selbstgeschriebenen
Windowsprogramm gehen.

Danke nochmal,

Thomas

von Stefan Seegel (Gast)


Lesenswert?

Hallo Thomas!

Um den eeprom-Variablen gleich von vorneherein einen Wert zu verpassen
gibt's z.B. folgenden Weg:

signed char var1 _attribute_ ((section (".eeprom"))) = 10;
signed char var2 _attribute_ ((section (".eeprom"))) = 3;
signed char var3[] _attribute_ ((section (".eeprom"))) = {1, 2,
3};

Dann musst du noch in Deinem MakeFile folgende Zeile suchen:

#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep

und das # entfernen damit die Werte beim Programmieren des µC in den
eeprom geschrieben werden.

Hoffe ich konnte helfen.
Stefan

von Thomas (Gast)


Lesenswert?

Halli hallo,

@Stefan:
Vielen Dank Stefan! Ich glaube das hilft mir weiter. Und wird dabei die
erste Variable auch an die Adresse 0 und die zweite Variable an die
Adresse 1 usw. geschrieben?

@für alle:
Ich versuche dafür einen Ringpuffer anzulegen, der mir die ankommenden
Zeichen von der UART abspeichert.Dazu habe ich folgenden Text im Forum
gefunden:

*Am einfachsten arbeitet es sich mit einem Ringbuffer, sagen wir mal 8
*byte gross.
*Zur Verwaltung benutzt man 3 Register, einen Schreibpointer, einen
*Lesepointer und ein Zählregister (Anzahl der empfangenen Bytes).
*-Zeichen wird empfangen -> Rx-Int wird ausgelöst
*-das byte wird an der durch den Schreibpointer addressierten
*Speicherzelle abgelegt
*-der Schreibpointer wird erhöht und geprüft, ob dabei die max.Adresse
*überschritten wurde, wenn ja, auf die Anfangsadresse zurücksetzen
*-byte-Zähler erhöhen fertig.
*
*Gelesen wird, wenn Zeit dafür ist. Zuerst prüfen, ob der Counter > 0
*wenn ja:
*-ein byte aus der durch den Lesepointer adressierten Speicher holen
*-Lesepointer erhöhen, wenn > max_Adresse zurücksetzen
*-byte-Zähler erniedrigen

ich habe das versucht mal zu realsieren.Der Ringbuffer soll bei mir
gefüllt werden, wenn ein Interrupt von der Uart kommt. Wenn das erste
Zeichen einen bestimmten Wert hat(noch nicht realisiert), soll der
EEPROM mit der gleichen Folge von der UART geschrieben werden. Aber der
Compiler gibt immer Warungen aus, die ich nicht so recht verstehe.
*warning: passing arg 1 of `eeprom_write_byte' makes pointer from
*integer without a cast

Kann mit bitte jemand weiterhelfen????


BYTE rxbuffer[8];
BYTE buff_count;
uint8_t *write_buffer;
uint8_t *read_buffer;
uint8_t *max_buff;


void SetVariables(void)
{
  write_buffer=rxbuffer;
  read_buffer=rxbuffer;
  buff_count=0;
  max_buff=&rxbuffer[8];
}


SIGNAL(SIG_UART_RECV)
{
    *write_buffer = UDR;
    if (write_buffer<max_buff)
      write_buffer++;
    else
      write_buffer=rxbuffer;
    buff_count++;

}


void WriteEeprom (void)
{
while (buff_count) {
  eeprom_write_byte(buff_count,write_buffer);
  write_buffer--;
  buff_count--;
  }
}

von Stefan Seegel (Gast)


Lesenswert?

Hi Thomas!

>eeprom_write_byte(buff_count,write_buffer);

so wird das nix, der erste parameter dieser funktion muss eine Adresse
in den eeprom speicher sein, also z.B.

signed char var1 _attribute_ ((section (".eeprom"))) = 10;
.....
eeprom_write_byte(&var1, 73);

mit arrays sieht das ganze dann so aus:

signed char vararray[] _attribute_ ((section (".eeprom"))) = {10,
12, 13};
.....
eeprom_write_byte(&vararray[0], 73);

MfG
Stefan

von Thomas (Gast)


Lesenswert?

@Stefan:

habs gerade mal versucht zu testen, aber da stimmt was noch nicht:

for(i=0;i<3;i++) {
   switch (eeprom_read_byte(&vararray[i])) {

ich will der Wert an stelle i auslesen und dann mit switch schauen, ob
ein Fall eingetroffen ist. Leider springt er immer auf default :-(( und
nichts passiert? Hast Du ne Ahnung wieso?

von Stefan Seegel (Gast)


Lesenswert?

Tach,

wurde das Eeprom auch wirklich beschrieben, also steht was drin? Am
besten mal mit Ponyprog oder so den eeprom auslesen und kucken.
Damit der avrdude den eeprom beim flashen mit beschreibt musst du die
oben genannte Zeile im makefile noch editieren (das # weg).

Vom Code her müssts denk ich theoretisch passen wie ich das sehe...

Stefan

von Thomas (Gast)


Lesenswert?

Hi,

also ich habe die Raute im Makefile entfernt, aber ich habe es bis
jetzt nur im Simulator getestet und der springt in die Zeile:

switch (eeprom_read_byte(&vararray[i]))

und dann sollte beispielsweise ne 1 an dieser Stelle im Array stehen,
damit dann dieser Fall eintreten kann

case '1' function_xy();

aber stattdessen springt es immer zu

default (tue nichts)

Verstehste??

Also irgendwie haut die Syntax von eeprom_read_byte nicht hin.

So ganz habe ich es eh noch nicht verstanden, wie das Adressargument
aussehen muss. Muss es ein Pointer sein oder ein Wert eines Pointers
oder nur ein int Wert. Habe leider keine Beispiele dazu gefunden :-(

Kannste mir da vielleicht weiterhelfen, dass könnte mich insgesamt auch
weiterbringen.

ahoi thomas

von OldBug (Gast)


Lesenswert?

So weit ich weis kann man im Simulator keine EEPROM-Zugriffe Simulieren
(das setzen der Registern schon, schreiben und rücklesen der Daten
allerdings nicht)...

von Thomas (Gast)


Lesenswert?

Hi Stefan,

jetzt funzt es! ich habe ausversehen das Makefile von einem anderen
file geändert. so das der eeprom wirklich nicht beschrieben wurde. aber
jetzt haut alles hin. Nun muss ich nur noch mal sehen, wie ich es
schaffe, die ankommenden Daten von der RS232 in einen Ringpuffer zu
schreiben, welcher dann in den EEProm übertragen wird. Meine Idee dazu
habe ich ja weiter oben schon einmal gepostet.

Vielen Dank Stefan...

Ciao Thomas

von Gottfried Bremer (Gast)


Lesenswert?

Hi Stefan
Du schriebst:
*mit arrays sieht das ganze dann so aus:
*
*signed char vararray[] _attribute_ ((section (".eeprom"))) = {10,
*12, 13};

Ist das auch der einfachste Weg, wenn man das ganze EEPROM mit
Messwerten vollschreiben will(eine ewig lange Definition eines
Arrays)?
oder geht auch was in der Art von
signed char vararray[] _attribute_ ((section (".eeprom"))) =
{0..511};
oder kann man sonst irgendwie einen Adresszeiger in einer Schleife über
das ganze EEPROM laufen lassen?

von Stefan Seegel (Gast)


Lesenswert?

Hi Thomas!

Die Werte in den {} Klammern brauchst du nur wenn du den Inhalt des
eeproms "vorbeschrieben" haben willst... Du kannst natürlich einfach
schreiben

signed char vararray[512] _attribute_ ((section (".eeprom")));


nachdem du ja den eeprom eh als Ringbuffer verwenden willst brauchst du
ja keine vorgegeben Werte nach dem flashen im eeprom stehen haben... Das
ist eher sinnvoll wenn man eine Grundkonfiguration im eeprm ablegen
möchte.

MfG
Stefan

von Thomas (Gast)


Lesenswert?

Hi Stefan,

danke nochmals für Deine Antwort. Zu Testzwecken habe ich den EEProm,
mit meiner Grundkonfiguration gleich beim Flashen, beschrieben. Später
soll allerdings die Grundkonfiguration mal über die RS232 in den EEProm
gelangen. Um diese Daten ordentlich von der Uart zu empfangen, dachte
ich mir, ein Ringbuffer wäre ganz gut. Wenn die Daten dann einmal im
Ringbuffer sind, schreibe ich sie in den EEProm. Ich weiß nicht, ob es
auch möglich ist, die Daten die von der Uart kommen, gleich in den
EEProm zu schreiben. Meinst Du das geht, ohne  das man dabei Daten
verliert?

danke Thomas

von Gottfried Bremer (Gast)


Lesenswert?

Beim Mega8 steht als "Typ Programming Time" für das EEPROM 8,5ms. Bis
ca. 800 baud sollte das gehen. Ansonsten musst du beim Senden noch eine
extra Pause einbauen.

von Stefan Seegel (Gast)


Lesenswert?

@Uli:

Habe eben versucht eine MMC an einem ATMega16 anzuschließen, aber
leider bleibt das Programm in der Init-Routine stecken. Wie ist das mit
den PIN Definitionen, wieso gibts 5 ? Hab ja nur 4 Leitungen...
Für meinen Mega 16 habe ich das ganze wie folgt gesetzt:

#define SPI_DI  PB6    //Port Pin an dem Data Output...
#define SPI_DO  PB5    //Port Pin an dem Data Input...
#define SPI_Clock  PB7    //Port Pin an dem die Clock...
#define MMC_Chip_Select  PB4   //Port Pin an dem Chip Select...
#define SPI_SS PB4

Stimmt das so ?

MfG
Stefan

P.S. Kennt jemand ein IC in dem 3.3V/5V Level-Shifter drin sind ? Das
mit den Widerständen ist mir nicht so ganz sympatisch...

von Jörg Wunsch (Gast)


Lesenswert?

Fang mal einen neuen Thread an.

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.