www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Bugs bei 98% Data und 60% Programm


Autor: Hannes E. (k1ngarthur) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einen etwas kuriosen Fehler.
Ich habe ein etwas umfangreicheres projekt, welches unter anderem ein 
menü enthält.
Um das Menü dynamischer zu machen, wird für jeden Menüpunkt eine 
Variable mit der Struktur
// Menü-Struktur
struct menueP{

  char *name;
  
  void (*func)(uint8_t);  
  uint8_t fdata;

  struct menueP *prev;
  struct menueP *next;
  struct menueP *parent;
  struct menueP *child;

};

struct menueP m1, m2, m3, m4, m5, m11, m12, m13, m21, m22, m23, m31, m32, m33, m34, m35, m36, m41, m42, m51m, m52;
erstellt.

Die Menüpunkte werden zur Laufzeit erstellt (also de Werte zugewiesen).
// Neuen Menüpunkt anlegen
void new_menueP(char *name, struct menueP* tmp, void (*fu)(uint8_t), uint8_t fud )
{

  // Erstellt einen neuen Menüpunkt

  tmp -> name = name;
  tmp -> func = fu;
  tmp -> parent = 0;
  tmp -> child = 0;
  tmp -> fdata = fud;

  return;

}

// Erstellung der Menüstruktur
void init_menue( void )
{

  // Erstellt die Menüstruktur

  // -----------------------------
  new_menueP("01 Zeit/Datum", &m1, NULL, 0);
  new_menueP("02 Wecker", &m2, NULL, 0);
  new_menueP("03 Farbe", &m3, NULL, 0);
  new_menueP("04 Musik", &m4, NULL, 0);

  m1.next = m3.prev = &m2;
  m2.next = m4.prev = &m3;
  m3.next = m1.prev = &m4;
  m4.next = m2.prev = &m1;

  // -----------------------------

  // -----------------------------
  new_menueP("11 Zeit", &m11, &m_time, 0);
  new_menueP("12 Datum", &m12, &m_date, 0);
  new_menueP("13 Geburtstag", &m13, &m_birthday, 0);

  m11.prev = m12.next = &m13;
  m12.prev = m13.next = &m11;
  m13.prev = m11.next = &m12;

  m11.parent = m12.parent = &m1;

  m1.child = &m11;
  // -----------------------------
  
  // -----------------------------
  new_menueP("21 Weckzeit", &m21, &m_time, 1 );
  new_menueP("22 Weckmusik", &m22, &m_al_music, 0 );
  new_menueP("23 Snoozezeit", &m23, &m_set_snooze, 0 );

  m21.next = m23.prev = &m22;
  m22.next = m21.prev = &m23;
  m23.next = m22.prev = &m21;

  m21.parent = m22.parent = m23.parent = &m2;

  m2.child = &m21;
  // -----------------------------

  // -----------------------------
  new_menueP("31 Farbe setzen", &m31, &m_color, 0);
  new_menueP("32 Farbwechsel", &m32, &m_color_switch_mode, 0);
  new_menueP("33 Weckfarbe", &m33, &m_color, 1);
  new_menueP("34 WeFarbWechs.", &m34, &m_color_switch_mode, 1);
  new_menueP("35 Helligkeit", &m35, &m_color_brightness, 0);
  new_menueP("36 WeHelligkeit", &m36, &m_color_brightness, 1);

  m31.next = m33.prev = &m32,
  m32.next = m34.prev = &m33;
  m33.next = m35.prev = &m34;
  m34.next = m36.prev = &m35;
  m35.next = m31.prev = &m36;
  m36.next = m32.prev = &m31;

  m31.parent = m32.parent = m33.parent = m34.parent = m35.parent = m36.parent = &m3;

  m3.child = &m31;
  // -----------------------------
  
  // -----------------------------
  new_menueP("41 MP3-Player", &m41, &m_player, 0);
  new_menueP("42 Laustaerke", &m42, &m_player_vol, 0);

  m41.next = m41.prev = &m42;
  m42.next = m42.prev = &m41;

  m41.parent = m42.parent = &m4;

  m4.child = &m41;
  // -----------------------------

  return;

}

Meine Menüfunktion wechselt dann entsprechend der Eingabe zum vorherigen 
(prev), nächsten (next) darunterliegenden (child) oder darüberliegenden 
(parent) Menüpunkt, bzw. ruft, falls vorhanden die entsprechende 
Menüfunktion (z.B. Einstellungen vornehmen) auf.

