Autor |
C: Variable wird unerklärlicherweise gelöscht.... |
|
|
|
|
BID = 463673
Steppenwolf Schreibmaschine
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
|
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 345
|
|
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) Beiträge: 6241
|
Die Arrays in C beginnen beim Index 0 und nicht bei 1...
|
BID = 463718
Steppenwolf Schreibmaschine
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
|
BID = 463722
Benedikt Inventar
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) Beiträge: 6241
|
Das ist vermutlich dein Problem !
|
BID = 463725
Steppenwolf Schreibmaschine
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) 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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) 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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
|
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 ![](/phpBB/images/smiles/smilie_smile.gif) ========================
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
![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif) ![](/phpBB/images/stars/star.gif)
Beiträge: 1757 Wohnort: Zürich, Schweiz
|
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
|