Hallo! Woran kann das liegen, dass mein Controller, sobald ich in ein vorhandenes Programm ein Unterprogramm einfüge, mein Controller an ganz merkwürdigen Stellen nicht mehr weiter läuft? Für sich alleine laufen die Programme. Fügt man sie zusammen, werden Warteschleifen auf einmal kürzer oder der Controller (mega16) bleibt irgendwo hängen. Ist in Assembler geschrieben. Der Stackpointer ist meine ich ordentlich initialisiert und auf das RAM Ende gesetzt. In der Simulation läuft es normal. Hat da jemand eine Idee, was da ein typische Fehler sein könnte?
Hi 1.Hast Du den Stack initialisiert. 2.wenn du push/pop Befehle benutzt,überprüfe,ob all gepushten Register wieder gepopt werden. Mfg HG
Ja den Stackpointer setze ich auf RAMEND. Und push und pop verwende ich garnicht. Is doch richtig, dass der Stackpointer bei AVRs von höherer Adresse zur niedrigeren zählt oder? Also anders als beim 8051 ?
Der Stack wächst nach unten. Irgendwelche Variablen im RAM abgelegt? Ich halte es üblicherweise so, dass ich den Stack ans obere Ende lege, und die Variablen am unteren Ende ablege, so dass genug Luft bleibt. Die Rücksprünge richtig organisiert? Sprich, die Unterprogramme auch schön ordentlich mit RET verlassen? Gruss Jadeclaw.
Ja eigentlich schon. In der Simulation mit AVR Studio klappt das auch alles wunderbar. Nur im Controller selbst eben nicht. Und ab und zu ändern sich die Stellen auch, an denen er stoppt. Find das absolut merkwürdig. Das ganze fängt auch erst an, wenn man mehrere Unterprogramme aufruft. MFG Dominik
Momentan den mega16. Aber beim mega32 hab ich genau die gleichen Probleme. Den Stack initialisieree ich so: ldi temp1, 0xff ; LOW-Byte der obersten RAM-Adresse out SPL, temp1 ldi temp1, 0x00 ; HIGH-Byte der obersten RAM-Adresse out SPH, temp1 Is das so in Ordnung? MFG Dominik
Bei mir steht: .INCLUDE "m16def.inc" ... ldi rTemp1, HIGH( RAMEND ) out SPH, rTemp1 ldi rTemp1, LOW( RAMEND ) out SPL, rTemp1 funktioniert einwandfrei.
@Dominik: Bist Du Dir sicher, daß die obere Endadresse Deines RAMs 0x00FF ist? Dann hätte IMHO Dein Controller ziemlich wenig RAM ...
Ancalagon hat es richtig gemacht. Dafür hat Atmel schliesslich den RAMEND definiert. 0x00ff ist etwas sehr niedrig und bei grösserer Verschachtelungstiefe kann der Stack in die Outputregister reinlaufen. Und dann schmiert der Prozi ab. Für technisch interessierte, RAMEND ist für den ATMega16 auf 0x045F gesetzt. Gruss Jadeclaw.
Du musst erst das HIGH-byte schreiben und dann erst das LOW-Byte ! Im Datenblatt des AVR steht für den Zugriff von 16-Bit Registern : zum Lesen : erst das LOW-Byte (High-Byte geht dabei in ein Latch und dann mit dem HIGH-Byte das Latch auslesen. zum Schreiben : erst das HIGH-Byte (das geht in das Latch) und dann das LOW-Byte (das geht dann erst zusammen mit dem Latchwert ins eigentliche 16-Bit Register). Das heißt : zum Schreiben eines 16 Bit Registers (wie z.B. SPL/SPH, TCNT1L/TCNT1H, ...) : ldi temp1,HIGH(RAMEND) out SPH,temp1 ; Latch wird beschrieben ldi temp1,LOW(RAMEND) out SPL,temp1 ; temp1 geht zusammen mit dem Latchinhalt ins Register und zum lesen : in temp1,SPL ; LOW-Byte, High-Byte geht in ein Latch in temp2,SPH ; HIGH-Byte, Latch wird gelesen Dann sollte es eigentlich auch mit deinem Programm funktionieren, da bei deinem Fehler der Stack auf 005F initialisiert wurde (SP und Latch beim Anschalten : 00, dann LOW-Byte von RAMEND in den SP : 005F) 005F liegt lt. Datenblatt im IO-Bereich. Sprich : mit jedem Call/Push überschreibst du ein IO-Register. Das konnte nicht gut gehen.
Hallo! Also mit dem Stackpointer das habe ich jetzt umgeändert. Aber das Programm spinnt immernoch. Bleibt zwar nicht mehr hängen, aber auf dem LCD wird jetzt "Ffb" ausgegeben anstatt "Hallo!". Hab den Eindruck, dass je nachdem wo und welche Unterprogramme man aufruft, der Ablauf des Programmes durcheinander kommt. Für sich alleine funktionieren die Unterprogramme alle. Hab das Programm jetzt mal angehängt. Vielleicht findet ja einer nen Fehler, der das verursachen könnte. Ich sitze da jetzt schon 2 Tage dran und verzweifel so langsam. Vielen Dank für die Hilfe! MFG Dominik
Wie ich sehe hast du die Displayroutinen auch aus einem Tutorial übernommen. Dabei musst du aber auch drauf achten, dass du die Routinen wie Delay, Wait50µs und eigentlich alles, was mit Delays zu tun hast anpasst. Wenn du Beispielsweise den Code, der für ein 4MHz Quarz (nur ein Beispiel) entwickelt wurde mit einem 16MHz AVR ausprobierst, wird das Timing auch 4x schneller. Das könnte beim Display dann Probleme geben. Achte darauf einfach nochmal, oder schreib die Routinen zum Warten von 50µs, 5ms, usw. für deinen Takt selbst. Bsp. für ein 1MHz Quarz. Call-Sprung zur Routine braucht 4 Zyklen, ret ebenfalls, daher muss man 992 Zyklen Delay einbauen Wait1ms: ldi LOOP,248 WAIT_LOOP: subi LOOP,1 nop brne WAIT_LOOP ; für die Schleife 4 Zyklen bei Sprung, 3 wenn weiter ret ; 248 * 4 = 992, + 8 = 1000 (1ms bei 1MHz) Das einfach an deine Taktfrequenz anpassen, schon gehts (hoffentlich ;-)
Also wenn die Wartezeiten länger sind ist es doch nicht so schlimm oder? Hab meinen auf 1 MHz laufen. Hab dann grad mal 4 MHz ausprobiert, wie im Tutorial und bekomme das gleiche Ergebnis. Für sich alleine läuft die LCD Ausgabe auch super. Alle Unterprogramme laufen für sich selber. Nur wenn ich sie zusammenbastel, dann gibt es Probleme. Grüße Dominik!
Hey ich habs. War wohl ein Fehler in einer der LCD routinen, den ich anscheinend ausversehen eingebaut habe. Er hat immer das untere Nibbel und obere Nibbel gleich ausgegeben. Also mit dem swap oder so hats wohl nicht richtig hingehauen. Damit wäre mein erstes Problem schonmal gelöst. Die Ausgabe läuft jetzt wunderbar. Arbeite mich jetzt mal wieder weiter durch und hoffe, dass das jetzt mein einziges Problem war und nicht noch wieder Probleme mit Unterprogrammen auftauchen. Also erstmal vielen Dank für eure Mühe. MFG Dominik
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.