LED_Lauflicht_mit_Z-Pointer

Oskar01

Mitglied
24. März 2008
267
0
16
Köln
Sprachen
  1. Assembler
Hallo,
habe ein kleines Programm für ein Lauflicht erstellt.
Nun stelle ich fest, daß Nulldaten nicht ausgeführt werden, hier bricht der String ab. Wird zwar als "nullterminiert" korrekt behandelt, aber, wie bekomme ich das hin, zum Beispiel Hex00 als Datenstring korrekt zu hinterlegen?
Noch etwas, die Z+-Anweisung wird im Simulator wie auch beim Assemblieren als Fehlermeldung "such command in ATMega8515 not supported" quittiert.
Daher die adiw-Anweisung als gängige Alternative gewählt.

Schönen-Rest-Sonntag noch.

Euer Oskar01
 

Anhänge

  • Zpointer1.txt
    2,2 KB · Aufrufe: 22
Hallo Oscar,

"z+" gibt es nur in Verbindung mit Store/Load indirect.

adwi zl, 1 wirkt direkt auf das 16Bit-Register Z (zl, zh), in diesem Fall inkrementiert es das z-Register.

Normalerweise nutzt man den Abschluss mit 0x00, um eine ASCII-Zeichenkette zu beenden. Wenn du in deinem Fall auch 0x00 ausgeben möchtest, könntest du ggf. die "Zeichekette" auf eine konstante Länge setzen, oder zum Beispiel den ersten Definebyte-Eintrag im Flash als Längenangabe verwenden.

Grüße,
Dirk
 
Danke

Hallo Dirk,
schon mal danke für den Tip.
Der .byte Eintrag geht, wie Du schon sagtest, glaube ich, nur im dseg aufwärts und nicht im cseg.(Oder?)
OK. Man könnte über Compare-Schleifen die String-Länge definieren, habe ich noch nicht ausprobiert, und/oder durch Verwendung eines "seltenen" Zeichens (§ zum Beispiel) den String damit terminieren.
Die Null im Lauflichtprogramm - sprich "alle LEDs an", könnte ich eventuell noch "umbiegen" mit einer arithmetischen Funktion. Bin noch dran.


Schönes Rest-Wochenende noch

Es grüßt
Oskar01
 
Der .byte Eintrag geht, wie Du schon sagtest, glaube ich, nur im dseg aufwärts und nicht im cseg.(Oder?)

Hallo Oscar,

mit .byte reserviert man im Datensegment (dseg) eine bestimmte Anzahl Bytes für eine Variable. Im Codesegment (cseg) wo du deine Daten für die LED-Ausgabe ablegst, verwendet man .db (define byte) oder .dw (define word) um Daten im Flash abzulegen, die man dann mit lpm oder elpm auslesen kann.

Gruß,
Dirk
 
.db Anweisung

Hallo,
so ganz zufrieden bin ich damit nicht.
Die .db Anwewisung funktioniert nur, wenn alle Konstanten hintereinandergesetzt werden und am Ende mit "Null" abgeschlossen werden.
Der Texteditor setzt mir aber oft auch Zeilenvorschub-Wagenrücklauf rein,
so daß im Assembiervorgang die Fehlermeldung unexpected /N kommt, schreibe ich nicht den Text einfach durch.

Habe gesehen, daß in Progs mehrere .db Anweisungen unter dem selben "Label" stehen.
Das funktioniert bei mir so nicht.
Also eine .db Anweisung nullterminiert ok.
Alle weiteren Anweisungen werden ignoriert.

Das verstehe ich nicht.


Gruß von Oskar01
 
Hallo,

kannst du dein Programm oder den entsprechenden Bereich deines Programms in einem Beitrag anhängen.

Man muss DefineByte ".db" nicht irgendwie abschließen, das ist nur interessant für Routinen, die auf ein Ende der Daten prüfen, zum Beispiel Routinen, die einen Text aus dem Flash-Memory lesen.

Das einzigste, was man bei .db beachten muss: Flash-Memory ist beim AVR nicht Byte- sondern Word-orientiert. Trägt man Daten in mehrere Zeilen (.db-Anweisungen) ein, muss man darauf achten, dass eine Zeile immer geradzahlige Byteeinträge enthält, ist dies nicht so, korrigiert AVR-Assembler durch Eintrag eines zusätzlichen Bytes (ich glaube 0x00 wird eingetragen).

