Forum: Compiler & IDEs Probleme mit Variablen oder Timings


von Martin K. (mkrelli)


Angehängte Dateien:

Lesenswert?

Hi...

Ich hab ein Programm, was auf einem ATmega8 einige TLC5941 mit Daten 
versorgen soll. Das sind Chips mit denen man LEDs treiben kann...
Der Controller läuft via externer Clock bei 16MHz (Fuses C9, D0)
Er muss mehrere aufgaben erfüllen, damit die LED Treiber arbeiten:
- Eingabe neuer Werte via SPI (12bit pro LED)
- Generierung eines Takts für Counter in den Treibern
- Statusleitungen Treiben

Ich verwende avrlib zusätzlich zum WinAVR.
Der Code in main.c ist in etliche Funktionen geteilt...
Einige davon sind nur zur Initialisierung...

Die Funktion "timer1CM" ist handler für das CompareMatch Interrupt des 
timer1 und sorgt für die generierung des besagten Takts und eines Update 
Pulses nachdem neue Daten zu den Treibern übertragen wurden. Sie nutzt 
dazu die beiden globalen Countervariablen "nGSCLKCycles" und 
"nUpdateTimeout"

Die Daten werden in "main" (vorläufig) fortlaufend generiert -> wert 
hochzählen -> maximum erreicht -> runterzählen.

Lange Rede, kurzer Sinn... das ganze geht irgendwie nicht. Es ist 
folgendes:
Zur Generierung der Werte gibt es in main eine lokale Variable "nValue" 
(deklariert kurz vor der Endlosschleife), Initialwert ist 1. (Ich geb 
mir einige Debuginfos per UART aus...) Der Wert wird in 
"transferColorData" ins richtige Format gepackt und übertragen. 
Allerdings nur beim ersten mal richtig... Der output sieht so aus:

init done
sending value:
schedule update
Status: grayscale cycle running
Status: grayscale cycle completed
sending value: 
¼ó¼óó0ó000ó0¼ó¼¼ó¼óó0ó000ó¼¼ó¼óó¼ó00ó0¼0ó¼¼ó¼óó¼ó00ó0¼0ó¼óó¼ó0¼ó0
0ó0¼óó¼ó¼¼ó0¼ó00ó0¼óó¼ó¼¼ó0óó00ó0¼ó¼¼ó¼óó0ó000ó0¼ó¼¼ó¼óó0ó000ó¼¼ó¼óó¼ó00 
ó0¼0óôôÇ
ZZÿ€j¼óó¼ó0¼ó00ó0¼óó¼ó¼¼ó0¼ó00ó0¼óóó
schedule update
Status: grayscale cycle running
Status: grayscale cycle completed
sending value: 
ó00ó0¼óó¼ó¼¼ó0óó00ó0¼óó¼ó¼¼ó0óó00ó0¼ó¼¼ó¼óó0ó000ó¼¼ó¼¼ó¼óó0ó000ó¼
¼ó¼óó¼ó00ó0¼0ó¼óó¼ó¼¼ó00ó0¼0ó¼óó¼ó0¼ó00ó0¼óó¼ó¼¼ó0óó00ó0¼óó¼ó¼¼ó0óó00ó0¼ 
ó¼¼ó¼ôôÇ
ZZÿ€aóó0ó000ó¼¼ó¼óó¼ó00ó0¼0ó¼óó¼ó¼¼¼
schedule update
Status: grayscale cycle running
Status: grayscale cycle completed

Die Interruptabfolge ist hier allerdings richtig.
Definier ich mir "nValue" als globale Variable im SRAM bleibt das 
Programm nach dem setzen des ersten Updates stehen (timer1CM 
funktioniert nicht mehr richtig) oder es kommt nur Matsch raus.

Ich dachte mir, es gäbe evtl. ein Timing-Problem mit dem Interrupt und 
habe mal die Zählvariablen "nGSCLKCycles" und "nUpdateTimeout" als 
Register global definiert, dann geht aber auch nichts mehr. (Output ist 
nur noch matsch)

Ich verwende SPI normalerweise auch mit Interrupts, es geht aber auch 
nicht wenn ich es ohne mache.

Außerdem hab ich den Code mal testweise auf einen mega16L auf meinem 
STK500 geladen und da wird zwar kein Datenmatsch auf der UART 
ausgegeben, aber die Werte in nValue sind plötzlich mal ganz groß und 
dann ist es wieder der gleiche wie vorher...

