C: Variable wird unerklärlicherweise gelöscht....

Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte

Elektronik Forum Nicht eingeloggt       Einloggen       Registrieren




[Registrieren]      --     [FAQ]      --     [ Einen Link auf Ihrer Homepage zum Forum]      --     [ Themen kostenlos per RSS in ihre Homepage einbauen]      --     [Einloggen]

Suchen


Serverzeit: 16 2 2025  19:36:03      TV   VCR Aufnahme   TFT   CRT-Monitor   Netzteile   LED-FAQ   Oszilloskop-Schirmbilder            


Elektronik- und Elektroforum Forum Index   >>   Microcontroller        Microcontroller : Hardware - Software - Ideen - Projekte


Autor
C: Variable wird unerklärlicherweise gelöscht....

    







BID = 463673

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf
 

  


Hallihallo zusammen,

ich arbeite gerade an meinem ersten grösseren Projekt mit C.
Es gilt ein Nokia 3310 LCD anzusteuern.
Die Ansteuerung klappt wunderbar, nur hab ich ein Problem mit der Programmierung.

Es geht um folgendes.

Jede Sekunde wird vom Timer1 ein Output Compare A Interrupt ausgelöst. In der Interruptroutine wird eine Variable ("Sekunde") hochgezählt. Dieser neue Sekunden-Wert soll dann auf dem LCD erscheinen.

Dazu muss das LCD zuerst gelöscht werden.
Dazu werden zwei verschachtelte For-Schleifen durchlaufen.

Nun kommts. Sobald die erste Schleife den Wert "6" annimmt, springt der Wert von "Sekunde" völlig zusammenhangslos auf 0 zurück. (Im AVR Studio Simulator eruiert und durch Realität bestätigt.).

Mein Wert wird auf dem LCD also nicht hochgezählt, sondern bleibt immer 0...

Hier die Codeschnipsel:

Initialisierung der Variable:


Code :


volatile uint16_t sekunde; //Sekunden-Variable

main(void)
{

sekunde = 0;

while(1) //Endlossschleife
{

}


}




Die Interruptroutine:


Code :


ISR(TIMER1_COMPA_vect) //Timer1 (Sekundentakt) Compare-Interrupt
{
char s[5];
PORTD ^= (1<<5); //LED toggeln

sekunde++; //Sekunde hochzählen

Clear_LCD(); //LCD löschen



utoa(sekunde,s,10); //Integer-to-Ascii (Ascii kommt aufs LCD) utoa für unsigned.
LCD_text(s,1,1); //Anzeigeroutine ==> Zeigt die Zeit in Sekunden auf dem LCD an
}



Die Clear_LCD-Routine:


Code :


void Clear_LCD(void)
{

uint8_t y;
uint8_t x;

for(y=1; y<=6; y++)// Zeilenblöcke durchzählen
{
for(x=1; x<=84; x++) //Spalten durchzählen
{
//datasend(y,x,0); //eine 0 schicken (LCD löschen)
cache[y][x] = 0; // nun stehen überall im Cache eine 0

}
}

cachesend(); //der Cache wird zum LCD geschickt
}


Hier steckt auch der Bock drin. Sobald x von 84 auf 0 springt und y den Wert 6 annimmt, nimmt der Inhalt der Variable "Sekunde" den Wert 0 an. Völlig zusammenhangslos (zumindest für mich)...
Die Routinen funktionieren sonst einwandfrei. Es wird sonst nirgends an "Sekunde" herumgewerkelt, nur hier...

Wieso ändert der Inhalt von "Sekunde" auf den Wert 0? Das darf doch net sein...
AVR: Mega88
AVR Studio, GCC

Weiss da jemand Rat?

Herzlichen Gruss und vielen Dank
Mario


_________________
Meine Projekte:
http://mauerer.m.googlepages.com

BID = 463703

Unregistered Guest

Stammposter



Beiträge: 345
Zur Homepage von Unregistered Guest ICQ Status  

 

  

Wenn du auch Assembler kannst, guck dir mal den Code in dem Beitrag weiter unten im Forum an.
Ansonsten ma warten, bis die Profis auftauchen. Oder du schickst dem Verfasser des Beitrags ne PN.

BID = 463713

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Grmpf, das ist ja nicht mein Problem...

Mein Display funktioniert wunderbar, ich kann auf ihm darstellen was ich will, Zeichensatz ist auch implementiert, das funktioniert tipptopp.