Das Label über dem .db steht für die Anfangsadresse des ersten .db-Eintrags.

Gruss,
Dirk
 
.db-Anweisung

Danke schon mal, Dirk,

hier noch der entscheidende Code, wird eine zweite .db Zeile hinzugefügt, bleibt es bei "BETRIEBSBEREIT"-Anzeige.
Das ist nun nicht nur bei der LCD so, sondern bei Hex Werten, die mir ein Lauflicht symbolisieren sollen.
Natürlich ist hier "nullterminiert". Das ist ja dann auch korrekt so. Nur, wird der Text länger, paßt das Ganze nicht mehr ins Editorfenster, so daß ich gerne eine zweite und ggf. weitere Zeilen mit .db beginnend anfügen möchte. Habe das so ausprobiert, es wird dann bislang nur der Wert, der hinter der ersten .db- Anweisung steht gezeigt, auch , wenn dieser nicht nullterminiert war. Da gibt es dann auch beim Assemblieren Fehlermeldungen. Nullterminierung muß hier sein, nehme ich mal an. Da ja auch R0 auf Null geprüft wird. Da mal ansetzen, nehme ich an. Nur wie am geschicktesten.


HTML:
ldi	ZL, LOW(text*2)		;Adresse des Strings in den
ldi	ZH, HIGH(text*2)		;Z-Pointer laden
rcall	Ausgabe			;Funktion Ausgabe aufrufen
nop
rjmp	String_Loop2	;in den String2 springen bzw. Wiederholung
 
text:				;hier wird Text Zeile 1 abgelegt

.db " BETRIEBSBEREIT ",0  


Ausgabe:

lpm				;erstes Byte des Strings nach R0 lesen
tst	R0			;R0 auf 0 testen
breq	print_end		;wenn 0, dann zu print_end
mov	temp,	r0		;Inhalt von R0 nach temp kopieren
rcall	Ausgabe1		;Ausgabe ueber PortB
adiw	ZL,	1		;Adresse des Z-Pointers um 1 erhoehen
rjmp	Ausgabe 		;wieder zum Anfang springen

print_end:

ret

; Ausgabe1, sendet das Byte aus temp ueber den PortB
 
Ausgabe1:

out	daten,	temp
rcall	LCD_Datenausgabe                  
rcall	Verzoegerung2
nop
ret


Gruß von Oskar01
 
Hallo Oskar,

...Habe das so ausprobiert, es wird dann bislang nur der Wert, der hinter der ersten .db- Anweisung steht gezeigt, auch , wenn dieser nicht nullterminiert war. Da gibt es dann auch beim Assemblieren Fehlermeldungen. Nullterminierung muß hier sein, nehme ich mal an.

der Assembler benötigt keine Nullterminierung. Was der Assembler allerdings macht, wenn du eine .db-Zeile mit einer ungeraden Byteanzahl hast, ist ein Zero-Byte anhängen. In diesem Fall werden weitere .db-Zeilen nicht ausgegeben, da du ja bei 0x00 abbrichst.

Der Assembler warnt, wenn er ein Zero-Byte anhängt:
warning: A .db segment with an odd number of bytes is detected. A zero byte is added.

Achte mal darauf, dass in der ersten Zeile eine gerade Anzahl von Zeichen steht und probiere es nochmal.

Grüße,
Dirk
 
Proggi läuft jetzt ohne Warnmeldungen

Hallo Dirk,
nochmals vielen Dank für die Tipps.
Tatsächlich, Daten inclusive Nullterm müssen insgesamt geradzahlig sein, ebenso muß das Komma am Ende der .db-Zeilen entfallen. (Sonst "unexpected /N" -Fehlermeldung).

Gleichzeitig Timer-Interrupt und Lauflicht mit Z-Pointer sind hier also in einem Proggi zusammengefaßt. Es sind drei Loops eingebaut, die später noch per Tastendruck angewählt werden könnten, ist beabsichtigt so, könnte natürlich auch alles in ein Label schreiben, zeigt nur auf, daß man auch nacheinander "verschiedene" lpm's aufrufen kann.
Es soll so richtig funkeln. Die "Störung" durch den Timer-Interrupt ist also durchaus beabsichtigt hier.
(Die Videocam verschluckte allerdings einiges an Flimmereffekt.)

