Forum: Mikrocontroller und Digitale Elektronik Timer Compare Interrupt mit ATtiny461A


von Stefan J. (michelangelo12)


Lesenswert?

Hallo!
Ich möchte mit dem ATtiny 461A mehr als die vorhandenen 3 PWM-Kanäle 
erzeugen.
Dafür lasse ich den Timer1 als 8bit Timer laufen und steuere die 
PWM-Ausgänge durch den Compare-Interrupt. Neben dem setzen des Ausgangs 
lade ich in der Compare-Interrupt-Routine das Register OCR1D mit dem 
Zeitwert für den nächsten Ausgang. Das ganze funktioniert auch, nur wenn 
zwei Zeitwerte direkt aufeinander folgen, führt der zweite nicht zu 
einem Interrupt.
In den Beschreibungen habe ich einen Hinweis gefunden das der Interrupt 
erst mit dem nächsten Timer-Takt erfolgt. Ist das der Grund weswegen 
aufeinander folgende Vergleichswerte nicht funktionieren.
Leider bin ich noch auf keine Lösung gekommen. Nur jeden zweiten Wert zu 
verwenden finde ich zu grob.
Ich hoffe ich habe das vertsändlich beschrieben.

Vielen Dank für eure Hilfe!

Gruß
stefan

von Stefan F. (Gast)


Lesenswert?

Laber nicht rum, sondern zeige und den Quelltext und beschreibe den 
Anwendungsfall. Ich vermute, es geht um Modellbau-Servos. Warum nimmst 
du dazu nicht einen der zahlreichen längst erprobten Codes?

von Stefan J. (michelangelo12)


Lesenswert?

Es geht um das Dimmen von LEDs.
Hier der Code:

; ATtiny461A

;*********************************************************************** 
************************
.include "tn461Adef.inc"
.device attiny461A


.def  dimm1=r1
.def  dimm2=r2
.def  dimmrot=r3
.def  Einzeln=r4
.def  Prell=r5
.def  Speichern=r6
.def    Flag=r7
.def  RGB=r8
.def  dimmgruen=r9
.def  dimmblau=r10
.def  Merker2_T=r11
.def  RGBneu=r12



.def    Merker=r16
.def    Merker2=r17
.def    Merker1_I=r18
.def    TimerL=r19
.def    TimerH=r20
.def    Dat1=r21
.def    Adr1=r22
.def    Adr2=r23
.def    BitN=r24
.def  Ausgabe1=r25
.def    Ausgabe2=r26
.def    Taste=r27
.def  Merker_T=r28

.def  ZLow=r30
.def  ZHigh=r31




;*********************************************************************
;  Interruptvektoren  :
;*********************************************************************
rjmp RESET ; Reset Handler
rjmp EXT_INT0 ; IRQ0 Handler
rjmp PCINT ; PCINT Handler
rjmp TIM1_COMPA ; Timer1 CompareA Handler
rjmp TIM1_COMPB ; Timer1 CompareB Handler
rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ; Timer0 Overflow Handler
rjmp USI_START ; USI Start Handler
rjmp USI_OVF ; USI Overflow Handler
rjmp EE_RDY ; EEPROM Ready Handler
rjmp ANA_COMP ; Analog Comparator Handler
rjmp ADC_ISR ; ADC Conversion Handler
rjmp WDT ; WDT Interrupt Handler
rjmp EXT_INT1 ; IRQ1 Handler
rjmp TIM0_COMPA ; Timer0 CompareA Handler
rjmp TIM0_COMPB ; Timer0 CompareB Handler
rjmp TIM0_CAPT ; Timer0 Capture Event Handler
rjmp TIM1_COMPD ; Timer1 CompareD Handler
rjmp FAULT_PROTECTION ; Timer1 Fault Protection




EXT_INT0:
PCINT:
TIM1_COMPA:
TIM1_COMPB:

TIM0_OVF:
USI_START:
USI_OVF:
EE_RDY:
ANA_COMP:
ADC_ISR:
WDT:
EXT_INT1:
TIM0_COMPA:
TIM0_COMPB:
TIM0_CAPT:

FAULT_PROTECTION:  reti

;*********************************************************************
;   Timer1 Overflow
;*********************************************************************
TIM1_OVF:
      in    Flag,SREG
      sbi    PORTB,2
      sbi    PORTA,3
      sbi    PORTA,5
      out    SREG,Flag
      reti

;*********************************************************************
;  Timer1 Compare D
;*********************************************************************
TIM1_COMPD:
      in    Flag,SREG
      cpi    Merker_T,0
      breq          TimerTest
      ldi    Merker_T,1
      out    OCR1D,Merker_T
      cbi    PORTB,2
      clr    Merker_T
      rjmp          TIM1_END

TimerTest:          ldi    Merker_T,2
      out    OCR1D,Merker_T
      ldi    Merker,20
      out    TIMSK,Merker
      ldi    Merker,148
      out    TIMSK,Merker
      cbi    PORTA,3

      rjmp          TIM1_END

RGB_direkt:
      sbrs          RGB,0
      rjmp          TIM1_Gruen
      cbi    PORTB,2

