Technik97
13.07.2011, 11:59
Hallo, ich habe folgendes Programm geschrieben::cool:
.NOLIST ; List-Output unterdrücken
.INCLUDE <m32def.inc> ; das gibt es für jeden Controllertyp
.LIST ; List-Output wieder aufdrehen
;------------------------------------------------------
; Eigene Defines
;------------------------------------------------------
.def tmp = r16
.def lowByte = r17
.def highByte = r18
.def channel = r19
.EQU clk = PA4
.EQU richtung = PA5
.EQU strom = PA6
.def time = r20
.def vergleich = r21
.def schluss = r22
.def bitmask = r23
.equ PWM_1 = PD4
.equ PWM_2 = PD5
.equ Richtung1 = PB1
.equ Richtung2 = PB3
.def zaehler = r24
.def zaehlen = r25
.def test = r26
.def test2 = r27
.CSEG ; was nun folgt, gehört in den FLASH-Speicher
.MACRO warten
ldi R17, @0 ; Lade direkten Wert in R17 1 Zyklus
LOOP2: ldi R18, 224 ; Lade direkten Wert in R18 1 Zyklus
LOOP1: ldi R19, 235 ; Lade direkten Wert in R19 1 Zyklus
LOOP0: dec R19 ; Dekrementiere R19 -> Z ist gesetzt, wenn R19 == 0
; 1 Zyklus
brne LOOP0 ; Teste Zero Flag (Z)
; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
dec R18 ; Dekrementiere R18 -> Z ist gesetzt, wenn R18 == 0
; 1 Zyklus
brne LOOP1 ; Teste Zero Flag (Z)
; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
dec R17 ; Dekrementiere R17 -> Z ist gesetzt, wenn R17 == 0
; 1 Zyklus
brne LOOP2 ; Teste Zero Flag (Z)
.ENDMACRO
;------------------------------------------------------
; Start Adresse 0000
;------------------------------------------------------
RESET:
jmp INIT ; springen nach "INIT"
.ORG INT_VECTORS_SIZE ; für die Vektoren Platz lassen
;------------------------------------------------------
; Initialisierung
;------------------------------------------------------
INIT:
ldi r24,high(RAMEND) ;Stack Pointer setzen
out SPH,r24 ; "RAMEND" aus m32def.inc
ldi r24,low(RAMEND) ;
out SPL,r24 ;
LDI tmp, 127 ; der wert "255" = FF ins allgemeine Register R24
OUT DDRA, tmp ; das kommt ins Controll-register f. PortC
; dadurch ist Port auf OUTPUT gestellt
sbi DDRA,clk ;clk Pin als Ausgang
sbi DDRA,richtung ;richtung Pin als Ausgang
sbi DDRA,strom ;strom Pin als Ausgang
sbi PORTA,clk ;clk Bit setzen
cbi PORTA,richtung ;Richtung vorgeben
sbi PORTA,strom ;Richtung vorgeben
LDI tmp, (1<<PWM_2)|(1<<PWM_1) ; PWM Bits auf eins
OUT DDRD, tmp ; das kommt ins Controll-Register f. PortD
; dadurch sin´d Pullups an Port an
; Port C auf Ausgang schalten:
ldi tmp, 0xFF
out DDRC, tmp
out PORTC, tmp
; ADC initialisieren
ldi tmp, 0b00000111 ;externe Referenzspannung (5V) / Kanal 7
out ADMUX, tmp
;mit "Free Run" und Vorteiler 128:
ldi tmp, ((1<<ADEN)|(1<<ADSC)|(1<<ADATE)) + 7 ;
out ADCSR, tmp
LDI bitmask, 125 ; Bitmaske definieren
LDI tmp, (1<<PWM_1)
EOR bitmask,tmp
ldi zaehlen, 0
ldi zaehler, 0
ldi test2, 2
STEP:
sbis PORTA,CLK ;prüfe, ob CLK gesetzt ist
rjmp aus ;dann überspringe diese Zeile
cbi PORTA,CLK ;und schalte CLK ein
warten 5
; ADC einlesen:
in lowByte, ADCL ; immer zuerst low byte lesen
in highByte, ADCH ; danach das mittlerweile gesperrte high byte
; zweimal nach rechts schieben über carry macht aus 10-Bit-Wert
;einen 8-Bit-Wert (damit er an einem Port angezeigt werden kann)
ror highByte
ror lowByte
ror highByte
ror lowByte
mov tmp, lowByte
out PORTC, tmp ; Wert über LEDs anzeigen
rjmp STEP
aus:
inc test
CP test2,test
brcs erhoehen
sbi PORTA,CLK ;CLK war gesetzt -> ausschalten
warten 5
; ADC einlesen:
in lowByte, ADCL ; immer zuerst low byte lesen
in highByte, ADCH ; danach das mittlerweile gesperrte high byte
; zweimal nach rechts schieben über carry macht aus 10-Bit-Wert
;einen 8-Bit-Wert (damit er an einem Port angezeigt werden kann)
ror highByte
ror lowByte
ror highByte
ror lowByte
mov tmp, lowByte
out PORTC, tmp ; Wert über LEDs anzeigen
ldi schluss, 250
CP tmp, schluss
brcs Hauptschleife
rjmp STEP
Hauptschleife:
LDI tmp, (1<<PWM_2)|(1<<PWM_1) ; PWM Bits auf eins
OUT DDRD, tmp
LDI tmp, (1<<Richtung1) ; Richtungs Bits auf eins
OUT DDRB, tmp ; das kommt ins Controll-Register f. PortB
; dadurch sin Pullups an Por
inc zaehler
COM tmp ; tmp complementieren
EOR tmp, bitmask ; XOR
OUT PortD, tmp ; tmp auf PortD schreiben
warten 1
COM tmp ; tmp complementieren
EOR tmp, bitmask ; XOR
OUT PortD, tmp ; tmp auf PortD schreiben
warten 4
CP zaehlen, zaehler
brcs Ende
rjmp Hauptschleife
Ende:
ldi zaehlen, 0
ldi zaehler, 0
LDI tmp, (0<<PWM_2)|(0<<PWM_1) ; PWM Bits auf eins
OUT DDRD, tmp
LDI tmp, (0<<Richtung1) ; Richtungs Bits auf eins
OUT DDRB, tmp ; das kommt ins Controll-Register f. PortB
; dadurch sin Pullups an Por
rjmp STEP
erhoehen:
inc zaehlen
ldi test, 0
jmp aus
Bei mir dreht sich der Schrittmotor und wenn man am Lichtsensor Licht macht:
1. dreht sich der PWM zu schnell
2. und nicht in die Position von wo das Licht gekommen ist.
:confused:
Ich will das Programm nicht groß ändern, z.B. will ich nicht für den PWM
einen Timer machen...
Danke schon im Vorraus. Ich bin gespannt auf eure Vorschläge;)
Mit freundlichen Grüßen, technik97;)
.NOLIST ; List-Output unterdrücken
.INCLUDE <m32def.inc> ; das gibt es für jeden Controllertyp
.LIST ; List-Output wieder aufdrehen
;------------------------------------------------------
; Eigene Defines
;------------------------------------------------------
.def tmp = r16
.def lowByte = r17
.def highByte = r18
.def channel = r19
.EQU clk = PA4
.EQU richtung = PA5
.EQU strom = PA6
.def time = r20
.def vergleich = r21
.def schluss = r22
.def bitmask = r23
.equ PWM_1 = PD4
.equ PWM_2 = PD5
.equ Richtung1 = PB1
.equ Richtung2 = PB3
.def zaehler = r24
.def zaehlen = r25
.def test = r26
.def test2 = r27
.CSEG ; was nun folgt, gehört in den FLASH-Speicher
.MACRO warten
ldi R17, @0 ; Lade direkten Wert in R17 1 Zyklus
LOOP2: ldi R18, 224 ; Lade direkten Wert in R18 1 Zyklus
LOOP1: ldi R19, 235 ; Lade direkten Wert in R19 1 Zyklus
LOOP0: dec R19 ; Dekrementiere R19 -> Z ist gesetzt, wenn R19 == 0
; 1 Zyklus
brne LOOP0 ; Teste Zero Flag (Z)
; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
dec R18 ; Dekrementiere R18 -> Z ist gesetzt, wenn R18 == 0
; 1 Zyklus
brne LOOP1 ; Teste Zero Flag (Z)
; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
dec R17 ; Dekrementiere R17 -> Z ist gesetzt, wenn R17 == 0
; 1 Zyklus
brne LOOP2 ; Teste Zero Flag (Z)
.ENDMACRO
;------------------------------------------------------
; Start Adresse 0000
;------------------------------------------------------
RESET:
jmp INIT ; springen nach "INIT"
.ORG INT_VECTORS_SIZE ; für die Vektoren Platz lassen
;------------------------------------------------------
; Initialisierung
;------------------------------------------------------
INIT:
ldi r24,high(RAMEND) ;Stack Pointer setzen
out SPH,r24 ; "RAMEND" aus m32def.inc
ldi r24,low(RAMEND) ;
out SPL,r24 ;
LDI tmp, 127 ; der wert "255" = FF ins allgemeine Register R24
OUT DDRA, tmp ; das kommt ins Controll-register f. PortC
; dadurch ist Port auf OUTPUT gestellt
sbi DDRA,clk ;clk Pin als Ausgang
sbi DDRA,richtung ;richtung Pin als Ausgang
sbi DDRA,strom ;strom Pin als Ausgang
sbi PORTA,clk ;clk Bit setzen
cbi PORTA,richtung ;Richtung vorgeben
sbi PORTA,strom ;Richtung vorgeben
LDI tmp, (1<<PWM_2)|(1<<PWM_1) ; PWM Bits auf eins
OUT DDRD, tmp ; das kommt ins Controll-Register f. PortD
; dadurch sin´d Pullups an Port an
; Port C auf Ausgang schalten:
ldi tmp, 0xFF
out DDRC, tmp
out PORTC, tmp
; ADC initialisieren
ldi tmp, 0b00000111 ;externe Referenzspannung (5V) / Kanal 7
out ADMUX, tmp
;mit "Free Run" und Vorteiler 128:
ldi tmp, ((1<<ADEN)|(1<<ADSC)|(1<<ADATE)) + 7 ;
out ADCSR, tmp
LDI bitmask, 125 ; Bitmaske definieren
LDI tmp, (1<<PWM_1)
EOR bitmask,tmp
ldi zaehlen, 0
ldi zaehler, 0
ldi test2, 2
STEP:
sbis PORTA,CLK ;prüfe, ob CLK gesetzt ist
rjmp aus ;dann überspringe diese Zeile
cbi PORTA,CLK ;und schalte CLK ein
warten 5
; ADC einlesen:
in lowByte, ADCL ; immer zuerst low byte lesen
in highByte, ADCH ; danach das mittlerweile gesperrte high byte
; zweimal nach rechts schieben über carry macht aus 10-Bit-Wert
;einen 8-Bit-Wert (damit er an einem Port angezeigt werden kann)
ror highByte
ror lowByte
ror highByte
ror lowByte
mov tmp, lowByte
out PORTC, tmp ; Wert über LEDs anzeigen
rjmp STEP
aus:
inc test
CP test2,test
brcs erhoehen
sbi PORTA,CLK ;CLK war gesetzt -> ausschalten
warten 5
; ADC einlesen:
in lowByte, ADCL ; immer zuerst low byte lesen
in highByte, ADCH ; danach das mittlerweile gesperrte high byte
; zweimal nach rechts schieben über carry macht aus 10-Bit-Wert
;einen 8-Bit-Wert (damit er an einem Port angezeigt werden kann)
ror highByte
ror lowByte
ror highByte
ror lowByte
mov tmp, lowByte
out PORTC, tmp ; Wert über LEDs anzeigen
ldi schluss, 250
CP tmp, schluss
brcs Hauptschleife
rjmp STEP
Hauptschleife:
LDI tmp, (1<<PWM_2)|(1<<PWM_1) ; PWM Bits auf eins
OUT DDRD, tmp
LDI tmp, (1<<Richtung1) ; Richtungs Bits auf eins
OUT DDRB, tmp ; das kommt ins Controll-Register f. PortB
; dadurch sin Pullups an Por
inc zaehler
COM tmp ; tmp complementieren
EOR tmp, bitmask ; XOR
OUT PortD, tmp ; tmp auf PortD schreiben
warten 1
COM tmp ; tmp complementieren
EOR tmp, bitmask ; XOR
OUT PortD, tmp ; tmp auf PortD schreiben
warten 4
CP zaehlen, zaehler
brcs Ende
rjmp Hauptschleife
Ende:
ldi zaehlen, 0
ldi zaehler, 0
LDI tmp, (0<<PWM_2)|(0<<PWM_1) ; PWM Bits auf eins
OUT DDRD, tmp
LDI tmp, (0<<Richtung1) ; Richtungs Bits auf eins
OUT DDRB, tmp ; das kommt ins Controll-Register f. PortB
; dadurch sin Pullups an Por
rjmp STEP
erhoehen:
inc zaehlen
ldi test, 0
jmp aus
Bei mir dreht sich der Schrittmotor und wenn man am Lichtsensor Licht macht:
1. dreht sich der PWM zu schnell
2. und nicht in die Position von wo das Licht gekommen ist.
:confused:
Ich will das Programm nicht groß ändern, z.B. will ich nicht für den PWM
einen Timer machen...
Danke schon im Vorraus. Ich bin gespannt auf eure Vorschläge;)
Mit freundlichen Grüßen, technik97;)