Mein Problem liegt in der Programmierung einer "Nebenfunktion".
Auf dem Display sollen einfach nur Sekunden hochgezählt werden. Das macht die Variable "Sekunde" und der Timer1, welcher jede Sekunde einen Compare-Interrupt auslöst. In der ISR soll der Wert der Variable "Sekunde" hochgezählt werden. Der Neue Wert dieser Variable soll auf dem Display angezeigt werden. Dazu muss das Display zuerst gelöscht werden. Die Clear_LCD-Routine funktioniert ansonsten wunderbar. Hier jedoch wird nach Aufrufen dieser Routine die Variable "Sekunde" unerklärlicherweise wieder auf den Wert 0 zurückgesetzt, ohne dass ich im Code etwas an der Variable drehe. Dies geschieht, sobald "y" in der Clear_LCD Routine den Wert 6 annimmt. Somit wird aum dem LCD immer der Wert 0 angezeigt, es wird nix hochgezählt, das "Sekunde" immer wieder auf 0 zurückgesetzt wird..

Ich vermute, dass irgend ein Speicherkonflikt vorliegen könnte. Ich weiss dies jedoch nicht, da ich zu wenig Erfahrung habe, deshalb frage ich hier nach.

Im Anhang findet sich noch das komplette Programm, für diejenigen, die sich das anschauen wollen.

Herzlichen Gruss
Mario


_________________
Meine Projekte:
http://mauerer.m.googlepages.com

[ Diese Nachricht wurde geändert von: Steppenwolf am 13 Okt 2007 10:56 ]

BID = 463716

Benedikt

Inventar

Beiträge: 6241

Die Arrays in C beginnen beim Index 0 und nicht bei 1...

BID = 463718

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Hat das jetzt was mit meinem Problem zu tun oder ist das eine Nebenbemerkung?.


_________________
Meine Projekte:
http://mauerer.m.googlepages.com

BID = 463722

Benedikt

Inventar

Beiträge: 6241

Das ist vermutlich dein Problem !

BID = 463725

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Hmm.... ich komm nicht drauf...
Was meinst du wo?
Ein Arrayindex "überläuft" bei mir ja nirgends... Gut, ich beginne beim "cache" array halt bei 1 mit zählen, das funktioniert ja aber trotzdem, das array ist ausreichend hoch definiert...

Im Sram haben noch knapp 500Bytes platz, also von daher sollte es doch keine Speicherkonflikte geben?



_________________
Meine Projekte:
http://mauerer.m.googlepages.com

BID = 463726

Benedikt

Inventar

Beiträge: 6241

Wie ist dein Array definiert ? Dass du im Array noch 500Bytes hast, kann nicht sein, denn das Array benötigt alleine schon 595 Bytes...

BID = 463734

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Aaaah... jeeetz seh ichs
Der arrayindex ist tatsächlich überlaufen...

Danke für die Hilfe!! Jetzt läuft es

Gruss
Mario



_________________
Meine Projekte:
http://mauerer.m.googlepages.com

BID = 463739

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Uh, wenn wir schon dabei sind, gleich noch ne kleine Frage

Folgendes Listing:



Code :


void LCD_text(uint8_t *text, uint8_t x, uint8_t line)
{

uint8_t i;
uint8_t hilfe; //sorgt für eine fortlaufende Nummerierung im Cache
hilfe=0;

while(*text)
{
for(i=0; i<5; i++) //ein Zeichen hat 5 Spalten
{
cache[line][x+hilfe] = pgm_read_byte(&Font[((*text - 0x20)*5)+i]); hilfe++;

}

text++;
}

cachesend(); //überträgt den neuen Cache zum LCD
}




*text ist ja ein Pointer. Er enthält die Addresse zur ihm zugewiesenen Variable/Konstante. In diesem Fall z.B. *text = "Hallo"

Ich verstehe die while-Schleifen-Bedingung nicht so recht. While(*text)... Ja was nun.. Die Schleife läuft durch während was true ist?

Und was bewirkt das statement "text++;" am Ende der While-Schleife?
Wird damit der "Adressraum" meines Textes "Hallo" durchgezählt und die Schleife läuft solange durch, wie man noch in diesem Adressraum ist?

Gruss
Mario

_________________
Meine Projekte:
http://mauerer.m.googlepages.com

BID = 463751

