www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATTiny2313 Timer1 - Problem mit Interrupt


Autor: -Tom-Tom- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich möchte mit dem ATTiny2313 mit dem Timer1 impulse ausgeben, bloß 
irgendwie scheitert das Vorhaben bei der Initialisierung:
    out    TCCR1C, temp0
    ldi    temp0, (3<<WGM12)|(5<<CS10) ;Vorteiler auf 1024
    out    TCCR1B, temp0
    ldi    temp0, (1<<WGM11)       ;Timer1 konfigurieren (Fast-PWM)
    out    TCCR1A, temp0

    ldi    temp0, (1<<TOIE1)      ;Overflow-Interrupt aktivieren
    out    TIMSK, temp0

    ldi    temp0, 0b00100000
    out    ICR1H, temp0
    clr    temp0
    out    ICR1L, temp0

das ganze soll einen Interrupt auslösen. Für's erste zum kontrollieren 
wollt ich mir am Oszi Impulse ausgeben.

Solange ich die Begrenzung des Zählers über das ICR weglasse, krieg ich 
meine Impulse, aber warum nicht mit?

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-Tom-Tom- schrieb:
> ich möchte mit dem ATTiny2313 mit dem Timer1 impulse ausgeben,
                                                        ^^^^^^
dann benutze als Vergleichsregister OCR1AH und OCR1AL.

ICR1L und ICR1H sind für die Input-Capture-Unit.

Autor: -Tom-Tom- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau da ist der Hacken,
an die Pins kann ich nicht ran, weil wegen dem Layout schon anders 
belegt sind.
Außerdem will ich den 16bit Timer hauptsächlich wegen der Zeit.

Das eigentliche Problem ist ja, dass der Interrupt nicht funktioniert 
...

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-Tom-Tom- schrieb:
> Das eigentliche Problem ist ja, dass der Interrupt nicht funktioniert

Mal langsam zum mitdenken:

Du stellst in deinem Programm eine Fast-PWM ein, naja eigentlich nicht:

-Tom-Tom- schrieb:
> ldi    temp0, (3<<WGM12)|(5<<CS10) ;Vorteiler auf 1024

wenn schon, dann (1<<WGM12)|(1<<CS10).
Deaktivierst aber deine PWM-Ausgänge (wo willst du dein Signal raus 
haben).
dann stellst du einen Timeroverflow interrupt ein.
Pfuscht noch kurz im Input-Capture-Ergebnis-Register und wunderst dich, 
dass nichts geht (was überhaupt)?

Poste mal schaltplan und kompletten Code, ansonsten siehe:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer

Autor: -Tom-Tom- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oke, vielleicht versuch ich mal zu erklären, auf was das ganze 
rauslaufen soll, sry dass ich das davor noch nicht hab ...

unterm Strich möchte ich eine variable Pausenzeit zwischen 0,05s und 
1,6s haben. Das ganze soll den AVR so wenig wie möglich belasten, weil 
der nebenbei ja noch ein DMX-signal auswertet und ein paar andere sachen 
macht.

Deswegen war meine Idee den Timer 1 mit seinen 16bit zu nehmen.

Und da es ja die Möglichkeit gibt mit ICR1 eine Obergrenze festzulegen, 
wie weit der zählt, wollte ich dies nutzen, dass ich variabel das ICR1 
einstelle und dann halt nach ablauf der Zeit einen Overflow-Interrupt 
auslöse.

Wollte ja den normalen Timer-Modus nehmen, aber bei dem geht ja das mit 
der Obergrenze nicht.

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-Tom-Tom- schrieb:
> Und da es ja die Möglichkeit gibt mit ICR1 eine Obergrenze festzulegen,
> wie weit der zählt, wollte ich dies nutzen, dass ich variabel das ICR1
> einstelle und dann halt nach ablauf der Zeit einen Overflow-Interrupt

So hier sind die Verständnisfehler :-)
Die PWM-Einstellungen haust du raus, nur CTC (Clear timer on compare 
match) bleibt drin.
Mit dem Registerpaar OCR1AH und ORC1AL stellst du deine Obergrenze ein.
Dann benutzt du nicht den Timer-Overflow, sondern den 
Timer-Compare-MAtch A interrupt.

