Hallo zusammen,
ich benutze für ein Funkgeräteprojekt einen ATMega128 (8MHz interner
Takt). Der entscheidenden Teil des Codes ist herauskopiert. Dieser Teil
soll einen ST7920 LCD-Controller in einem 12864 LCD ansprechen. Die
Datenübertragung ist im 8-Bit-Mode. Datenport ist PORTC, Über PA4..PA7
laufen RS, RW, E und RST.
Der ATMega128 hat folgende Fuses: L:E4, H:D1, E:FF.
Problem: Sobald ich PA7 auf "hi" setze (also nach dem RESET des LCD) und
einen weiteren Schreibzugriff auf PORTA durchführe (im Code das
Schreiben einer "0"), resettet sich der Controller und das Programm
startet neu.
Auslöser ist dabei nicht die "0" sondern das Setzen von wahlweise RS, RW
oder E in der Funktion lcd_write().
Der Codeschnipsel hängt an (dk7ih.c).
Hat jemand eine Idee, worin das Verhalten des Controllers begründet sein
könnte?
Grüße
Peter
DK7IH (Peter) schrieb:> AVCC anzuschließen hatte leider bezüglich des Problems keinen Effekt.> Schade. :-(
Sind auch alle GNDs angeschlossen, ist jedes (A)VCC/GND-Pärchen mit
jeweils 100nF abgeblockt?
Wenn der Compiler keinen Murks baut, gibt es bei dem gezeigten Code, der
nichts anderes macht, als ein paar Pins zu beschreiben, keinen Grund
dasfür einen Softwarefehler zu vermuten. Ergo: Hardware.
So, leider war diese Prüfung auch unergiebig. Alle VCCs, GNDs und 100nF
Kondensatoren sind korrekt angeschlossen. Spannungen liegen korrekt an,
Controller wurde auch probehalber gewechselt, immer noch der gleiche
Effekt.
Compiler ist AVR GCC unter Linux.
Grüße
Peter
Hallo,
ja, das Target stimmt, das Projekt läuft unter "mini6" und wird auch so
von AVRDUDE auf den Controller geladen. Hier mal die entsprechenden
Zeilen aus dem Makefile:
MCU = atmega128
FORMAT = ihex
TARGET = mini6
OPT = 3
Optimierungslevels habe ich verschiedene getestet, jedes Mal das gleiche
Ergebnis.
Dann habe ich mal probehalber alle Zeilen aus der Funktion lcd_init() in
das Hauptprogramm geschrieben. Jetzt tritt der Fehler, was mich sehr
verwundert, NICHT mehr auf, wenn lcd_init() nun nicht mehr aufgerufen
wird. Dieses Ergebnis ist nicht zufällig sondern reproduzierbar. Könnte
es sein, dass der Compiler da einen Fehler macht?
Das HEX-File hänge ich an.
Gruß
Peter
Kann es sein, dass die Versorgungsspannung des Controllers einbricht,
wenn du in der lcd_write etwas auf den Port ausgibst?
Dann eventuell extern ein Kurzschluss am Pin gebaut?
Hallo,
die Versorgungsspannung habe ich mit dem Scope überprüft, die ist
vollkommen glatt.
Interessant ist ja, dass wenn ich lcd_write() weglasse und die
entsprechenden Aufrufe identisch in das Hauptprogramm setze, der Fehler
dann nicht mehr auftritt. Dann habe die PINs an PORTA und PORTC bei
Überprüfung mit dem Scope die korrekten Signale und Soft- und Hardware
arbeiten einwandfrei.
Die Platine habe ich auch überprüft. Zwei ATMega128 (jeweils auf
Breakoutboards verlötet) zeigen ebenfalls identisches Verhalten.
Daher meine Vermutung, dass der Fehler vom Compiler kommt, der mit dem
Handling der Funktion ein Problem hat.
Gruß
Peter
Ok, dann könnte die Vermutung darin liegen, dass der Stackpointer nicht
eingestellt wurde, womit der Controller bei Funktionsaufruf bestimmte
Infos nicht auf den Stack bekommt und deshalb einen Reset macht.
Allerdings nutzt du C und der Compiler sollte sich darum kümmern, anders
als bei Assembler, wo man das selbst einstellen muss. Vielleicht hier
was verstellt?
Andererseits dürte dann bereits das Betreten der Funktion schon ein
Problem sein...
Erzeugt dein Compiler ein .lss-File mit Assemblercode und Kommentaren,
in denen die C-Befehle stehen? Darüber ließe sich auch einiges heraus
finden, denke ich.
DK7IH (Peter) schrieb:> Das HEX-File hänge ich an.
Das Hex entspricht nicht dem oben gezeigten Code.
Denn:
1
intmain(void)
2
{
3
DDRA=0xFF;
4
5
PORTA|=128;
nach PortA |= 128 sitzt ein Delay drin, dass der Compiler sicher nicht
selbst reingebastelt hat, sieht so aus:
1
ldi r24,k66
2
ldi r25,k0E
3
L0069:
4
sbiw r24,k01
5
brne L0069
und dauert 14744 Takte gleich 1,8ms@8MHz.
Außerdem wird in der Main Bit 7 von PortA nach dem Delay wieder
gelöscht, bevor's in die lcd_write() geht.
Ansonsten sieht der Code aus dem Hex dem geposteten C ähnlich, er rennt
zum Schluss in eine Endlosschleife.
Du verwechselst da aber nicht eine Endlosschleife mit einem Neustart?
Wie willst Du bei diesem Code das Eine vom Anderen unterscheiden?
Du müsstest mindestens eine Led beim Startup blinken lassen, um das zu
erkennen.
DK7IH (Peter) schrieb:> Der ATMega128 hat folgende Fuses: L:E4, H:D1, E:FF.
E:FF ist richtig, versichere Dich dennoch erneut, nicht dass es E:FD
heißt und der M103C compatibility mode an ist.
Hi,
ja, ich habe den Code zum Testen nochmal zwischendurch etwas verändert.
Das Delay hat in der Tat ca. 1ms und ist natürlich von mir. ;-)
Der Unterschied zwischen normalem Programmlauf und Dauer-Neustart ist
für mich erkennbar, weil ein Scope an PA7 hängt. Wenn das Programm
korrekt arbeitet (also der Funktionsaufruf nicht stattfindet) bleibt der
Pegel nach dem Togglen auf "hi".
Wenn das Programm sich selbst neu startet, wechselt PA7 zwischen 0
(PORTA &= ~(128);) und 1 (PORTA |= 128;). Die Endlosschleife ist ja
leer, da passiert dann bei korrektem Programmablauf nichts mehr, was PA7
verändert.
Ich hänge nochmal ein .C-, ein .lss und ein HEX-File an, die jetzt
zueinander passen.
Gruß
Stackpointer wird konfiguriert. Es wird der Speicherbereich des
ATmega128 genommen. Im M103C Compatible Mode würde das jedoch über den
SRAM hinaus springen, siehe Datenblatt Abschnitt "SRAM Data Memory" (bei
mir Seite 17).
Das mit dem M103-Mode war ein guter Tipp. Ich hatte übersehen, dass die
Kommandozeile, mit der ich den zweiten ATMega128 eingestellt hatte, ein
fehlerhaftes Zeichen hatte. Jetzt sehe ich die ersten Zeichen auf dem
Display. Vielen Dank!