Pr0gm4n
15.01.2011, 18:07
Hallo zusammen,
in der Schule lernen wir in Info zur Zeit Assembler und da hab ich mir gedacht ich lern jetz mal AVR-Assembler ;)
Ich mach grad das mikrocontroller.net-tutorial durch und bin bei den timern
#define servoreg1 DDRA
#define servoreg2 DDRA
#define servoport1 PORTA
#define servoport2 PORTA
#define servopin1 PA0
#define servopin2 PA1
.def servo1 = R19
.def servo2 = R20
.include "m32def.inc"
.def tmp = R16 ; Allzweckregister
.def counter = R17 ; Counter für Timer-1-Zyklen
.def counter2 = R18 ; Counter für Timer-0-Zyklen
.equ Timer1AOVF = 200 ; 200 = 0,1ms bei prescaler 8
; 20 = 0,01ms bei prescaler 8
; 2 = 0,001ms bei prescaler 8
; 10 = 0,005ms bei prescaler 8
; 16 = 0,001ms bei prescaler 1
; 80 = 0,005ms bei prescaler 1
.org 0x000
rjmp Main
.org OC1Aaddr ; Output Compare1A Interrupt Vector Address
rjmp OC1A_interrupt
.org OVF0addr ; Overflow0 Interrupt Vector Address
rjmp OVF0_interrupt
.org INT_VECTORS_SIZE
OC1A_interrupt:
inc counter
;update servos:
cp counter, servo1
brne s2
cbi servoport1, servopin1
s2:
cp counter, servo2
brne counterreset
cbi servoport2, servopin2
counterreset:
cpi counter, 200
brne end
clr counter
sbi servoport1, servopin1
sbi servoport2, servopin2
end: reti
OVF0_interrupt:
inc counter2
cpi counter2, 255
brne end2
inc servo1
inc servo2
clr counter2
cpi servo1, 21
brne end
ldi servo1, 10
ldi servo2, 10
end2: reti
Main: ; hier beginnt das Hauptprogramm
ldi tmp, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, tmp
ldi tmp, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, tmp
clr tmp
;/*Timer 0:
ldi tmp, ( 1 << CS02 ) | ( 1 << CS00 ) ; Prescaler auf 1024
out TCCR0, tmp
;=> 61.4 Overflows in der Sekunde (bei 16 MHz)
;=> alle 16,4 ms
ldi tmp, TIMSK
ori tmp, ( 1 << TOIE0 ) ; TOIE0: Interrupt bei Timer Overflow
out TIMSK, tmp
;*/ ;Timer 0
;/*Timer 1:
ldi tmp, high( Timer1AOVF - 1 )
out OCR1AH, tmp
ldi tmp, low( Timer1AOVF - 1 )
out OCR1AL, tmp
; Prescaler auf 1 (001), 8 (010), 64 (011), 256 (100), 1024 (101)
ldi tmp, ( 1 << WGM12 ) | ( 1 << CS11 )
out TCCR1B, tmp
ldi tmp, TIMSK
ori tmp, ( 1 << OCIE1A ) ; OCIE1A: Interrupt bei Timer Compare A
out TIMSK, tmp
;*/ ;Timer 1
ldi tmp, 0xFF
out DDRA, tmp
ldi counter, 0x00
ldi counter2, 0x00
rcall init_servos
sei
loop:
rjmp loop
init_servos:
sbi servoreg1, servopin1
ldi servo1, 10
sbi servoreg2, servopin2
ldi servo2, 10
ret
Ziel war es:
2 Servos "parallel" von anschlag1 zu anschlag 2 zu fahren und wenn man dort ankommt wieder auf anschlag 1
mit timer0 sollte ich dank 16MHz und 1024 prescaler mit dem counter2 und den 256 fürn overflow von mir auf etwa 4 sekunden takte kommen bei denen im interrupt die servopositionen servo1 und servo2 inkrementiert werden, bei 10 positionen sollte das also 40s dauern, bis der wieder die richtung wechselt und zum anschlag 1 fährt.
timer1 soll dagegen die pwm übernehmen
16MHz, prescale 8, compare bei 200 --> alle 0.1 ms
ergebnis des codes sind zwei zwischen anschlag 1 und ca. 15° hin- und herbewegende servos
als board nehm ich grad weil ich nix besseres zur hand hatte das pollin funk evaluationsboard ver 1.1 mit ATMega32
die stromversorgung des servos läuft zwar auch über den spannungsregler der platine, aber nicht über den controller, der spannungsregler wird dabei weder warm noch sonstwas außergewöhnliches...
Ich hoffe ihr könnt mir helfen.
LG Roland
PS: im AVR-Studio-Debugger läuft alles ohne Probleme, die Taktzyklen sind genau so wie ich sie ausgerechnet hatte, alle 20ms ein neues signal für den servo, die länge des signals passt, auch die zeit zum "hochschalten" der position der servos stimmt...
keine ahnung was da wieder nicht geht...
danke schonmal an alle
in der Schule lernen wir in Info zur Zeit Assembler und da hab ich mir gedacht ich lern jetz mal AVR-Assembler ;)
Ich mach grad das mikrocontroller.net-tutorial durch und bin bei den timern
#define servoreg1 DDRA
#define servoreg2 DDRA
#define servoport1 PORTA
#define servoport2 PORTA
#define servopin1 PA0
#define servopin2 PA1
.def servo1 = R19
.def servo2 = R20
.include "m32def.inc"
.def tmp = R16 ; Allzweckregister
.def counter = R17 ; Counter für Timer-1-Zyklen
.def counter2 = R18 ; Counter für Timer-0-Zyklen
.equ Timer1AOVF = 200 ; 200 = 0,1ms bei prescaler 8
; 20 = 0,01ms bei prescaler 8
; 2 = 0,001ms bei prescaler 8
; 10 = 0,005ms bei prescaler 8
; 16 = 0,001ms bei prescaler 1
; 80 = 0,005ms bei prescaler 1
.org 0x000
rjmp Main
.org OC1Aaddr ; Output Compare1A Interrupt Vector Address
rjmp OC1A_interrupt
.org OVF0addr ; Overflow0 Interrupt Vector Address
rjmp OVF0_interrupt
.org INT_VECTORS_SIZE
OC1A_interrupt:
inc counter
;update servos:
cp counter, servo1
brne s2
cbi servoport1, servopin1
s2:
cp counter, servo2
brne counterreset
cbi servoport2, servopin2
counterreset:
cpi counter, 200
brne end
clr counter
sbi servoport1, servopin1
sbi servoport2, servopin2
end: reti
OVF0_interrupt:
inc counter2
cpi counter2, 255
brne end2
inc servo1
inc servo2
clr counter2
cpi servo1, 21
brne end
ldi servo1, 10
ldi servo2, 10
end2: reti
Main: ; hier beginnt das Hauptprogramm
ldi tmp, HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
out SPH, tmp
ldi tmp, LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
out SPL, tmp
clr tmp
;/*Timer 0:
ldi tmp, ( 1 << CS02 ) | ( 1 << CS00 ) ; Prescaler auf 1024
out TCCR0, tmp
;=> 61.4 Overflows in der Sekunde (bei 16 MHz)
;=> alle 16,4 ms
ldi tmp, TIMSK
ori tmp, ( 1 << TOIE0 ) ; TOIE0: Interrupt bei Timer Overflow
out TIMSK, tmp
;*/ ;Timer 0
;/*Timer 1:
ldi tmp, high( Timer1AOVF - 1 )
out OCR1AH, tmp
ldi tmp, low( Timer1AOVF - 1 )
out OCR1AL, tmp
; Prescaler auf 1 (001), 8 (010), 64 (011), 256 (100), 1024 (101)
ldi tmp, ( 1 << WGM12 ) | ( 1 << CS11 )
out TCCR1B, tmp
ldi tmp, TIMSK
ori tmp, ( 1 << OCIE1A ) ; OCIE1A: Interrupt bei Timer Compare A
out TIMSK, tmp
;*/ ;Timer 1
ldi tmp, 0xFF
out DDRA, tmp
ldi counter, 0x00
ldi counter2, 0x00
rcall init_servos
sei
loop:
rjmp loop
init_servos:
sbi servoreg1, servopin1
ldi servo1, 10
sbi servoreg2, servopin2
ldi servo2, 10
ret
Ziel war es:
2 Servos "parallel" von anschlag1 zu anschlag 2 zu fahren und wenn man dort ankommt wieder auf anschlag 1
mit timer0 sollte ich dank 16MHz und 1024 prescaler mit dem counter2 und den 256 fürn overflow von mir auf etwa 4 sekunden takte kommen bei denen im interrupt die servopositionen servo1 und servo2 inkrementiert werden, bei 10 positionen sollte das also 40s dauern, bis der wieder die richtung wechselt und zum anschlag 1 fährt.
timer1 soll dagegen die pwm übernehmen
16MHz, prescale 8, compare bei 200 --> alle 0.1 ms
ergebnis des codes sind zwei zwischen anschlag 1 und ca. 15° hin- und herbewegende servos
als board nehm ich grad weil ich nix besseres zur hand hatte das pollin funk evaluationsboard ver 1.1 mit ATMega32
die stromversorgung des servos läuft zwar auch über den spannungsregler der platine, aber nicht über den controller, der spannungsregler wird dabei weder warm noch sonstwas außergewöhnliches...
Ich hoffe ihr könnt mir helfen.
LG Roland
PS: im AVR-Studio-Debugger läuft alles ohne Probleme, die Taktzyklen sind genau so wie ich sie ausgerechnet hatte, alle 20ms ein neues signal für den servo, die länge des signals passt, auch die zeit zum "hochschalten" der position der servos stimmt...
keine ahnung was da wieder nicht geht...
danke schonmal an alle