Dieser wird ausgelöst, sobald der Zählwert im Timer gleich der 
Einstellung im OCR1A ist. Die CTC-Einstellung löscht dir bei 
erfolgreichem Vergleich auch gleich den Timer-Wert, damit er wieder von 
vorne anfängt.
:-)

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Und da es ja die Möglichkeit gibt mit ICR1 eine Obergrenze festzulegen,
>wie weit der zählt, wollte ich dies nutzen, dass ich variabel das ICR1
>einstelle und dann halt nach ablauf der Zeit einen Overflow-Interrupt
>auslöse.

Dann nimm den Timer-Mode 15 und den OCR1A-Interrupt. Der 
Overflow-Interrupt wird mit ICR1 als Top nicht ausgelöst, weil ein 
Overflow nicht erreicht wird.

MfG Spess

Autor: -Tom-Tom- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Floh schrieb:
> So hier sind die Verständnisfehler :-)
> Die PWM-Einstellungen haust du raus, nur CTC (Clear timer on compare
> match) bleibt drin.
> Mit dem Registerpaar OCR1AH und ORC1AL stellst du deine Obergrenze ein.
> Dann benutzt du nicht den Timer-Overflow, sondern den
> Timer-Compare-MAtch A interrupt.

Danke :)

aber ganz funktionierts noch nicht:
    clr    temp0
    out    TCCR1C, temp0
    ldi    temp0, (1<<WGM12)|(5<<CS10)
    out    TCCR1B, temp0
    clr    temp0
    out    TCCR1A, temp0

    ldi    temp0, (1<<OCIE1A)      ;Overflow-Interrupt aktivieren
    out    TIMSK, temp0

bis hierher tuts was es tun soll ... löst den Interrupt aus,
aber wenn ich dann den max-wert einstelle:
    ldi    temp0, 0b00010000
    out    OCR1AH, temp0
    clr    temp0
    out    OCR1AL, temp0  
