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


von Hannes E. (k1ngarthur) Benutzerseite


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
1
// Menü-Struktur
2
struct menueP{
3
4
  char *name;
5
  
6
  void (*func)(uint8_t);  
7
  uint8_t fdata;
8
9
  struct menueP *prev;
10
  struct menueP *next;
11
  struct menueP *parent;
12
  struct menueP *child;
13
14
};
15
16
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).
1
// Neuen Menüpunkt anlegen
2
void new_menueP(char *name, struct menueP* tmp, void (*fu)(uint8_t), uint8_t fud )
3
{
4
5
  // Erstellt einen neuen Menüpunkt
6
7
  tmp -> name = name;
8
  tmp -> func = fu;
9
  tmp -> parent = 0;
10
  tmp -> child = 0;
11
  tmp -> fdata = fud;
12
13
  return;
14
15
}
16
17
// Erstellung der Menüstruktur
18
void init_menue( void )
19
{
20
21
  // Erstellt die Menüstruktur
22
23
  // -----------------------------
24
  new_menueP("01 Zeit/Datum", &m1, NULL, 0);
25
  new_menueP("02 Wecker", &m2, NULL, 0);
26
  new_menueP("03 Farbe", &m3, NULL, 0);
27
  new_menueP("04 Musik", &m4, NULL, 0);
28
29
  m1.next = m3.prev = &m2;
30
  m2.next = m4.prev = &m3;
31
  m3.next = m1.prev = &m4;
32
  m4.next = m2.prev = &m1;
33
34
  // -----------------------------
35
36
  // -----------------------------
37
  new_menueP("11 Zeit", &m11, &m_time, 0);
38
  new_menueP("12 Datum", &m12, &m_date, 0);
39
  new_menueP("13 Geburtstag", &m13, &m_birthday, 0);
40
41
  m11.prev = m12.next = &m13;
42
  m12.prev = m13.next = &m11;
43
  m13.prev = m11.next = &m12;
44
45
  m11.parent = m12.parent = &m1;
46
47
  m1.child = &m11;
48
  // -----------------------------
49
  
50
  // -----------------------------
51
  new_menueP("21 Weckzeit", &m21, &m_time, 1 );
52
  new_menueP("22 Weckmusik", &m22, &m_al_music, 0 );
53
  new_menueP("23 Snoozezeit", &m23, &m_set_snooze, 0 );
54
55
  m21.next = m23.prev = &m22;
56
  m22.next = m21.prev = &m23;
57
  m23.next = m22.prev = &m21;
58
59
  m21.parent = m22.parent = m23.parent = &m2;
60
61
  m2.child = &m21;
62
  // -----------------------------
63
64
  // -----------------------------
65
  new_menueP("31 Farbe setzen", &m31, &m_color, 0);
66
  new_menueP("32 Farbwechsel", &m32, &m_color_switch_mode, 0);
67
  new_menueP("33 Weckfarbe", &m33, &m_color, 1);
68
  new_menueP("34 WeFarbWechs.", &m34, &m_color_switch_mode, 1);
69
  new_menueP("35 Helligkeit", &m35, &m_color_brightness, 0);
70
  new_menueP("36 WeHelligkeit", &m36, &m_color_brightness, 1);
71
72
  m31.next = m33.prev = &m32,
73
  m32.next = m34.prev = &m33;
74
  m33.next = m35.prev = &m34;
75
  m34.next = m36.prev = &m35;
76
  m35.next = m31.prev = &m36;
77
  m36.next = m32.prev = &m31;
78
79
  m31.parent = m32.parent = m33.parent = m34.parent = m35.parent = m36.parent = &m3;
80
81
  m3.child = &m31;
82
  // -----------------------------
83
  
84
  // -----------------------------
85
  new_menueP("41 MP3-Player", &m41, &m_player, 0);
86
  new_menueP("42 Laustaerke", &m42, &m_player_vol, 0);
87
88
  m41.next = m41.prev = &m42;
89
  m42.next = m42.prev = &m41;
90
91
  m41.parent = m42.parent = &m4;
92
93
  m4.child = &m41;
94
  // -----------------------------
95
96
  return;
97
98
}

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:
1
// Funktionen für die Menünavigation
2
void menue(struct menueP *tmp)
3
{
4
5
  void (*function)(uint8_t);
6
  uint8_t keybrd;
7
8
  deact_tmr();              // alle Timer aus
9
10
  lcd_bg( 1 );              // Displaybeleuchtung an
11
  lcd_bg_time = 1;            // beleuchtung dauernd an
12
13
  while( tmp ){
14
15
    // -- Innerhalb des Menüs
16
17
    // Funktion zuordnen
18
    function = tmp -> func;
19
20
    // Tastaturpuffer löschen
21
    keybrd = 0x00;
22
23
    
24
    // Anzeigen des Menüpunktes    
25
    lcd_clear();              // Display löschen
26
27
    while( !(keybrd) ){
28
29
      if( _KEYBRD ) _keybrd(&keybrd);    // Tastatur abfragen
30
31
      lcd_string(tmp -> name);        // Menüpunkt-Namen anzeigen
32
33
      // Symbol anzeigen
34
      lcd_setcursor(7,2);
35
      lcd_string(">");
36
37
      // ggf.Funktion aufrufen
38
      if( (keybrd & BTN_ENTER) && *function ){
39
        
40
        // Display löschen
41
        lcd_clear();
42
43
        // Tastaturpuffer löschen
44
        keybrd = 0x00;
45
46
        // Funktion aufrufen
47
        (*function)(tmp -> fdata);
48
49
        // Tastaturpuffer löschen
50
        keybrd = 0x00;  
51
        
52
        // Display löschen
53
        lcd_clear();    
54
55
      }
56
57
      // Warten auf Benutzereingabe
58
      if( (keybrd & BTN_MENUE) ) tmp = tmp -> parent;          // nach oben
59
      if( (keybrd & BTN_ENTER) && !function ) tmp = tmp -> child;    // nach unten
60
      if( (keybrd & BTN_UP) ) tmp = tmp -> prev;            // zurück
61
      if( (keybrd & BTN_DOWN) ) tmp = tmp -> next;          // vorwärts
62
63
      _delay_ms(100);
64
65
    }
66
67
  }
68
69
  lcd_clear();    // Display löschen
70
  act_int();       // alle Timer wieder an
71
72
  flash_time = 0;    // Alarmflag aus  
73
  lcd_bg_time = 0;  // LCD Hintergrundbeleuchtung aus
74
75
  _delay_ms(100);
76
77
}

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?

von Schorsch (Gast)


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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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

von Hannes E. (k1ngarthur) Benutzerseite


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?

von Hannes E. (k1ngarthur) Benutzerseite


Lesenswert?

> Passiert dann beim Drücken einer Taste immer das selbe?
Ja.

von Karl H. (kbuchegg)


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-Tutorial#Programmspeicher_.28Flash.29

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

Das genaue Gegenteil ist der Fall.
Das entlastet dein RAM

von Hannes E. (k1ngarthur) Benutzerseite


Lesenswert?

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

Werde das mal ausprobieren.

von Hannes E. (k1ngarthur) Benutzerseite


Lesenswert?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29
Hat funktioniert. Bin jetzt mit den zusätzlichen Menüpunkten bei 71% 
Data 55% Programm.

Vielen Dank für die schnelle Hilfe!

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.