Menüfunktion:
// Funktionen für die Menünavigation
void menue(struct menueP *tmp)
{

  void (*function)(uint8_t);
  uint8_t keybrd;

  deact_tmr();              // alle Timer aus

  lcd_bg( 1 );              // Displaybeleuchtung an
  lcd_bg_time = 1;            // beleuchtung dauernd an

  while( tmp ){

    // -- Innerhalb des Menüs

    // Funktion zuordnen
    function = tmp -> func;

    // Tastaturpuffer löschen
    keybrd = 0x00;

    
    // Anzeigen des Menüpunktes    
    lcd_clear();              // Display löschen

    while( !(keybrd) ){

      if( _KEYBRD ) _keybrd(&keybrd);    // Tastatur abfragen

      lcd_string(tmp -> name);        // Menüpunkt-Namen anzeigen

      // Symbol anzeigen
      lcd_setcursor(7,2);
      lcd_string(">");

      // ggf.Funktion aufrufen
      if( (keybrd & BTN_ENTER) && *function ){
        
        // Display löschen
        lcd_clear();

        // Tastaturpuffer löschen
        keybrd = 0x00;

        // Funktion aufrufen
        (*function)(tmp -> fdata);

        // Tastaturpuffer löschen
        keybrd = 0x00;  
        
        // Display löschen
        lcd_clear();    

      }

      // Warten auf Benutzereingabe
      if( (keybrd & BTN_MENUE) ) tmp = tmp -> parent;          // nach oben
      if( (keybrd & BTN_ENTER) && !function ) tmp = tmp -> child;    // nach unten
      if( (keybrd & BTN_UP) ) tmp = tmp -> prev;            // zurück
      if( (keybrd & BTN_DOWN) ) tmp = tmp -> next;          // vorwärts

      _delay_ms(100);

    }

  }

  lcd_clear();    // Display löschen
  act_int();       // alle Timer wieder an

  flash_time = 0;    // Alarmflag aus  
  lcd_bg_time = 0;  // LCD Hintergrundbeleuchtung aus

  _delay_ms(100);

}

Das Funktioniert auch einwandfrei.

Füge ich jetzt aber einen weiteren mMenüunkt '05' mit zwei Unterpunkten 
hinzu, über die Einstellungen im EEPROM gespeichert bzw. aus dem EEPROM 
geladen werden sollen, erscheinen beim Wechsel von Punkt 02 zu 03 oder 
von 04 zu 03 nur kryptische Zeichen auf dem Display und eine Steuerung 
ist nicht möglich.
Teilweise wird beim Drücken der Menütasten dann auch meine Startfunktion 
(die alles initialisiert) aufgerufen, was sonst nur in der main() vor 
meiner while(1){...}-Schleife (aus der wird das Menü aufgerufen) 
geschieht.

Der Datnespeicher ist dann auch bei 98% und der Programmspeicher bei 60%
Der Menüpunkt '05' funktioniert einwandfrei.

Ich vermute, dass die Variable für Menüpunkt 03 irgendwo am Ende des 
RAMs liegt und die Speicherzelle nicht richtig beschreibbar ist (ev. ist 
dort der Bootloader?).



Kann mir jemand helfen, dieses Problem zu lösen?

Autor: Schorsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für den Fall dass sich deine Frage auf einen AVR bezog:

Verschieb erstmal alle Strings in den Flash. Momentan hast du alle 
Strings doppelt: Einmal im Flash als initialisierungs-Wert, einmal im 
RAM.

http://avr-libc.nongnu.org/user-manual/group__avr_...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes E. schrieb:
> Teilweise wird beim Drücken der Menütasten dann auch meine Startfunktion
> (die alles initialisiert) aufgerufen,
Passiert dann beim Drücken einer Taste immer das selbe?
Oder jedesmal was anderes?

> Ich vermute, dass die Variable für Menüpunkt 03 irgendwo am Ende des
> RAMs liegt und die Speicherzelle nicht richtig beschreibbar ist
Der Stack braucht auch noch Platz im Datenspeicher...

Autor: Hannes E. (k1ngarthur) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Würde es dazu nicht genügen Variabeln mit den Strings als Wert zu 
initialisieren?
Durch die Seite (hinterm Link) steige ich noch nicht ganz durch.

Das bläst meinen RAM doch nur noch mehr auf oder?

Autor: Hannes E. (k1ngarthur) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Passiert dann beim Drücken einer Taste immer das selbe?
Ja.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes E. schrieb:
> Würde es dazu nicht genügen Variabeln mit den Strings als Wert zu
> initialisieren?

Nein.
Im Moment machst du dir dein SRAM mit Texten dicht, die eigentlich kein 
Mensch im SRAM braucht.

> Durch die Seite (hinterm Link) steige ich noch nicht ganz durch.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

> Das bläst meinen RAM doch nur noch mehr auf oder?

Das genaue Gegenteil ist der Fall.
Das entlastet dein RAM

Autor: Hannes E. (k1ngarthur) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das genaue Gegenteil ist der Fall.
> Das entlastet dein RAM
ja, ist mir jetzt auch klar geworden.

Werde das mal ausprobieren.

Autor: Hannes E. (k1ngarthur) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
Hat funktioniert. Bin jetzt mit den zusätzlichen Menüpunkten bei 71% 
Data 55% Programm.

Vielen Dank für die schnelle Hilfe!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.