Forum: Mikrocontroller und Digitale Elektronik Frage zu Servoansteuerung mittels Timer 1 im Atmega8 (assembler)


von Nino K.L. (Gast)


Lesenswert?

Hallo,

ich versuche mich an einer Servoansteuerung mittels Timer 1 in einem 
Atmega8. Untenstehender Programmcode soll vorerst einfach nur den Servo 
in eine bestimmte Position bringen, sonst nichts. Dazu lade ich in das 
Timer Compare Register A (OCR1AL und OCR1AH) den Wert dec 20.000. Das 
entspricht der Gesamtdauer Impuls + Pause von 20 ms. (Der Prozessor 
läuft mit 1 MHz und der Timer im CTC Modus.)

Zum Test soll bei Auslösung des Interrupts (also bei dec 20.000) ein 
Impuls ausgegeben werden, was ich mit einer einfachen Warteschleife von 
256 Impulsen Länge erledige. (Zu kurz für einen Servo. Egal - ist nur 
ein Test)

Ich würde also als Ergebnis ein Signal erwarten, das 256 Takte auf 5 
Volt ist und den Rest auf 0 Volt. Tatsächlich ist es so, daß die 5 Volt 
Phase paßt, die 0 Volt Phase jedoch viel zu kurz ist. (Ich teste das 
natürlich nicht mit dem Servo, sondern schaue mir das Ergebnis mit einem 
Alt-aber-gut-Oszi an) Die Gesamtdauer, in der sich das Signal 
wiederholt, ist offensichtlich 256 Takte plus "ein bißchen was".

Meine Bitte wäre, ob jemand in den untenstehenden Code reinschauen 
könnte. Ich bin sicher, daß ich nur irgend eine Kleinigkeit übersehe. 
Was mache ich falsch bzw. wo liegt mein Denkfehler?

Vielen Dank und beste Grüße,
Nino.
1
  .include "m8def.inc"    
2
3
  .def PulsH_L      = r2    ; Servo horizontal Pulslänge in Takten
4
  .def PulsH_H      = r5
5
6
  .def temp        = r16  ; temp für allgemeine Anwendungen 
7
  .def temp1        = r17
8
  .def temp2        = r18
9
  .def temp3        = r19
10
11
  .equ PulsDauer_L = 0b00100000  ; Impuldsdauer 20 ms = 20.000 Takte
12
  .equ PulsDauer_H = 0b01001110
13
14
.org 0x00
15
    rjmp RESET        ; Reset Handler
16
    reti ;rjmp EXT_INT0    ; IRQ0 Handler
17
    reti ;rjmp EXT_INT1    ; IRQ1 Handler
18
    reti ;rjmp TIM2_COMP  ; Timer2 Compare Handler
19
    reti ;TIM2_OVF      ; Timer2 Overflow Handler
20
    reti ;rjmp TIM1_CAPT  ; Timer1 Capture Handler
21
    rjmp TIM1_COMPA      ; Timer1 CompareA Handler
22
    reti ;rjmp TIM1_COMPB      ; Timer1 CompareB Handler
23
    reti ;rjmp TIM1_OVF    ; Timer1 Overflow Handler
24
    reti ;rjmp TIM0_OVF    ; Timer0 Overflow Handler
25
    reti ;rjmp SPI_STC    ; SPI Transfer Complete Handler
26
    reti ;rjmp USART_RXC  ; USART RX Complete Handler
27
    reti ;rjmp USART_UDRE  ; UDR Empty Handler
28
    reti ;rjmp USART_TXC  ; USART TX Complete Handler
29
    reti ;rjmp ADC      ; ADC Conversion Complete Handler
30
    reti ;rjmp EE_RDY    ; EEPROM Ready Handler
31
    reti ;rjmp ANA_COMP    ; Analog Comparator Handler
32
    reti ;rjmp TWSI      ; Two-wire Serial Interface Handler
33
    reti ;rjmp SPM_RDY    ; Store Program Memory Ready Handler
34
35
  .include "WARTESCHLEIFEN.asm"  ; selbsterklärend
36
37
RESET:
38
39
  ldi temp1, PulsDauer_L              