Könnte sich bitte mal jemand den Code ansehen und mir sagen, ob ich da 
einen riesen Fehler gemacht hab der mir noch nicht aufgefallen ist?

merci,
Martin.

von Peter Diener (Gast)


Lesenswert?

Hallo,

deklariere alle Variablen, die im Interrupt genutzt werden als volatile.

Das verhindert, dass eine Optimierung des Compilers zu Fehlern führen 
kann.

Gruß,

Peter

von Falk B. (falk)


Lesenswert?

@ Peter Diener (Gast)

>deklariere alle Variablen, die im Interrupt genutzt werden als volatile.

Nöö, das braucht man nur für die, welche sowohl im Interrupt als 
auch im Hauptprogramm verwendet werden.

MFG
Falk

von Peter Diener (Gast)


Lesenswert?

Hallo Falk,

war unpräzise von mir, stimmt natürlich.

Peter

von Martin K. (mkrelli)


Lesenswert?

hey ho...

danke für den tipp.
ich hab das für die betreffenden variablen gemacht und "nValue" 
endgültig in den globalen bereich verschoben:

volatile uint16_t nGSCLKCycles;
volatile uint8_t nUpdateTimeout;

volatile uint16_t nValue = 1;  // only 12bit used

volatile struct {
  unsigned fNeedUpdate:1;
  unsigned fUp:1;
} flags;


der punkt ist:
auf dem mega16L im STK500 gehts jetzt (mit internem RC oszi).
auf meinem ATmega8 hat sich nichts verändert, sowohl nicht mit externer 
clock als auch nicht mit internem oszillator.

ich werd mal versuchen die uart implementation direkt von winavr zu 
nutzen. theoretisch müsste es ja identisch sein, aber dann hab ich 
wenigstens die kontrolle über die einstellungen.

hat sonst noch jemand eine idee?

greets,
Martin.

von Falk B. (falk)


Lesenswert?

@ Martin Krellmann (mkrelli)

>auf dem mega16L im STK500 gehts jetzt (mit internem RC oszi).

Und UART? Naja. ABer das diskutiere ich nicht mehr.

>auf meinem ATmega8 hat sich nichts verändert, sowohl nicht mit externer
>clock als auch nicht mit internem oszillator.

>Ich verwende avrlib zusätzlich zum WinAVR.

Ich denke mal dass mit der avrlib was nicht stimmt. Falscher Controller 
eingestellt oder so. Die rprint GEschiten sehen mir verdächtige aus. Und 
das Kauderwelsch deutet darauf hin, dass Pointer ins Flash an die 
falsche Stelle zeigen.

MFG
Falk

von Martin K. (mkrelli)


Angehängte Dateien:

Lesenswert?

Falk Brunner wrote:
> Ich denke mal dass mit der avrlib was nicht stimmt. Falscher Controller
> eingestellt oder so.

die überlegung hatte ich auch. der controller sollte zwar richtig 
gewesen sein, aber ich habe meinen code erstmal soweit als möglich von 
der avrlib getrennt... d.h.:

- ich hab ein neues makefile mit mfile gebaut
- was ich aus der avrlib noch brauchte (timer.c, buffer.c, vt100.c) hab 
ich in mein eigenes verzeichnis kopiert und etwas abgeändert (typen 
geändert, z.b. u08 nach uint8_t)
- die uart initialisiere und benutze ich komplett unabhängig von der 
avrlib (und via printf und stdout)
- beim spi transfer hab ich auch die interruptnutzung deaktiviert... bis 
auf die timer läuft jetzt alles ohne interrupts

ich stellte dannt fest, dass sich der controler nach dem ersten 
main-loop zurückgesetzt hat ---> watchdog war an.
ich erziel damit jetzt schon wesentlich bessere ergebnisse.
die zeichen werden sauber übertragen, nur die ausgabe von "nValue" (dem 
farbwert) klappt nicht - bzw. nur im ersten loop
(auch wenn ich das so mache, wie im avr-gcc tut mit sprintf und nem 
stringbuffer)

was kann da noch sein?

greets,
Martin.

PS: ich hab den neuen code nochmal angehängt

von Martin K. (mkrelli)


Lesenswert?

hi leute...

okay das problem hat sich erledigt. ich hab mir mal die neueste winavr 
version geladen und den code damit kompiliert. es geht jetzt.

danke für die tipps

greets,
Martin.

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.