The Man
16.11.2007, 14:33
Hallo Hallo,
ich bin dabei mir einen 4 Kanal Servo PWM Generator bauen.
Prinzip:
Takt = 8MHz
Ich habe zwei ISR:
die eine wird angesprungen, wenn eine ADC fertig ist.
hier werden AD Werte in die Ram Adressen 108 bis 111 geladen
und der AD Kanal um 1 erhöht.
Die andere bei einem Comparematch des TIMER 2 mit Prescaller = 1 und OCR2 = 30 zum Zug. Dort werden PINS des PORTD LOW gelegt und ein Zycluszähler erhöht.
Zu Begin des Programs werden 4 Analogwerte eingelsen.
Diese werden der Größe nach sortiert und mit dem Zugehörigen Pin in den Ramadressen 100 - 108 gespeichert.
************************************************** *******
Nach dem Sortieren kommt eine Verzögerungsschleife um ca. 18ms zu erreichen.
Dann wird der PORTD mit 01010101 belegt.(die Servo sind immer eins versetzt)
Nun folgt eine Verzögerung von 1ms.
Bis hierhin geht auch alles.
Der Pegel bleibt solange HIGH bis der Zyclus den selben Wert hat, wie
der dazugehörige PIN. Das Problem ist jetzt, dass diese Schleife bei etwa 3,8 ms liegt.(Osszi)
Findet sich im Code mit einer !!!!!-Reihe.
Im Simulator des AVR Studio läuft das Ganze.
Hat jemand eine Idee?
.include "m8def.inc"
.def tmp = r16
.def lowe = r17
.def lowz = r18
.def highe = r19
.def merker = r20
.def konst = r21
.def zyclus = r22
.def kanal = r23
.def zyclusnummer = r24
.def pin = r25
.def xlow = r26
.def xhigh = r27
.def ylow = r28
.def yhigh = r29
.def zlow = r30
.def zhigh = r31
.org 0x000
rjmp reset
.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue
.org ADCCaddr
rjmp adcc
reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000010
out TCCR0,tmp
ldi konst,8
ldi xlow,100
ldi ylow,116
ldi tmp,1
st y+,tmp
ldi tmp,4
st y+,tmp
ldi tmp,16
st y+,tmp
ldi tmp,64
st y+,tmp
ldi ylow,108
ldi zlow,108
ldi lowe,255
ldi tmp,0b00100000
out DDRC,tmp
ldi tmp,0b01010101
out DDRD,tmp
ldi tmp,0b011000000
out ADMUX,tmp
ldi tmp,30
out OCR2,tmp
nop
nop
nop
sei
main:
;*****************************
;***ADC Freerun + Interrupt***
;*****************************
ldi r16,0
ldi r17,255
ldi r18,0
ldi r19,0
ldi r20,0
ldi r21,0
ldi r22,0
ldi r23,0
ldi r24,0
ldi r25,0
ldi r26,100
ldi r27,0
ldi r28,108
ldi r29,0
ldi r30,108
ldi r31,0
ldi kanal,0b011000000
out ADMUX,kanal
ldi tmp,0b11001101 ;PRESCALER FEHLT
out ADCSRA,tmp
ldi xlow,108
pos:
cpi r26,112
breq voll2
rjmp pos
voll2:
ldi xlow,100
ldi lowe,255
schleife2:
schleife1:
ld lowz,y ;108 - 109 - 110 - 111
cp lowz,lowe
brsh istgrossr
mov lowe,lowz
mov zlow,ylow ;Z-Pointer zeigt auf Adresse mit kleinstem Wert (KW)
istgrossr: ;(KW)
inc ylow ;109 - 110 - 111 - 112 ;(KW)
cpi r28,112 ;(KW)
brlo schleife1 ;(KW)
add r30,konst ;0b10000000 => Bereich 136 bis 139 ;(KW + 4)
ld merker,z ;dort ist der PIN Wert gespeichert ;(KW + 4)
subi r30,8 ;(KW)
st x+,lowe ;100 - 102 - 104 - 106 ;(KW)
st x+,merker;101 - 103 - 105 - 107 ;(KW)
ldi lowe,255 ;(KW)
st z,lowe ;(KW)
ldi ylow,108
ldi zlow,108
cpi xlow,108
brlo schleife2
ldi r26,100
ld r0,x+;100 zyclus
ld r1,x+;101 pin
ld r2,x+;102
ld r3,x+;103
ld r4,x+;104
ld r5,x+;105
ld r6,x+;106
ld r7,x+;107
ldi r26,100
ldi r30,108
ldi tmp,0
sorten:
ld lowe,x+ ;100 - 107
st z+,lowe ;108 - 115
ld pin,x+
add pin,tmp
mov tmp,pin
st z+,pin ;108 - 115
ld lowz,x
cp lowz,lowe
brne diff
dec r30
dec r30
rjmp gleich
diff:
ldi tmp,0
gleich:
cpi r26,108
brne sorten
ldi r26,108
ld r8,x+;108 zyclus
ld r9,x+;109 pin
ld r10,x+;110
ld r11,x+;112
ld r12,x+;113
ld r13,x+;114
ld r14,x+;115
ld r15,x+;116
ldi r26,0
ldi tmp,0
out TCNT0,tmp
waita:
in tmp,TCNT0
cpi tmp,252
brlo waita
ldi tmp,0
out TCNT0,tmp
inc r26
cpi r26,72
brlo waita
ldi tmp,0b00001001 ;RPESCALER 1
out TCCR2,tmp
ldi r26,108
ldi tmp,0
out TCNT2,tmp
ldi tmp,0b01010101
out PORTD,tmp
ldi tmp,0b10000000
out TIMSK,tmp
ldi zyclus,0
warten1:
cpi zyclus,250
breq wigger
rjmp warten1
wigger:
sbi PORTC,5
ldi zyclus,0
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!
pulse:
ld zyclusnummer,x+
ld pin,x+
in tmp,PORTD
com pin
and pin,tmp
loop:
cp zyclusnummer,zyclus
brne loop
in tmp,PORTD
cpi tmp,0
brne pulse
cbi PORTC,5
warten:
cpi zyclus,249
brsh ende
rjmp warten
ende:
ldi tmp,0
out TIMSK,tmp
ldi ylow,108
ldi r30,108
ldi r26,100
ldi tmp,0
nullen:
st x+,tmp
cpi r26,116
brlo nullen
ldi merker,0
ldi zyclusnummer,0
rjmp main
;**********************************
;speichert den ADC Wert in die
;Vektoradresse und schaltet auf den
;nächsten ADC Kanal
;**********************************
adcc:
in tmp,ADCH
andi tmp,0b11111100
st x+,tmp ;108=>109=>110=>111=>112
cpi kanal,0b011000011
brsh fertig
inc kanal
out ADMUX,kanal
ldi tmp,0b11001101 ;PRESCALER FEHLT
out ADCSRA,tmp
fertig:
reti
hitvalue:
inc zyclus
cp zyclus,zyclusnummer
brne nicht
out PORTD,pin
nicht:
reti
Danke,
The Man
ich bin dabei mir einen 4 Kanal Servo PWM Generator bauen.
Prinzip:
Takt = 8MHz
Ich habe zwei ISR:
die eine wird angesprungen, wenn eine ADC fertig ist.
hier werden AD Werte in die Ram Adressen 108 bis 111 geladen
und der AD Kanal um 1 erhöht.
Die andere bei einem Comparematch des TIMER 2 mit Prescaller = 1 und OCR2 = 30 zum Zug. Dort werden PINS des PORTD LOW gelegt und ein Zycluszähler erhöht.
Zu Begin des Programs werden 4 Analogwerte eingelsen.
Diese werden der Größe nach sortiert und mit dem Zugehörigen Pin in den Ramadressen 100 - 108 gespeichert.
************************************************** *******
Nach dem Sortieren kommt eine Verzögerungsschleife um ca. 18ms zu erreichen.
Dann wird der PORTD mit 01010101 belegt.(die Servo sind immer eins versetzt)
Nun folgt eine Verzögerung von 1ms.
Bis hierhin geht auch alles.
Der Pegel bleibt solange HIGH bis der Zyclus den selben Wert hat, wie
der dazugehörige PIN. Das Problem ist jetzt, dass diese Schleife bei etwa 3,8 ms liegt.(Osszi)
Findet sich im Code mit einer !!!!!-Reihe.
Im Simulator des AVR Studio läuft das Ganze.
Hat jemand eine Idee?
.include "m8def.inc"
.def tmp = r16
.def lowe = r17
.def lowz = r18
.def highe = r19
.def merker = r20
.def konst = r21
.def zyclus = r22
.def kanal = r23
.def zyclusnummer = r24
.def pin = r25
.def xlow = r26
.def xhigh = r27
.def ylow = r28
.def yhigh = r29
.def zlow = r30
.def zhigh = r31
.org 0x000
rjmp reset
.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue
.org ADCCaddr
rjmp adcc
reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000010
out TCCR0,tmp
ldi konst,8
ldi xlow,100
ldi ylow,116
ldi tmp,1
st y+,tmp
ldi tmp,4
st y+,tmp
ldi tmp,16
st y+,tmp
ldi tmp,64
st y+,tmp
ldi ylow,108
ldi zlow,108
ldi lowe,255
ldi tmp,0b00100000
out DDRC,tmp
ldi tmp,0b01010101
out DDRD,tmp
ldi tmp,0b011000000
out ADMUX,tmp
ldi tmp,30
out OCR2,tmp
nop
nop
nop
sei
main:
;*****************************
;***ADC Freerun + Interrupt***
;*****************************
ldi r16,0
ldi r17,255
ldi r18,0
ldi r19,0
ldi r20,0
ldi r21,0
ldi r22,0
ldi r23,0
ldi r24,0
ldi r25,0
ldi r26,100
ldi r27,0
ldi r28,108
ldi r29,0
ldi r30,108
ldi r31,0
ldi kanal,0b011000000
out ADMUX,kanal
ldi tmp,0b11001101 ;PRESCALER FEHLT
out ADCSRA,tmp
ldi xlow,108
pos:
cpi r26,112
breq voll2
rjmp pos
voll2:
ldi xlow,100
ldi lowe,255
schleife2:
schleife1:
ld lowz,y ;108 - 109 - 110 - 111
cp lowz,lowe
brsh istgrossr
mov lowe,lowz
mov zlow,ylow ;Z-Pointer zeigt auf Adresse mit kleinstem Wert (KW)
istgrossr: ;(KW)
inc ylow ;109 - 110 - 111 - 112 ;(KW)
cpi r28,112 ;(KW)
brlo schleife1 ;(KW)
add r30,konst ;0b10000000 => Bereich 136 bis 139 ;(KW + 4)
ld merker,z ;dort ist der PIN Wert gespeichert ;(KW + 4)
subi r30,8 ;(KW)
st x+,lowe ;100 - 102 - 104 - 106 ;(KW)
st x+,merker;101 - 103 - 105 - 107 ;(KW)
ldi lowe,255 ;(KW)
st z,lowe ;(KW)
ldi ylow,108
ldi zlow,108
cpi xlow,108
brlo schleife2
ldi r26,100
ld r0,x+;100 zyclus
ld r1,x+;101 pin
ld r2,x+;102
ld r3,x+;103
ld r4,x+;104
ld r5,x+;105
ld r6,x+;106
ld r7,x+;107
ldi r26,100
ldi r30,108
ldi tmp,0
sorten:
ld lowe,x+ ;100 - 107
st z+,lowe ;108 - 115
ld pin,x+
add pin,tmp
mov tmp,pin
st z+,pin ;108 - 115
ld lowz,x
cp lowz,lowe
brne diff
dec r30
dec r30
rjmp gleich
diff:
ldi tmp,0
gleich:
cpi r26,108
brne sorten
ldi r26,108
ld r8,x+;108 zyclus
ld r9,x+;109 pin
ld r10,x+;110
ld r11,x+;112
ld r12,x+;113
ld r13,x+;114
ld r14,x+;115
ld r15,x+;116
ldi r26,0
ldi tmp,0
out TCNT0,tmp
waita:
in tmp,TCNT0
cpi tmp,252
brlo waita
ldi tmp,0
out TCNT0,tmp
inc r26
cpi r26,72
brlo waita
ldi tmp,0b00001001 ;RPESCALER 1
out TCCR2,tmp
ldi r26,108
ldi tmp,0
out TCNT2,tmp
ldi tmp,0b01010101
out PORTD,tmp
ldi tmp,0b10000000
out TIMSK,tmp
ldi zyclus,0
warten1:
cpi zyclus,250
breq wigger
rjmp warten1
wigger:
sbi PORTC,5
ldi zyclus,0
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!
pulse:
ld zyclusnummer,x+
ld pin,x+
in tmp,PORTD
com pin
and pin,tmp
loop:
cp zyclusnummer,zyclus
brne loop
in tmp,PORTD
cpi tmp,0
brne pulse
cbi PORTC,5
warten:
cpi zyclus,249
brsh ende
rjmp warten
ende:
ldi tmp,0
out TIMSK,tmp
ldi ylow,108
ldi r30,108
ldi r26,100
ldi tmp,0
nullen:
st x+,tmp
cpi r26,116
brlo nullen
ldi merker,0
ldi zyclusnummer,0
rjmp main
;**********************************
;speichert den ADC Wert in die
;Vektoradresse und schaltet auf den
;nächsten ADC Kanal
;**********************************
adcc:
in tmp,ADCH
andi tmp,0b11111100
st x+,tmp ;108=>109=>110=>111=>112
cpi kanal,0b011000011
brsh fertig
inc kanal
out ADMUX,kanal
ldi tmp,0b11001101 ;PRESCALER FEHLT
out ADCSRA,tmp
fertig:
reti
hitvalue:
inc zyclus
cp zyclus,zyclusnummer
brne nicht
out PORTD,pin
nicht:
reti
Danke,
The Man