40
  out OCR1AL, temp1        ; Schreibe die Werte auch in das Timer
41
  ldi temp1, PulsDauer_H        ; Output Compare Register
42
  out OCR1AH, temp1
43
44
  ldi temp1, 0b11111111      ; Ports einstellen (1=Ausgang, 0=Eingang)
45
  out DDRB, temp1            ; Bit8 (links) = PB8; Bit0 (rechts) = PB0
46
  ldi temp1, 0b00100000
47
  out DDRC, temp1
48
  ldi temp1, 0b01111111
49
  out DDRD, temp1
50
51
  ldi temp1, high(RAMEND)        ; Stackzeiger einrichten
52
  out SPH, temp1
53
  ldi temp1, low(RAMEND)
54
  out SPL, temp1
55
                            
56
  ldi temp1, (1<<WGM12) | (1<<CS10) ; CTC Modus einschalten, Vorteiler auf 1
57
  out TCCR1B, temp1
58
59
  ldi temp1,  1 << OCIE1A | 0 << OCIE1B        ; OCIE1A: Interrupt bei Timer Compare
60
  out TIMSK, temp1
61
62
  sei              ; Interrupts generell zulassen  
63
64
Hauptprogramm:
65
rjmp Hauptprogramm
66
67
TIM1_COMPA:
68
  cli              ; interrupts ausschalten
69
70
  sbi PORTD, 2
71
72
  rcall warte_256
73
  cbi PORTD, 2
74
75
  sei              ; Interrupts wieder einschalten
76
reti

Und dazu noch die Warteschleife:
1
warte_256:
2
  push temp1
3
; ============================= 
4
; rcall       3 Zyklen
5
; push (á2)     2 Zyklen
6
; Schleife   243 Zyklen
7
; nop       2 Zyklen
8
; pop (á2)     2 Zyklen
9
; ret       4 Zyklen
10
; ----------------------------- 
11
; SUMME     256 Zyklen
12
  ldi  temp1, $51
13
A256:
14
  dec  temp1
15
  brne A256
16
  nop
17
  nop
18
  pop temp1
19
ret

von Spess53 (Gast)


Lesenswert?

Hi

> Ich bin sicher, daß ich nur irgend eine Kleinigkeit übersehe.
>Was mache ich falsch bzw. wo liegt mein Denkfehler?

Für mich liegt der Fehler schon im Konzept. Das ganze lässt sich mit dem 
Timer1 ohne Warteschleife und Interrupt machen. PWM-Mode 14. Mit ICR die 
Periodenzeit und mir OCR1A oder B Pulsdauer einstellen. Fertig.

mfG Spess

von Peter D. (peda)


Lesenswert?

Nino K.L. schrieb:
> ldi temp1, PulsDauer_L
>   out OCR1AL, temp1        ; Schreibe die Werte auch in das Timer
>   ldi temp1, PulsDauer_H        ; Output Compare Register
>   out OCR1AH, temp1

Lies im Datenblatt den Abschnitt Timer1, Accessing 16-bit Registers und 
korrigiere Deinen Code entsprechend.

Nino K.L. schrieb:
> TIM1_COMPA:
>   cli              ; interrupts ausschalten

Lies im Datenblatt den Abschnitt Reset and Interrupt Handling, was beim 
Eintritt in den Interrupt erfolgt und korrigiere Deinen Code 
entsprechend.

von Nino K.L. (Gast)


Lesenswert?

Hallo nochmal,

wußte ich doch, daß Profis sofort erkennen, woran es hapert. Vielen Dank 
für die Hilfe!

@Peter:
Tut mir leid, daß ich die betreffenden Stellen im Datenblatt nicht 
selbst gefunden hab. (Sind ja doch 230 Seiten) Danke für die Verweise, 
die in weiterer Folge das Programm sofort zum Laufen gebracht haben.

@Speß:
Mit deiner Hilfe mache ich jetzt den Programmcode noch kürzer. Da ich im 
uC-Bereich noch Lernender bin, hatte ich bisher den PWM Mode 14 noch 
nicht benützt. Es wurde also offensichtlich Zeit. Danke für die 
Information!

Beste Grüße,
Nino.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.