Benedikt

Inventar

Beiträge: 6241


Zitat :
Steppenwolf hat am 13 Okt 2007 12:07 geschrieben :

*text ist ja ein Pointer. Er enthält die Addresse zur ihm zugewiesenen Variable/Konstante.

Genau.

Zitat :

In diesem Fall z.B. *text = "Hallo"

Das ist nicht ganz richtig.
Korrekt müsste es heißen:
text="Hallo", denn *text ist die Dereferenzierung (mit anderen Worten: Der Inhalt der Adresse), und das wäre in diesem Fall ein char, nämlich der erste Buchstabe, also 'H'


Zitat :

Ich verstehe die while-Schleifen-Bedingung nicht so recht. While(*text)... Ja was nun.. Die Schleife läuft durch während was true ist?

Man muss wissen, dass true nichts anderes ist wie ungleich 0, und dass ein String mit einer 0 am Ende gekennzeichnet wird.
Die Schleife läuft also solange, bis die 0 am Ende erkannt wird.


Zitat :

Und was bewirkt das statement "text++;" am Ende der While-Schleife?

Damit wird der Pointer erhöht, und so Buchstabe für Buchstabe abgearbeitet.

BID = 463762

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Supi, jetzt ist alles klar! Dankeschön!

Gruss
Mario

_________________
Meine Projekte:
http://mauerer.m.googlepages.com

BID = 474245

stenny

Gerade angekommen


Beiträge: 16
Wohnort: Weilheim (Oberbayern)

Hallo Mario,

Deinen Ausführungen zufolge bist Du gerade dabei Deine ersten Erfahrungen in der embedded SW-Entwicklung mit C zu machen. Hierzu von mir zunächst mal Glückwunsch zu den ersten Erfolgen

Einen kleinen Hinweis kann ich mir allerdings nicht ersparen. Bei Deinem Programm fällt mir auf, dass die gesamte Programmfunktion im Kontext der Interrupt-Serviceroutine des Timer-Capture-Interrupts abgearbeitet wird. Diese Implementierung ist in Deiner Anwendung nicht kritisch, da der Interrupt lediglich im Sekundentakt auftritt und die SW ansonsten nichts zu tun hat. Ein solches Design ist allerdings eher die Ausnahme. Die Regel ist vielmehr, dass ein Mikrocontroller gut ausgelastet wird und die Durchlaufzeit durch eine Interruptroutine so kurz wie möglich gehalten wird.
Solch ein Design ist beispielsweise dadurch zu erreichen, dass die ISR nur eine "Flag"-Variable beschreibt, auf die im Hauptprogramm gewartet wird. z.B. so oder ähnlich:

============== fast schon C-Code ========================
volatile uint8_t sekundenEreignis = 0;

void main(void) // non-hosted environment!
{
<allgem. Initialisierungen>

// die Hauptschleife
while (1)
{
if (0 != sekundenEreignis)
{
<LCD-Ansteuerung und sonstige Funktionalität>
sekundenEreignis = 0; // timer wieder "scharf" schalten
}
}
}

void timerInterrupt(void)
{
sekundenEreignis = 1;
<IRQ Aufräumarbeiten>
}
=================================================================

BID = 475275

Steppenwolf

Schreibmaschine



Beiträge: 1757
Wohnort: Zürich, Schweiz
Zur Homepage von Steppenwolf

Hallo stenny,

vielen Dank für deine Tipps,

dieses Code-Beispiel war nur ein Programm-Protoyp meinerseits und dementsprechend wurden solche "Design-Regeln" von mir nicht beachtet.

Im "Originalprogramm" führe ich nur das absolut Nötigste in der Interruptroutine aus und setze Status-Flags um die Sache kurz zu halten.

Herzlichen Gruss
Mario

_________________
Meine Projekte:
http://mauerer.m.googlepages.com


Zurück zur Seite 1 im Unterforum          Vorheriges Thema Nächstes Thema 


Zum Ersatzteileshop


Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum       Datenschutz       Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland       

gerechnet auf die letzten 30 Tage haben wir 23 Beiträge im Durchschnitt pro Tag       heute wurden bisher 22 Beiträge verfasst
© x sparkkelsputz        Besucher : 183062621   Heute : 16134    Gestern : 21641    Online : 279        16.2.2025    19:36
10 Besucher in den letzten 60 Sekunden        alle 6.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.0436820983887