TIM1_Gruen:
      sbrs          RGB,1
      rjmp          TIM1_Blau
      cbi    PORTA,3

TIM1_Blau:
      sbrs          RGB,2
      rjmp          TIM1_Next
      cbi    PORTA,5

TIM1_Next:
      cpi    ZLow,112
      brne          NextPWM
      ldi    ZLow,103
NextPWM:
      ld    Merker_T,Z+
Next_ok:          out    OCR1D,Merker_T
      inc    ZLow
      ld    RGB,Z+
      mov    Merker_T,RGB
      cpi    Merker_T,0
      breq  TIM1_Next


TIM1_END:          out    SREG,Flag
      reti

;*********************************************************************
;  Initialisierungsroutine
;*********************************************************************
RESET:
      ldi    Ausgabe1,255
      out    DDRA,Ausgabe1
      ldi    Ausgabe2,191
      out    DDRB,Ausgabe2
      ldi    Merker,0
      out    PORTA,Merker
      ldi    Merker,64
      out    PORTB,Merker
      clr    Einzeln
      clr    Speichern
      clr    RGBneu
      clr    ZHigh
      ldi    ZLow,103
      ldi    Merker,128
      out    TCCR0A,Merker
      ldi    Merker,4
      out    TCCR0B,Merker
      ldi    Merker,163
      out    TCCR1A,Merker
      ldi    Merker,8
      out    TCCR1B,Merker
      ldi    Merker,160
      out    TCCR1C,Merker
      ldi    Merker,0
      out    PLLCSR,Merker
      ldi    Merker,0
      out    TCCR1D,Merker
      ldi    Merker,0
      out    TC1H,Merker

            ldi    Merker,148
      out    TIMSK,Merker
                    sei

;*********************************************************************
; Hauptprogramm
;*********************************************************************
Start:
OutOK:                  ori    Ausgabe1,40
      out    DDRA,Ausgabe1
      ori    Ausgabe2,46
      out    DDRB,Ausgabe2
      mov    Merker,dimm1
      out           OCR1A,Merker
      mov    dimmblau,dimm1
      mov    dimmgruen,dimm2
      mov    Merker,dimm2
      out    OCR1B,Merker
;*********************************************************************** 
*******************************************************************
;RGB dimm-Werte sortieren und in RAM speichern
;*********************************************************************** 
*******************************************************************
      clr    RGBneu
      cp    dimmrot,dimmgruen
      brsh          grbl
      cp    dimmrot,dimmblau
      brsh          blkl

      sts    103,dimmrot
      ldi    Merker,1
      sts    104,Merker
      cp    dimmgruen,dimmblau
      brsh          grma
      sts    106,dimmgruen
      ldi    Merker,2
      sts    107,Merker
      sts    109,dimmblau
      ldi    Merker,4
      sts    110,Merker
      rjmp          SortEnde

grma:            sts    109,dimmgruen
      ldi    Merker,2
      sts    110,Merker
      sts    106,dimmblau
      ldi    Merker,4
      sts    107,Merker
      rjmp          SortEnde

grbl:            cp    dimmgruen,dimmblau
      brsh          blkl

      sts    103,dimmgruen
      ldi    Merker,2
      sts    104,Merker
      cp    dimmrot,dimmblau
      brsh          roma
      sts    106,dimmrot
      ldi    Merker,1
      sts    107,Merker
      sts    109,dimmblau
      ldi    Merker,4
      sts    110,Merker
      rjmp          SortEnde

roma:            sts    109,dimmrot
      ldi    Merker,1
      sts    110,Merker
      sts    106,dimmblau
      ldi    Merker,4
      sts    107,Merker
      rjmp          SortEnde

blkl:            sts    103,dimmblau
      ldi    Merker,4
      sts    104,Merker
      cp    dimmrot,dimmgruen
      brsh          roma2
      sts    106,dimmrot
      ldi    Merker,1
      sts    107,Merker
      sts    109,dimmgruen
      ldi    Merker,2
      sts    110,Merker
      rjmp          SortEnde

roma2:            sts    109,dimmrot
      ldi    Merker,1
      sts    110,Merker
      sts    106,dimmgruen
      ldi    Merker,2
      sts    107,Merker
SortEnde:
;*********************************************************************** 
*******************************************************************
;gleiche dimmwerte finden
;*********************************************************************** 
*******************************************************************
      lds    Merker,103
      lds    Merker2,106
      cp    Merker,Merker2
      breq          Gleich36
      lds    Merker,104
      sts    105,Merker
      lds    Merker,106
      lds    Merker2,109
      cp    Merker,Merker2
      brne          Ungleich69
      lds    Merker,107
      lds    Merker2,110
      or    Merker,Merker2
      sts    108,Merker
      ldi    Merker,0
      sts    111,Merker
      rjmp          GleichEnde
Gleich36:          lds    Merker,104
      lds    Merker2,107
      or    Merker,Merker2
      sts    105,Merker
      ldi    Merker,0
      sts    108,Merker
      lds    Merker,106
      lds    Merker2,109
      cp    Merker,Merker2
      brne          MaxUngl
      ldi    Merker,7
      sts    105,Merker
      ldi    Merker,0
      sts    111,Merker
      rjmp          GleichEnde