http://www.kbra01.de/Lauflicht3.mpg


Habe noch ein wenig experimentiert.
Zielsetzung: Interrupt-Routinen schaltbar gestalten.

Die Lösung- eigentlich Fuzzy-Logik- ich weiß, durch Laden falscher Werte in Timer
ab einer bestimmten Anzahl von Interupts über Label Timervar(iationen) den Interrupthandler übertölpeln. Rückkehr mit Sprung zum Hauptprogramm.
Interessant, wird das Statusregister auf Stack gesichert und wiederhergestellt, läuft das Programm stark verkürzt.
Deswegen hier lediglich ausgeremt dringelassen.

Der beabsichtige Effekt soll sein, daß ab "Leuchtband" das schnelle Flackern der Leuchtdioden aufhört aber bei Wiederholung von vorne das Flackern wieder einsetzt.

Es stellt sich natürlich die Frage, wie "disable" ich Interrupts reversibel im Verlaufe des Programms. Gut, den sei -Befehl (generelle Interruptfreigabe) durch Gegenbefehl unwirksam machen. Habe aber keine Idee, wie man das praktisch bewerkstelligen könnte ohne Tricks.

Hier der Code mit etwas ausführlicherer Kommentierung:

Das Lauflichtprogramm gliedert sich, wie oben schon gesagt, in drei Gruppen.
1.) Einzelne Leuchtdiode wandert erst schnell, dann immer langsamer werdend hin und her.
2.) Ein Leuchtband, vergleichbar mit einer Aussteuerungsanzeige am Kassettendeck, füllt sich und entleert sich wieder. Hierbei auch wieder ein Beschleunigungsterm drin.
3.) Abwechselndes Aufleuchten von LEDs mit jeweils einer LED Lücke dazwischen.
Natürlich auch wieder eine stärker betonte Verlangsamung mit drin, bis zum Quasi Stillstand und Blinken einer einzelnen LED.
Dann Wiederholung von vorne.

Jetzt sollte nur noch der "Klettereffekt" durch zusätzliches Flackern bei Programmabschnitt 1 mithilfe des Timer-Interrupts verdeutlicht werden. Stimmt noch nicht ganz, ok, auch das "erste" Leuchtband flackert noch. Siehe Video, das leider am Ende etwas verkürzt werden mußte, da der FTP-Server mittem im Upload crashte vor ner halben Stunde.

Code:
;* Lauflicht mit Timer-Interrupt-Flackereffekt,
;* Verlassen und Wiederherstellen der 
;* Interruptroutine 
;* CPU Takt 4 MHz
;* LED-Ausgabe auf Port B
;

.nolist
.include "8515def.inc"
.list
 
.def temp = r16
.def temp1 = r17
.def temp2 = r18
.def temp3 = r19
.def zeit = r20
.def zeit1 = r21
.def zeit2 = r22

.equ leds = portb
 
.CSEG 
.org 0x0000

rjmp Hauptprogramm

.org 0x007 ;.equ OVF0addr=$007;Overflow0 Interrupt Vector Address

rjmp Timerueberlauf

Hauptprogramm:	

ldi	temp,	low(RAMEND)	;Stackpointer initialisieren
out	SPL,	temp                    
ldi	temp,	high(RAMEND)
out	SPH,	temp                    
ldi	temp,	0xFF	;Portzuweisung: durch Laden von 
out	DDRB,	temp	;HexFF Datenrichtung PortB Ausgang  
ldi	temp,	0x05	;Timer 1 Vorteiler 1:1024
out	TCCR0,	temp
ldi	temp,	0x02	;Interruptausgabe mit TOIE0 enablen
out	TIMSK,	temp
ldi	temp3,	0x00
sei			;generelle Interruptfreigabe
rjmp Lauflicht

Timerueberlauf:

