PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit return



dreadbrain
12.07.2009, 19:45
Hallo,
ich bin dabei meine ersten größeren Programme in C zu schreiben.

Derzeit möchte ich eine Steuerung für eine Heizung programmieren.

Zur Tasterentprellung habe ich die Routine aus dem mikrocontroller.net genommen.(habe ich im Code-Tag entfernt).

Die Definitionen sind in einer Datei ausgelagert(define.c).

Jetz habe ich das Problem, wenn ich eine Funktion(menue_auswahl)aus main heraus aufrufe, und durch ein return wieder zurück will, das mir der Controller einen Reset macht.


#include <avr/io.h>
#include <stdlib.h>
#include <lcd.h>
#include <string.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <define.c>
#include <avr/pgmspace.h>

// hier stünde normal die Tastenentprellungsroutine (die hat
//in vorherigen Programmen auch schon super funktioniert
//und es wurde nichst daran geändert.


void menue_auswahl(uint8_t m_auswahl_page);
//################################################## #####################################
//################################################## ###################################

void init_controller(void)
{
DDRA = 0b00000011; // PORTA als Ausgang
DDRC = 0xFF; // PORTC 0 Ausgang
DDRB = 0x00; // PORTB = Eingang
PORTB = 0xFF;

TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024
TIMSK = 1<<TOIE0; // enable timer interrupt
// Pullups aktiviert

lcd_init(LCD_DISP_ON);

lcd_puts_p(PSTR("Steuerung1.0"));
_delay_ms(1000);
lcd_clrscr();
startup ++;
return;
}

int main(void)
{
if (startup<1)
{
init_controller();
}
while(1) //Hauptprogrammschleife/Startseite
{

if ( get_key_short( 1<<KEY0 ))
{
menue_auswahl(1);
}

lcd_gotoxy(0, 0);
lcd_puts_p(PSTR("Brauchwasser: 42ßC"));
lcd_gotoxy(10,2);
lcd_puts("MENUE");
lcd_gotoxy(0,2);
lcd_puts("OK");



}
return(0);

}
//################################################## ######################################
//################################################## #########################################
//AuswahlMenü Ebene1
//################################################## #####################################
void menue_auswahl(uint8_t m_auswahl_page)
{
char zeile1_m_auswahl[12];

lcd_clrscr();
while(1)
{
switch (m_auswahl_page)
{
case 1: strcpy_P (zeile1_m_auswahl, PSTR("A.Aktoren "));
break;
case 2: strcpy_P (zeile1_m_auswahl, PSTR ("B.Schaltschwellen "));
break;
case 3: strcpy_P (zeile1_m_auswahl, PSTR ("C.Sensoren "));
break;
case 4: strcpy_P (zeile1_m_auswahl, PSTR ("D.Betriebszeiten "));
break;
case 5: strcpy_P (zeile1_m_auswahl, PSTR ("Einstellungen "));
break;
default: strcpy_P (zeile1_m_auswahl, PSTR ("Fehler "));
break;
}



lcd_gotoxy(0, 0);
lcd_puts(zeile1_m_auswahl);
lcd_puts(itoa( startup, temp_string1, 10 ));
lcd_gotoxy(0, 1);
lcd_gotoxy(10,2);
lcd_puts_p(PSTR ("AENDERN"));



if( get_key_press( 1<<KEY0 ))
switch (m_auswahl_page)
{
lcd_clrscr();
//case 1 : menue_aktoren();
//break;
//case 2 : menue_werte();
//break;
//case 3: menue_sensoren();
//break;
default: return ;//dieses return macht Probleme
}

if( get_key_press( 1<<KEY1 ))
{
m_auswahl_page++;
if (m_auswahl_page>5)
{
m_auswahl_page = 1;
}

}
if( get_key_press( 1<<KEY2 ))
{
m_auswahl_page--;
if (m_auswahl_page<1)
{
m_auswahl_page =5;
}

}

if( get_key_press( 1<<KEY3 ))
{
lcd_clrscr();
return; // dieses return mach ebenfalls Probleme
}

}
return;
}






Die beiden return-Anweisungen( im letzen drittel, mit Kommentar versehen) werden durch Tasten aufgerufen(Rücksprung zur Hauptseite).
Danach beginnt der Controller von neuem.
Er fürht die init_controller neu aus, obwohl in der Variablen startup bereits eine 1 steht.

Kann mal jemand bitte über den Code schauen, da ich vorher nich solche Probleme hatte und schon alles mögliche ausprobiert habe.

mfg Benedikt

PS Sonst muss ich wieder zurück zu BASCOM!^^

Besserwessi
12.07.2009, 21:42
Könnte es sein das der Speicher (RAM) zu knapp ist. Dann besteht die Gefahr das sich Stack und Daten in Gehege kommen. Bei einem Mega48 könnte das schon mal kanpp werden. Welcher µC wird benutz ?

Erfahrung habe ich damit auch noch nicht, aber es gibt da tool die den Stack testen. Ganz Einfach ist das nicht, da ja auch locale Daten genutzt werden.

dreadbrain
12.07.2009, 23:39
Hallo,

das Programm läuft auf einem MEGA16.

Denke nicht das der Ram voll ist, da ich auf dem MEGA16 schon C-Programme in ähnlicher größe betrieben habe.

Außerdem habe ich alle Texte die auf dem LCD angezeigt werden in den FLASH verbannt.


mfg Benedikt

sternst
13.07.2009, 01:09
void menue_auswahl(uint8_t m_auswahl_page)
{
char zeile1_m_auswahl[12];
...
case 1: strcpy_P (zeile1_m_auswahl, PSTR("A.Aktoren "));
break;
case 2: strcpy_P (zeile1_m_auswahl, PSTR ("B.Schaltschwellen "));
break;
case 3: strcpy_P (zeile1_m_auswahl, PSTR ("C.Sensoren "));
break;
case 4: strcpy_P (zeile1_m_auswahl, PSTR ("D.Betriebszeiten "));
break;
case 5: strcpy_P (zeile1_m_auswahl, PSTR ("Einstellungen "));
break;
default: strcpy_P (zeile1_m_auswahl, PSTR ("Fehler "));
break;

Wenn du die Rücksprungadresse auf dem Stack überschreibst, kann das return auch nicht mehr funktionieren.

SprinterSB
13.07.2009, 01:10
Deine lokalen char-Arrays bekommen mehr Zeichen, als sie aufnehmen können. Daher wird mit strcpy* ein Teil des Stacks überschrieben, nicht unwahrscheinlich die Return-Adresse --> Programm landet im Nirwana.

dreadbrain
13.07.2009, 08:47
Hallo,

danke das ists!.

Auf alles habe ich geachtet, aber auf die Zeichenlänge meiner strings nicht.

Danke!


mfg