Hallo!!!
Ich bin blutiger Anfänger was Assembler und µC angeht. Ich benutzte das
AVR Studio 4 und einen ATmega 8 mit 10 Mhz getaktet.
Ich würde nun gerne eine (Software)-PWM mit 10 Hz (sodass eine LED
blinkt) realisieren.
Ich weiß nun nicht richtig, wie ich die Subroutine mit dem Runterzählen
von 1.000.000 anstellen soll ( sollte am ende 10Hz entsprechen, oder?).
Ich komme mit den Befehlen nicht klar.
Aktueller Stand, der so nicht funktioniert, aus der Subroutine "erste"
kommt er nicht raus...
****************************************************************
.include "m8def.inc"
LDI r16, HIGH(RAMEND) ; Oberes Byte
OUT SPH,r16 ; an Stapelzeiger
LDI r16, LOW(RAMEND) ; Unteres Byte
OUT SPL,r16 ; an Stapelzeiger
ldi r16, 0b00000001
out ddrb, r16
; Hauptprogramm
Haupt:
;definieren der Register für 1.000.000
.equ ges = 1000000 ;gesamtes register
ldi r16, low(ges) ;bit 0-8
ldi r17, byte2(ges) ;bit 8-16
ldi r18, byte3(ges) ;bit 16-24
rcall erste
rjmp haupt
erste:
;Subtrahieren mit 1
ldi r19, 0x01
sub r16, r19
sbc r17, r19
sbc r18, r19
breq weiter
rjmp erste
weiter: ; hier wird der Port gesetzt.
ldi r16, 0x01
out portb, r16
rjmp haupt
*************************************************************
Wie funktioniert das mit dem zählen??? Kann mir da bitte jemand
weiterhelfen???
Und Bitte nicht über Sinn oder Unsinn des Programmes diskutieren, es
dient lediglich dem lernen von Assembler, das es mit dem integrierten
Timer einfacher und vorallem Sinnvoller geht weiß ich auch, Danke!!!
MFG
also, deine 24bit zahl zerlegst du in drei achtBit zahlen.
jedes register in einem.
r18:r17:r16
das ist ok. aber ob das mit dem ...byte(2) geht, glaub ich ne
beim rechnen von minus eins:
dazu gibt es einen speziellen befehl: DEC register. => siehe
instr.summary
beim subrahieren der drei register, darfst du das erstmal NUR mit dem
niederwertigstens machen, und nur falls du bei dieser rechnung:
r16=0 ist und du da jetzt eins abzieht: dann kommt (wegen acht bit)
nach der ausführung von dec r16 raus:
r16=255 und NUR in diesem fall darfst du vom nächsten (hier r17) eins
abziehen!! und geht dieses (r17) von null auf 255, dann im
nächsthöheren... also r18...
rechne doch mal, wie in der schule gelernt, schriftlich: 104-1. das
ergebnis wieder minus eins.. unso weiter, und beobachte, wann du von der
nächsthöheren stelle auch was abziehst...
Hallo Gast,
1. "blinken" ist keine PWM
2. wenn Du blinken willst, musst Du auch den Zustand der LED ändern
3. Du musst mehrere Schleifen schachteln
Gruss Otto
Ok, vielen Dank erstmal.
Ich denke, das mit dem blinken wäre mir spästens nachdem der Zähler
funktioniert hätte auch aufgefallen :D.
und wie realisiere ich das mit dem runterzählen, gibt es dafür bestimmte
Befehle, oder muss ich jedes Bit in einer einzelnen Subroutine bis zum
Übertrag herunterzählen lassen, steh da gerade etwas auf dem Schlauch,
sorry.
MFG
LDI r18, 255 (15)
schleife3:
LDI r17, 255 (255)
schleife2:
LDI r16, 255 (255)
schleife1:
DEC r16
BRNE schleife1
DEC r17
BRNE schleife2
DEC r18
BRNE schleife3
...
dieser zähler zählt von (255hoch3=16'581'375) bis null runter, dann
gehts mit ... weiter.. die drei werte musst du noch anpassen. Die Werte
in der Klammer ergeben fast 1Million durchläufe (975375mal)
ok vielen Dank, dass sollte mir weiter helfen...
wollte gerade schon Fragen, wo ich infos zu "djnz" finde, im Datenblatt
ist er schließlich nicht drin...
MFG
so, hab jetzt ein neues Programm geschrieben, laut Debugger funktioniert
es, die Realität sieht leider anders aus :(.
das Oszi zeigt leider auch keine Reaktion, kommt ne komplette
Gleichspannung von 5 V raus...
Ist mein Controller vielleicht defekt??? Datenübertragung hat alles
wunderbar funktioniert...
Vielleicht findet jemand einen Fehler, ich danke euch schonmal im
voraus, wie immer eben ;)...
MFG
************************************************************************
**
;definitionsdatei
.include "m8def.inc"
; einrichten des Stacks
LDI r16, HIGH(RAMEND) ; Oberes Byte
OUT SPH,r16 ; an Stapelzeiger
LDI r16, LOW(RAMEND) ; Unteres Byte
OUT SPL,r16 ; an Stapelzeiger
;Ausgänge konfigurieren
ldi r16, 0b00000001
out ddrb, r16
; Hauptprogramm
Haupt:
;auschalten des ausgangs
clr r19
out portb, r19
.def byt1 = r20 ;R16
.def byt2 = r21 ;R17
; Hier wird runtergezählt bis 0, und dann der Ausgang gesetzt.
; bewerten der Register
; *********hier die Zeit einstellen, anhand der werte der
bits**********
;
**********************************************************************
ldi byt1, 64 ;bit 0-8 (entspricht R16)
ldi byt2, 13 ;bit 8-16 (entspricht R17)
ldi r18, 3 ;bit 16-24
;die werte noch in die register schreiben
mov r16, byt1
mov r17, byt2
;das ergibt 1 mio ( 00001111.01000010.01000000 (24bit))
rcall schleife1 ; bit 0-8 herunterzählen
schleife1:
dec r16
breq schleife2
rcall schleife1
schleife2:
mov r16, byt1
dec r17
breq schleife3
rcall schleife1
schleife3:
mov r16, byt1
mov r17, byt2
dec r18
breq einschalten
rcall schleife1
;port einschalten nach ...mio durchläufen
einschalten:
ldi r19, 0x01
out portb, r19
rcall haupt
************************************************************************
**