;clr	temp2
;in	temp2,	SREG	;Sichert Statusregister
;push	temp2		;auf Stack
ldi	temp1,	0xFF	;bewirkt Flackern aller LEDs
out	leds,	temp1
inc	temp3
cpi	temp3,	0x85	;nach 133 "Breaks"
breq	Timervar	;Verlassen des Timer-Interrupts 
;pop	temp2		;Wiederherstellen 
;out	SREG, temp2 ;des Statusregisters
reti

Timervar:		;Verlassen des Timer-
ldi	temp,	0x06	;Interrupts durch Laden
out	TCCR0,	temp	;"falscher" Werte in TCCR0
ldi	temp,	0x02	;Interruptausgabe mit TOIE0 enablen
out	TIMSK,	temp
ret

Lauflicht:

rcall	Lichtpunkt
rcall	Timerreset
rjmp	Lauflicht
;ret

Timerreset:			;Wiederherstellen der
				;Timer-Interrupt-Routine
rjmp	Hauptprogramm
;ret

Lichtpunkt:

ldi	ZL,	LOW(leds0*2)	;Adresse des Strings0 in den
ldi	ZH,	HIGH(leds0*2)	;Z-Pointer laden
rcall	print			;Funktion print aufrufen
rjmp	Leuchtband		;in den naechsten String springen
 
;Konstanten von String0 werden hier im Flash abgelegt:
 
leds0:

.db 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F 
.db 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE
.db 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F
.db 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE
.db 0xFE, 0xFE, 0xFD, 0xFD, 0xFD, 0xFB, 0xFB, 0xFB
.db 0xFB, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xEF, 0xEF
.db 0xEF, 0xEF, 0xEF, 0xEF, 0xDF, 0xDF, 0xDF, 0xDF
.db 0xDF, 0xDF, 0xDF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF
.db 0xBF, 0xBF, 0xBF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F
.db 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0	

;inclusive Nullterm geradzahlige Anzahl Bytes,
;sonst "padding-byte-mismatch"-Warnmeldung
 
print:

lpm				;erstes Byte des Strings0 nach R0 lesen
tst	R0			;R0 auf 0 testen
breq	print_end		;wenn 0, dann zu print_end
mov	temp,	r0		;Inhalt von R0 nach temp kopieren
rcall	ausgabe			;Ausgabe ueber PortB
adiw	ZL:ZH,	1		;Adresse des Z-Pointers um 1 erhoehen
rjmp	print			;zum Anfang springen, um naechstes 
				;Byte aus dem dseg-Label leds0 ;zu holen
print_end:
ret
 
; Ausgabe, sendet das Byte aus temp ueber den PortB
 
ausgabe:

out	leds,	temp                  
rcall	Warten
ret

Leuchtband:

ldi	ZL,	LOW(leds1*2)	;Adresse des Strings1 in den
ldi	ZH,	HIGH(leds1*2)	;Z-Pointer laden
rcall	print1			;Funktion print1 aufrufen
rjmp	Toggle 

print1:

lpm				;erstes Byte des Strings1 nach R0 lesen
tst	R0			;R0 auf 0 testen
breq	print_end1		;wenn 0, dann zu print_end1
mov	temp,	r0		;Inhalt von R0 nach temp kopieren
rcall	ausgabe                    
adiw	ZL:ZH,	1		;Adresse des Z-Pointers um 1 erhoehen
rjmp	print1			;zum Anfang springen, um naechstes 
				;Byte aus dem dseg-Label leds1 ;zu holen

print_end1:
ret	  

leds1:				;Konstanten von String1

.db 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F
.db 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F
.db 0x3F, 0x3F, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
.db 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0xF0, 0x0F
.db 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F
.db 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0	

;inclusive Nullterm geradzahlige Anzahl Bytes,
;sonst "padding-byte-mismatch"-Warnmeldung

Toggle:

ldi	ZL,	LOW(leds2*2)	;Adresse des Strings2 in den
ldi	ZH,	HIGH(leds2*2)	;Z-Pointer laden
rcall	print2			;Funktion print1 aufrufen
;rjmp Lauflicht
ret 

print2:

lpm				;erstes Byte des Strings2 nach R0 lesen
tst	R0			;R0 auf 0 testen
breq	print_end2		;wenn 0, dann zu print_end2
mov	temp,	r0		;Inhalt von R0 nach temp kopieren
rcall	ausgabe                    
adiw	ZL:ZH,	1		;Adresse des Z-Pointers um 1 erhoehen
rjmp	print2			;zum Anfang springen, um naechstes 
				;Byte aus dem dseg-Label leds2 ;zu holen
