gun22
30.01.2006, 20:40
Hallo,
ich möchte eine Servosteuerung bauen und verwende gerade den ATmega8515L. Da ich eine recht kleine Schritte benötige, möchte ich den 16-Bit Timer im Fast-PWM-Modus betreiben.
Nun das Problem:
Laut Datenblatt stelle ich nun alles so ein, dass ich das ICR-Register als TOP-Wert nehme und das OCR1A-Register als Vergleichswert. Lasse ich das ganze dann im Simulator des AVR-Studios laufen, zählt das TCNT-Register erst hoch bis 0x01FF, dann aber wieder runter auf 0. Sieht nach Phase-Correct-Mode aus, wobei aber nicht einmal der TOP-Wert stimmt. Hinzu kommt noch, dass wenn ich den Vergleichswert setze (hier bei mir auf 1500 = 0x05dc), er jedesmal nach dem initialisieren der Steuerregister (TCCR) auf 0x01dc gesetzt wird.
Den Quellcode hab ich mal mit beigefügt, damit ihr seht, was ich da getippt habe und es besser nachvollziehen könnt.
Mache ich da was falsch oder kann ich das Datenblatt einfach nicht richtig interpretieren? Beim 8-Bit Timer mit PWM geht alles super, brauche aber eben den mit 16-Bit.
Würde mich freuen wenn ihr mir weiterhelfen könnt.
Lg gun22
.include "m8515def.inc"
; Konstanten
.equ pwm_top = 20000 ; für ICR1-Register
.equ ps_min = 1000 ; Minimum für PWM-Signale
.equ ps_max = 2000 ; Maximum für PWM-Signale
.equ pwm_ctrl1 = 0b11000010 ; Fast-PWM-Mode; TOP = ICR1;
.equ pwm_ctrl2 = 0b00011000 ; Takt = ClK/1
; Variablen
.def temp = r16
.def temp_s = r17 ; temp für Status
; Makros
.macro out_16
ldi temp,high(@2)
out @0,temp
ldi temp,low(@2)
out @1,temp
.endmacro
.CSEG
.ORG 0x00 ; Startadresse 0x00
rjmp reset ; zur reset-Routine
;************************************************* *******************
; pwm_init:
; Die Register von Timer1 werden so gesetzt, dass er im PWM-Modus
; läuft. Zusätzlich wird PORTD als Ausgang für das Compare-Flag
; benutzt.
;************************************************* *******************
pwm_init: in temp_s,SREG ; SREG sichern und
cli ; globale Interrupts sperren
ldi temp,0b00100000 ; Pin5 an PortD als
out DDRD,temp ; Ausgang für Compare-Flag
ldi temp,pwm_ctrl1 ; Steuerbefehle für den
out TCCR1A,temp ; Timer schreiben
ldi temp,pwm_ctrl2
out TCCR1B,temp
out_16 ICR1H,ICR1L,pwm_top ; Top-Wert schreiben
; Signal-Wert schreiben
out_16 OCR1AH,OCR1AL,ps_min+((ps_max-ps_min)/2)
in temp,TCCR1B
ori temp,0b00000001
out TCCR1B,temp
out SREG,temp_s ; SREG zurückschreiben
ret
;************************************************* *******************
; reset:
; Hier werden nur allgemeine Einstellungen gemacht, wie z.B. den
; Stack einrichten usw.
;************************************************* *******************
reset: ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
;************************************************* *******************
; main:
; Das Hauptprogramm ruft die Unterprogramme zum Initialisieren auf
; und springt dann in eine Endlosschleife.
;************************************************* *******************
main: rcall pwm_init ; Timer initialisieren
loop: rjmp loop
ich möchte eine Servosteuerung bauen und verwende gerade den ATmega8515L. Da ich eine recht kleine Schritte benötige, möchte ich den 16-Bit Timer im Fast-PWM-Modus betreiben.
Nun das Problem:
Laut Datenblatt stelle ich nun alles so ein, dass ich das ICR-Register als TOP-Wert nehme und das OCR1A-Register als Vergleichswert. Lasse ich das ganze dann im Simulator des AVR-Studios laufen, zählt das TCNT-Register erst hoch bis 0x01FF, dann aber wieder runter auf 0. Sieht nach Phase-Correct-Mode aus, wobei aber nicht einmal der TOP-Wert stimmt. Hinzu kommt noch, dass wenn ich den Vergleichswert setze (hier bei mir auf 1500 = 0x05dc), er jedesmal nach dem initialisieren der Steuerregister (TCCR) auf 0x01dc gesetzt wird.
Den Quellcode hab ich mal mit beigefügt, damit ihr seht, was ich da getippt habe und es besser nachvollziehen könnt.
Mache ich da was falsch oder kann ich das Datenblatt einfach nicht richtig interpretieren? Beim 8-Bit Timer mit PWM geht alles super, brauche aber eben den mit 16-Bit.
Würde mich freuen wenn ihr mir weiterhelfen könnt.
Lg gun22
.include "m8515def.inc"
; Konstanten
.equ pwm_top = 20000 ; für ICR1-Register
.equ ps_min = 1000 ; Minimum für PWM-Signale
.equ ps_max = 2000 ; Maximum für PWM-Signale
.equ pwm_ctrl1 = 0b11000010 ; Fast-PWM-Mode; TOP = ICR1;
.equ pwm_ctrl2 = 0b00011000 ; Takt = ClK/1
; Variablen
.def temp = r16
.def temp_s = r17 ; temp für Status
; Makros
.macro out_16
ldi temp,high(@2)
out @0,temp
ldi temp,low(@2)
out @1,temp
.endmacro
.CSEG
.ORG 0x00 ; Startadresse 0x00
rjmp reset ; zur reset-Routine
;************************************************* *******************
; pwm_init:
; Die Register von Timer1 werden so gesetzt, dass er im PWM-Modus
; läuft. Zusätzlich wird PORTD als Ausgang für das Compare-Flag
; benutzt.
;************************************************* *******************
pwm_init: in temp_s,SREG ; SREG sichern und
cli ; globale Interrupts sperren
ldi temp,0b00100000 ; Pin5 an PortD als
out DDRD,temp ; Ausgang für Compare-Flag
ldi temp,pwm_ctrl1 ; Steuerbefehle für den
out TCCR1A,temp ; Timer schreiben
ldi temp,pwm_ctrl2
out TCCR1B,temp
out_16 ICR1H,ICR1L,pwm_top ; Top-Wert schreiben
; Signal-Wert schreiben
out_16 OCR1AH,OCR1AL,ps_min+((ps_max-ps_min)/2)
in temp,TCCR1B
ori temp,0b00000001
out TCCR1B,temp
out SREG,temp_s ; SREG zurückschreiben
ret
;************************************************* *******************
; reset:
; Hier werden nur allgemeine Einstellungen gemacht, wie z.B. den
; Stack einrichten usw.
;************************************************* *******************
reset: ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
;************************************************* *******************
; main:
; Das Hauptprogramm ruft die Unterprogramme zum Initialisieren auf
; und springt dann in eine Endlosschleife.
;************************************************* *******************
main: rcall pwm_init ; Timer initialisieren
loop: rjmp loop