kommt nix mehr ... :( warum?

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste mal dein komplettes Programm

Autor: -Tom-Tom- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.include "tn2313def.inc"

; ================================================================================================
; Register etc. definieren
; ------------------------------------------------------------------------------------------------

.def temp_ZL    = R1
.def temp_ZH    = R2
.def SREGbuf    = R3
.def temp0       = R16            
.def temp1       = R17
.def temp2       = R18
.def temp3      = R19
.def str_val    = R20
.def brightness    = R21

.def DMXstate    = R23
.def PWM_Count     = R24

.equ XTAL      = 16000000        ; Prozessortakt
.equ DMX_Daten    = 0x60          ; Startadresse DMX Array im RAM
.equ DMX_Kanaele  = 2           ; Zahl der DMX-Kanäle (Strobe,Helligkeit)

; ------------------------------------------------------------------------------------------------
; Interrupt-Vektor-Tabelle Tiny2313
; ------------------------------------------------------------------------------------------------

.CSEG

.org 0x0000

    rjmp    Start                      ; Reset Handler
    reti                ; External Interrupt Request 0
    reti                ; External Interrupt Request 1
    reti                ; Timer/Counter1 Capture Event
    rjmp  TMR_Overflow        ; Timer/Counter1 Compare Match A
    reti                ; Timer/Counter1 Overflow
    reti                     ; Timer/Counter0 Overflow --> PWM-Routine
    rjmp  DMX_Byte_Received      ; Rx Complete --> Byte empfangen
    reti                ; Data Register Empty
    reti                ; Tx Complete
    reti                ; Analog Comparator
    reti                ; Pin Change Interrupt
    reti                ; Timer/Counter1 Compare Match B
    reti                ; Timer/Counter0 Compare Match A
    reti                ; Timer/Counter0 Compare Match B
    reti                ; USI Start Condition
    reti                ; USI Overflow
    reti                ; EEPROM Ready
    reti                ; Watchdog Timer Overflow

; ------------------------------------------------------------------------------------------------
; Stackpointer, Ports setzen, etc.
; ------------------------------------------------------------------------------------------------

Start:

    ldi   temp0, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
    out   SPL, temp0

    ldi   temp0, 0b00100000
    out   DDRD, temp0          ; PortD setzen
    ldi   temp0, 0b01000000
    out   PortD, temp0          ; Pullup an PortD

      clr    temp0
      out    TCCR1C, temp0        ;Timer 1 konfigurieren
      ldi    temp0, (1<<WGM12)|(5<<CS10)  ;Vorteiler 1024; Mode 4
      out    TCCR1B, temp0
      clr    temp0
      out    TCCR1A, temp0

       ldi    temp0, (1<<OCIE1A)          ;Overflow-Interrupt aktivieren
      out    TIMSK, temp0


      ldi    temp0, 0b00010000      ;irg einen Wert in OCR1 schreiben
      out    OCR1AH, temp0
      clr    temp0
      out    OCR1AL, temp0

    rcall  DMX_Init          ; DMX initialisieren

    sei                  ; Interrupts aktivieren

; ================================================================================================
; Hauptroutine, DMX-Daten empfangen und in die Kanal-Register schieben
; ------------------------------------------------------------------------------------------------

main:
    ldi   ZH, high(DMX_Daten)
    ldi    ZL, low(DMX_Daten)
    ld    str_val, Z+
    ld    brightness, Z+
              


    rjmp  main

TMR_Overflow:

    sbi    PORTD,5
    
    
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    

    cbi    PORTD,5

    reti

; ================================================================================================
; DMX Initialisieren
; ------------------------------------------------------------------------------------------------

DMX_Init:

      ldi   temp0, ((XTAL/4000000)-1)   ; Usart auf 250 kbaud setzen
      out   UBRRL, temp0
      clr   temp0
      out   UBRRH, temp0

      ldi   temp0, (3<<UCSZ0)|(1<<USBS) ; 8 Datenbits, 2 Stoppbits
      out   UCSRC, temp0      
    sbi   UCSRB, RXEN          ; Receiver enable
    sbi   UCSRB, RXCIE        ; RX Complete Int. enable

    ldi   temp0, 0b00000000      ; PortB auf Eingang (DIP-Schalter)
    out   DDRB, temp0
    ldi   temp0, 0b11111111
    out   PortB, temp0          ; Pullup an PortB

    ldi    ZH, high(DMX_Daten)      ; alle Kanäle im RAM auf 0 setzen
    ldi    ZL, low(DMX_Daten)
    clr    temp0
    ldi   DMXstate, DMX_Kanaele

write_RxD:  

    st     Z+,temp0
    dec    DMXstate
    brne  write_RxD

    ret


; ================================================================================================
; ISR für DMX-Empfang
; ------------------------------------------------------------------------------------------------

DMX_Byte_Received:
    in      SREGbuf, SREG
    push  temp1
    push  temp0    
    push  ZH
    push   ZL
    mov    ZL, temp_ZL
    mov    ZH, temp_ZH

    in    temp0,UCSRA          ; Status und Daten holen
    in    temp1,UDR

    sbrc  temp0,FE          ; Frame-Error: neuer Durchgang
    rjmp  dmx_frame_error  
    
    cpi    DMXstate, 1           ; Startbyte testen
    breq  dmx_startbyte

      cpi   DMXstate, 2           ; Startadresse abfragen
    breq    dmx_startadr
      
     cpi   DMXstate, 3  
      brsh  dmx_handle_byte

dmx_finish:
    mov    temp_ZH, ZH
    mov    temp_ZL, ZL
    pop    ZL
    pop    ZH
    pop    temp0
    pop    temp1
    out     SREG, SREGbuf  
    reti      

dmx_startbyte:
    tst   temp1             ; Byze = 0 --> Startbyte, sonst Fehler
    brne   dmx_err
    inc    DMXstate

    in     ZL, PinB           ; Startadresse vom DIP holen (PortB)
    com     ZL
    clr    ZH
    sbis  PinD, 6            ; 9. Bit von PortD1 holen
    inc    ZH

    rjmp  dmx_finish

dmx_startadr:
    sbiw  ZH:ZL, 1          ; Adresse runterzählen
    brne  dmx_finish          ; Startadresse noch nicht erreicht

    ldi   ZH, high(DMX_Daten)
    ldi    ZL, low(DMX_Daten)
    inc    DMXstate
    
dmx_handle_byte:  
    st    Z+, temp1

    cpi    ZL, low(DMX_Daten+DMX_Kanaele)
    brne  dmx_finish
    cpi    ZH, high(DMX_Daten+DMX_Kanaele)
    brne  dmx_finish  
    clr    DMXstate
    rjmp  dmx_finish
  
dmx_frame_error:
    ldi   DMXstate, 1          ; Frame-Error --> neuer Durchlauf
    cbi    UCSRA,FE          ; Flag löschen, falls längere Pause
    rjmp  dmx_finish

dmx_err:
     clr   DMXstate          ; auf nächsten FE warten      
    rjmp  dmx_finish

; ================================================================================================

Autor: -Tom-Tom- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Empfangsroutine ist nicht von mir, aber funktioniert, hab ich schon 
bei mehreren Programmen verwendet.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.