print_end2:
ret	  

leds2:				;Konstanten von String2

.db 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 
.db 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0x55
.db 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55
.db 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55
.db 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55
.db 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
.db 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA 
.db 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55
.db 0x55, 0x55, 0x55, 0x55, 0xEF, 0xFF, 0xEF, 0xFF		
.db 0xEF, 0xFF, 0xEF, 0xFF, 0xFF, 0

;inclusive Nullterm geradzahlige Anzahl Bytes,
;sonst "padding-byte-mismatch"-Warnmeldung

Warten:		;Pause

ldi	zeit,	0xFF
ldi	zeit1,	0xFF
ldi	zeit2,	0x85
push	zeit
push	zeit1
push	zeit2

Verzoegerungs_Schleife: 

dec	zeit
cpi	zeit,	1
brlt	Verzoegerungs_Schleife
ldi	zeit,	0xFF
dec	zeit1
cpi	zeit1,	1
brlt	Verzoegerungs_Schleife
ldi	zeit1,	0xFF
dec	zeit2
cpi	zeit2,	1
brlt	Verzoegerungs_Schleife
pop	zeit2
pop	zeit1
pop	zeit
ret

Schönes Bastel-Wochenende am heimischen PC noch... wünscht,
Oskar01
 
Doku war fehlerhaft

Hallo,
also "übertölpeln" brauchte man hier nichts, denn der Timer kann auch mit Laden von O inaktiviert werden. Das ist dann syntaktisch völlig richtig und hat mit "Fuzzy"-Logik nichts mehr zu tun.
So, unten noch das korrigierte und etwas expandierte Proggi, das bei Gelegenheit noch um die Dimmfunktion erweitert werden wird.

Schönen Sonntagabend noch,
Euer Oskar01


P.S.: Das ausprobierte Pulsweitenmodulationsprogramm lief schon, nur kann ich es so nicht in dieses Proggi integrieren, weil zu wenig Register vorhanden sind, der Z-Pointer nimmt ja auch die letzten Register in Beschlag. Vielleicht fällt mir noch etwas dazu ein. Bis demnächst.
 

Anhänge

  • Lauflicht3108.txt
    7,7 KB · Aufrufe: 6
Hallo Oskar,

... weil zu wenig Register vorhanden sind, der Z-Pointer nimmt ja auch die letzten Register in Beschlag. Vielleicht fällt mir noch etwas dazu ein. Bis demnächst.


mir ist aufgefallen, dass du das SRAM im AVR nicht verwendest. Normalerweise nutzt man die Register r0 bis r31 als Arbeitsregister, in kleinen Programmen kann man hier auch seine Variablen ablegen, die dann permanent ein Arbeitsregister belegen. Wenn es allerdings knapp wird, nutzt man dann das SRAM. Die Arithmetic Logic Unit (ALU) hat nur Zugriff auf die Register r0 bis r31, nicht aber auf das SRAM. Das heisst, dass du keine Rechenoperationen, logische Vergleiche (bedingte Sprünge) usw. mit dem SRAM durchführen kannst. Du musst zuerst den Inhalt einer SRAM-Adresse in ein Arbeitsregister kopieren (am besten ab Register r16), dann die Operation durchführen und ggf. das Ergebnis wieder im SRAM ablegen.

Eine Übersicht der Data-Transfer-Instructions findest du ziemlich am Ende des Datasheets deines AVRs.

Grüße
Dirk
 
.dseg und .BYTE verwendet

Hallo,
danke für den Tip, Dirk,
habe wieder etwas experimentiert. Man konnte nun Register einsparen.
Einmal durch Verwendung von Stack-Operationen, dann durch Verwendung von Datensegment-Verschiebung von Ladewerten der Zeitschleifen-Register.
Summa Summarum ergibt sich zwar ein Einspareffekt bei den Temporär-Registern, allerdings wiederum ein erhöhter Programminhalt durch das Umladen auf das dseg, was mir - siehe unten - nur in Einzelschritten gelungen ist.