Ungleich69:          lds             Merker,107
      sts    108,Merker
MaxUngl:          lds    Merker,110
      sts    111,Merker
GleichEnde:
;*********************************************************************** 
*******************************************************************
      rjmp  Start

von Stefan F. (Gast)


Lesenswert?

Sorry, mit Assembler kenne ich mich zu wenig aus.

Kannst du für die anderen Experten vielleicht noch präzisieren, was "nur 
wenn
zwei Zeitwerte direkt aufeinander folgen" genau bedeutet?

von Stefan J. (michelangelo12)


Lesenswert?

Wenn der 1. PWM Ausgang bei einem Timerwert von zum Beispiel 120 
ausgeschaltet wird und der 2. PWM Ausgang  bei 121 ausgeschaltet werden 
soll, dann wird für den 2. PWM-Wert kein Timer-Inerrupt ausgelöst. 
Obwohl die Abarbeitungszeit der Timer-Inerrupt-Routine deutlich unter 
dem Zyklus vom Timer liegt.
Was muss ich beachten wenn der Timer-Interrupt bei einem nur um eins 
höheren Timerwert direkt wieder ausgelöst werden soll?

Danke und GRuß!

von S. Landolt (Gast)


Lesenswert?

Ich kann zwar Assembler, aber das Programm ist mir zu unübersichtlich, 
allein schon das Aufdröseln der TCCR1n. Darum nur ein Rat:

> ldi    Merker,160
> out    TCCR1C,Merker

Die erste Zeile schreibt man üblicherweise als
  ldi    Merker,(1<<COM1A1S)|(1<<COM1B1S)


> sts    108,Merker
Statt 108 gibt man im Bereich .dseg einen Namen an, z.B. Hase

Hase:  .byte 1  ; mein Name ist Hase

und schreibt dann im Programm

  sts    Hase,Merker

von Stefan F. (Gast)


Lesenswert?

Immerhin verstehe ich jetzt dein Problem :-)

Im Datenblatt steht dazu auf Seite 90:
"The Timer/Counter1 register values go through the internal 
synchronization registers, which cause the input synchronization delay, 
before affecting the counter operation. "

Und auf Seite 94 steht:
"The OCR1x Registers are double buffered when using any of the Pulse 
Width Modulation (PWM) modes... The double buffering synchronizes the 
update of the OCR1x Compare Registers to either top or bottom of the 
counting sequence. "

Wenn ich das richtig verstehe, muss der neue Wert also nicht nur um 1 
höher sein, sondern er wird sogar bis zum nächsten Zyklus verzögert.

von S. Landolt (Gast)


Lesenswert?

> when using any of the Pulse Width Modulation (PWM) modes

Eben das lässt sich bei der obigen Schreibweise nur recht mühsam 
feststellen.

von Stefan F. (Gast)


Lesenswert?

TCCR1A.PWM1A und TCCR1A.PWM1B sind beide gesetzt, also PWM Mode.

von S. Landolt (Gast)


Lesenswert?

Und das erkennen Sie so aus der Lamäng? Hut ab!

von Stefan F. (Gast)


Lesenswert?

> Und das erkennen Sie so aus der Lamäng?

Das ist kein Kunststück. Ein bisschen Assembler kann ich schon, aber ein 
bisschen Phantasie hätte schon genügt:

>ldi    Merker,163
>out    TCCR1A,Merker

163 ist binär 1010 0011

die beiden niedrigsten Bits aktivieren laut Datenblatt den PWM Modus.

von Stefan J. (michelangelo12)


Lesenswert?

Ich wollte den tiny461 zunächst nur mit seinen PWM-Kanälen nutzen. 
Inzwischen möchte ich aber mit einem Tiny noch mehr LEDs ansteuern als 
PWM-Kanäle vorhanden sind. Mir geht es also nicht um die hier auch 
verwendeten PWM-Kanäle, die übrigens völlig fehlerfrei funktionieren, 
sondern um die Software-PWM-Kanäle mit dem 8bit-Timer1.

von Stefan F. (Gast)


Lesenswert?

Dann könnte es eine gute Idee sein, nicht mehr den PWM Modus zu benutzen

von S. Landolt (Gast)


Lesenswert?

Lässt sich nicht der Timer0 dafür (mit-)verwenden? Ich sehe zwar, dass 
er aktiviert wird, kann aber seine Aufgabe nicht erkennen.

von Stefan J. (michelangelo12)


Lesenswert?

Der Timer0 wird für das Auswerten einer IR-Fenbedienung genutzt. Ich bin 
davon ausgegangen das der Timer1 für die Hardware-PWM einfach durchläuft 
und auch für andere Zwecke genutzt werden kann. Gibt es in der 
BEschreibung einen Hinweis das dies nicht möglich ist? Hatte bisher 
keinen Hinweis in der Richtung finden können.

von S. Landolt (Gast)


Lesenswert?

?
Stefan Us hat ja bereits die betreffende Passage aus dem Datenblatt 
zitiert.

Beitrag #5222945 wurde von einem Moderator gelöscht.
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.