Hallo, ich beschäftige mich seit kurzem mit dem Assembler programmieren. Dazu verwende ich einen Atmega8 auf einem Selfmade Experimentierboard mit ein paar Ausgängen (PortB zu LEDS), Tastern, Mehrfarbige LED und einem Summer. Als Einstieg habe ich ein Sample verwendet welches eine LED am PortB blinken lässt. Hat auch funtkioniert. Im nächsten schritt wollte ich ein Lauflicht programmieren. --> Hat auch funktioniert und das lauflicht läuft und läuft :D ABER: Mir ist aufgefallen dass das Bit7/Led8 und Bit8/Led6 nicht vollständig leuchten. Hier der Assembler Sourcecode. Die Kommentare stimmten teilweise nicht mehr überein und manche Dinge werden noch nicht aufgerufen. Als Test schalte ich alle LEDs ein. ************************************************************************ ****** ;* ;* Titel: LED Blinkprogramm ;* Autor: Rüdiger Kluge ;* Version: 01.01.0003 ;* Build date: 22.12.08 ;* Target: ATmega8 ;* ;* Zweck: ;* Eine an PORTB, PB0 angeschlossene LED blinkt ;* Die Periode des Blinkens kann mit den Variablen ;* delay_0 ;* delay_1 ;* delay_2 ;* eingestellt werden. ;* ;*********************************************************************** ******* ;*********************************************************************** ******* ;* Definitionen ;*********************************************************************** ******* .include "m8def.inc" ; Definitionen für ATmega8 .def temp = r16 ; temp ist symbolischer Name für Register 16 ; wird als temporäre Variable verwendet .def delay_0 = r17 ; delay_0 ist symbolischer Name für Register 17 .def delay_1 = r18 ; delay_1 ist symbolischer Name für Register 18 .def delay_2 = r19 ; delay_2 ist symbolischer Name für Register 19 .def count = r20 .equ LED_0 = ~0b00000000 ;*********************************************************************** ******* ;* Programm Start nach Reset ;* ;* der Stackpointer wird initialisiert ;* RAMEND = $045F = 1119 beim ATmega8 ;* Register werden gesetzt ;*********************************************************************** ******* RESET: ; hier startet der Code nach einem Reset ldi temp,high(RAMEND) ; $04 wird in Register 16 geladen out SPH,temp ; SPH, oberes Byte des Stackpointers wird $04 ldi temp,low(RAMEND) ; $5F wird in Register 16 geladen out SPL,temp ; SPL, unteres Byte des Stackpointers wird $5F out DDRB,temp ; setzt alle PINs von PORTB als Ausgang ldi temp,LED_0 ; temp wird 0b00000000 ;*********************************************************************** ******* ;* Hauptprogramm ;* ;* eine endlose Schleife ;*********************************************************************** ******* MAIN: ; hier startet das Hauptprogramm ; ldi delay_0, 1 ; delay_0 wird 0 ; ldi delay_1, 1 ; delay_1 wird 0 ; ldi delay_2, 4 ; delay_1 wird 0 out PORTB,temp ; PORTB, PIN0 wird gesetzt ; lsr temp ; com temp ; cpi count, 8 ; breq RESET_REGISTER ; rcall SUB_COUNT ; rcall SUB_DELAY ; Verzögerung, Sprung zu Unterprogramm rjmp MAIN ; springt zurück zu MAIN: ;*********************************************************************** ******** ;* Unterprogramm SUB_DELAY ;* ;* erzeugt eine Verzögerung für das Blinken ;* ;*********************************************************************** ******** SUB_DELAY: ; hier ist der Einsprung ins Unterprogramm ; hier beginnt die innere Schleife dec delay_0 ; delay_0 = delay_0 - 1 brne SUB_DELAY ; wird ausgeführt, solange delay_0 nicht 0 ist ; hier beginnt die innere Schleife dec delay_1 ; delay_0 = delay_0 - 1 brne SUB_DELAY ; wird ausgeführt, solange delay_0 nicht 0 ist ; hier beginnt die innere Schleife dec delay_2 ; delay_0 = delay_0 - 1 brne SUB_DELAY ; wird ausgeführt, solange delay_0 nicht 0 ist ; hier beginnt die innere Schleife ret ; Sprung zurück ins Hauptprogramm zur ; Instruktion nach ; rcall SUB_DELAY, also rjmp SUB_COUNT: inc count ret RESET_REGISTER: ldi temp, LED_0 out PORTB,temp ldi count, 0 rjmp MAIN *********************************************************************** Könnt ihr mir bitte helfen was ich falsch mache ? Auch auf meinem zweiten Board tritt der selbe Fall auf. DANKE !! Grüße Luki Foto ist angehängt.
:
Bearbeitet durch User
DDRB ist falsh initialisiert.Tausche mal die 2 Zeilen nach der Stackpointer-Init.
Hallo, wird $5F out DDRB,temp ; setzt alle PINs von PORTB als Ausgang ldi temp,LED_0 ; temp wird 0b00000000 was bringt Dich auf die Idee, daß $5F ALLE Pins auf Ausgabg schaltet? Bei sind bei 0b00111111 nur Pb0...PB5 Ausgang und Pb6+7 beliben Eingang. Da schaltest Du also nur den internen PullUp (irgendwas um 30k) ein- und aus, logisch, daß die LEDs mit solche einem großen Vorwiderstand nur glimmen. Da solltest Du also temp schon mit $FF laden... Gruß aus Berlin Michael
Hallo! Vielen dank für die schnelle Hilfe !! Hab nicht damit gerechnet so schnell eine Antwort zu bekommen. Ich habe jetzt den DDRB nicht mit $5F sondern mit $FF also wie von Knut vorgeschalgen die Zeilen nach der Stackpointer Initialisierung vertauscht. --> Folglich wird DDRB mit $FF initialisiert. Zum Thema Stackpointer-Init bin ich mir auch nicht sicher warum ich das benötige. Ich greife ja nicht auf dem Stack zu. Kann mir das jemand erklären oder weiß jemand wo ich das nachlesen kann ? Vielen Dank nochmals für die schnelle Hilfe !! :) Gruß Luki
Lukas A. schrieb: > Zum Thema Stackpointer-Init bin ich mir auch nicht sicher warum ich das > benötige. Ich greife ja nicht auf dem Stack zu. Sobald Du Unterprogramme aufrufst (call, rcall, später evtl. auch Interrupt Service Routinen), verwendet der Controller automatisch den Stack. Dort legt er die Rücksprung-Adresse ab.
:
Bearbeitet durch User
Alles klar ! Vielen dank ! Und ich dachte dass macht der Atmega selbst wenn man Unterprogrammer oder ISR aufruft. Nur wenn ich selbst auf den Stack zugreife muss ich diesen Decklarieren. Leider war meine Vermutung falsch ! Danke nochmals !
Hi >Und ich dachte dass macht der Atmega selbst wenn man Unterprogrammer >oder ISR aufruft. Das ist richtig. >Nur wenn ich selbst auf den Stack zugreife muss ich >diesen Decklarieren. Da bleiben außer push und pop nicht viel übrig. Ansonsten hast du, außer der Stackinitialisierung, nichts mit dem Stack zu tun. Und selbst das wird bei neueren AVR automatisch erledigt. MfG Spess
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.