Hier nun das abgeänderte Proggi als Dateianhang:


Schönen Sonntag noch.....
es grüßt Oskar01

P.S.:Leider klappte es mit dem Z-Pointer nicht so ganz, das dseg zu optimieren. Also,
Anzahl der Bytes auf mehr als 1 festzulegen und dann, wie im Analogieschluß bei der .db-Anweisung, nun auch auf das dseg zuzugreifen.
Die verschiedenen Befehle, die so bekannt sind, mal ausprobiert, es ergibt sich ein ganz eigenartiges Verhalten des MC.
Das Programm scheint nur hochzuzählen, bis das SRAM vollgeschrieben ist, dann bricht das Programm ab. Also, die Leuchtdioden blinken wie beim Incrementvorgang, haben aber nichts mit dem eingegebenen Programm gemein.
Die Anweisung Z+ gibt mir Rätsel auf. Scheinbar wird diese vom ATMega8515 nicht in der Form unterstützt, wie sie im Net angegeben ist. Aber auch die adiw-Anweisung hilft hier nicht. Nehme an, das hat etwas mit dem fehlenden "Padding-Byte-Ergänzungs-Feature" beim Assembler zu tun, die zwar beim cseg bei der .db-Anweisung funktioniert, im dseg aber wohl so nicht.
Hier noch der kurze Test-Code mit nur 2 Bytes im dseg:
Code:
;* Lauflicht mit DSEG-Daten,
;* CPU Takt 4 MHz
;* LED-Ausgabe auf Port B
;

.nolist
.include "8515def.inc"
.list
 
.def temp = r16
.def zeit = r17
.def zeit1 = r18
.def zeit2 = r19

.equ leds = portb
 
.CSEG 
.org 0x0000

rjmp Hauptprogramm

Hauptprogramm:	

ldi	temp,	low(RAMEND)	;Stackpointer initialisieren
out	SPL,	temp                    
ldi	temp,	high(RAMEND)
out	SPH,	temp                    
ldi	temp,	0xFF	;Portzuweisung: durch Laden von 
out	DDRB,	temp	;HexFF Datenrichtung PortB Ausgang  
ldi	r30,	LOW(led_0)
ldi	r31,	HIGH(led_0)
ldi	temp,	0x01
st	Z,	temp
adiw ZL:ZH, 1
ldi	temp,	0x03
st	Z,	temp

rjmp	Ausgabe

Ausgabe:


ld	temp,	Z
out	leds,	temp
rcall	Warten
rcall	Warten
rcall	Warten
adiw	ZL:ZH, 1
ld	temp,	Z
out	leds,	temp
rcall	Warten
rjmp Ende

Ende:
rjmp Ende

.dseg

led_0:	.BYTE 2


.cseg

Warten:		;Pause

ldi	zeit,	0xFF
ldi	zeit1,	0xFF
ldi	zeit2,	0x85
push	zeit
push	zeit1
push	zeit2

Verzoegerungs_Schleife: 

dec	zeit
cpi	zeit,	1
brlt	Verzoegerungs_Schleife
ldi	zeit,	0xFF
dec	zeit1
cpi	zeit1,	1
brlt	Verzoegerungs_Schleife
ldi	zeit1,	0xFF
dec	zeit2
cpi	zeit2,	1
brlt	Verzoegerungs_Schleife
pop	zeit2
pop	zeit1
pop	zeit
ret

habe auch mal r30 bzw. r31 mit clr gelöscht, hilft aber auch nicht, noch nicht einmal die einfache Z- (also nicht Z+)- Anweisung bringt den gewünschten Erfolg.
Entweder leuchten alle LEDs oder nur die ersten beiden sind aus, was dafür spricht, daß nur der zuletzt geladene Wert auch tatsächlich übernommen wird.
 

Anhänge

  • Lauflicht060908.txt
    7,7 KB · Aufrufe: 3
Hallo Oskar,

du musst den Adresszeiger für deine SRAM-Variablen initialisieren (.org). Beim Lesen aus dem SRAM erhöhst du durch adiw erneut den Inhalt im Z-Register, so dass du dann bei der indirekten Adressierung (ld) auf die zwei Speicherstellen hinter der Variable LED_0 zugreifst.
Wegen dieser Padding-Byte-Sache: Das SRAM ist byte-orientiert, nicht word-orientiert wie beim Flash, es gibt hier kein Padding-byte, der Zugriff erfolgt direkt über Byteadresse.

Hier mal ein bisschen Code, wie man auf SRAM zugreift (es ist natürlich auch mit ld, ldd usw. möglich)
Code:
.dseg
.org 0x60   ; Die ersten 96 Speicherstellen sind dem IO-Memory-Bereich zugeordnet,
            , ab Adresse 0x60 sind sie dem SRAM zugeordnet

LED_0:  .byte 2   ; Adresse 0x60 und 0x61


; Der Zugriff erfolgt dann zum Beispiel folgendermassen:

; In das SRAM schreiben
ldi temp, 0xFF
sts LED_0, temp    ; niederwertige Byte (Adresse 0x60)
ldi temp, 0xAA
sts LED_0+1, temp  ; höherwertige Byte (Adresse 0x61)

; ....

; Aus dem SRAM lesen
lds temp, LED_0
; ...
lds temp, LED_0+1
Grüße
Dirk
 
jetzt gehts...

Hallo Dirk,
erst mal vielen Dank für Deinen Tip.

Hier nun das geänderte Testprogramm, wobei mir auffiel,
daß die .org 0x0060 Angabe für das dseg auch entfallen kann.

Die Angabe für das dseg können auch an anderer Stelle des Listings als direkt am Anfang positioniert sein, nur immer die Direktive .dseg muß am Ende von einer .cseg-Direktive mit Wechsel zum Codesegment gefolgt sein, sonst wird alles nach der .dseg-Direktive als dorthin-zu-schreibendes Programm gedeutet.

Noch ein Schmankerl zum Sonntagsausklang:
Ein Zusatz, der bewirken soll, daß das Programm nach definierten Wiederholungen sich in den Schlafmodus versetzt, woraus es - jetzt noch ohne "Watchdog" - nur mit manuellem Reset wiedererweckt werden kann.

Vielen Dank nochmals,
bis dann....
Gruß von Oskar01
 

Anhänge

  • Dsegsleep.txt
    2,2 KB · Aufrufe: 3
Hallo Oskar,
... wobei mir auffiel,
daß die .org 0x0060 Angabe für das dseg auch entfallen kann.

das funktioniert nur auf den ersten Blick. Du schreibst und liest dann ja direkt im IO-Memory-Bereich. Je nachdem auf welcher Adresse im IO-Memory-Bereich deine Variablen liegen, änderst du zum Beispiel einen Port, die Konfiguration eines Timers, Inhalte im Register-File oder was anderes, also da kann dann alles mögliche passieren!

... also immer Startadresse im DataSegment festlegen!

Grüße
Dirk
 
...ist auch drin im angegenenen Proggi

Hallo Dirk,
das angehängte Programm hat natürlich die vorgeschlagene und richtige Syntax.

PHP:
.dseg
.org 0x0060		;Die ersten 96 Speicherstellen
			;sind dem IO-Memory-Bereich
			;zugeordnet0x60 sind sie dem
			;SRAM zugeordnet

led_0:	.byte 2		;Adresse 0x60 und 0x61
zeit_0:	.byte 3		;Adresse 0x62 bis 0x64

.cseg 
.org 0x0000

Und, jetzt, wo Du es sagst, ist mir noch was aufgefallen,
etwas, was nicht sein dürfte, wenn alles korrekt programmiert wäre:
Das Impuls-Pause-Verhältnis der Leuchtdiodenanzeige ist nicht mehr 1:1, wenn die .org 0x0060-Angabe fehlt.

Dann bemerkte ich noch, daß die Zeitschleifen etwas langsamer laufen. Das hat aber wohl damit nichts zu tun.
Das liegt wohl daran, wie ich irgendwo nachgelesen habe, daß die Zugriffszeiten auf das SRAM doppelt so hoch sind. Also bei 4 MHz nicht pro Taktzyklus die besagten 250 Nanosekunden, sondern deren 500.
Das ist vielleicht garnicht mal so schlecht, wenn ich möglichst große Zeitverzögerungen händeringend realisieren möchte.

Gruß von Oskar01
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)