Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATmega32] przerwania od timera

ceZar PK 12 Sie 2008 18:30 1893 4
  • #1 12 Sie 2008 18:30
    ceZar PK
    Poziom 10  

    Mam problem z przerwaniem od Timera0. Chodzi o to by Timer0 zgłaszał przerwanie w trybie pracy z porównaniem. Jest to tryb Clear Timer on Compare Match (CTC). Licznik zlicza zdarzenia zewnętrzne i w momencie zliczenia do zadanej wartości ma zgłosić przerwanie i zacząc liczyć od zera. Aby to osiągnąć do rejestru OCR0 wpisuję wartość do której licznik ma liczyć. Rejestr ustawień licznika TCCR0 zapisuję następująco:
    (0<<FOC0)|(0<<WGM00)|(0<<COM01)|(0<<COM00)|(1<<WGM01)|(1<<CS02)|(1<<CS01)|(0<<CS00)
    (czyli zliczanie zewnętrzengo sygnału przy zboczu opadającym, tryb pracy CTC - zerowanie licznika w trybie porównania, odłączone wyjście OC0). W rejestrze TIMSK odblokowuję przerwania od Timera0 wpisując "1" w bicie OCIE0. Poza tym przerwania są oczywiście globalnie odblokowane (bit I w SREG). Powinno to według mnie działać a tymczasem sprawa wygląda tak że licznik liczy rzeczywiście do zadanej przeze mnie wartości po czym sie zeruje i liczy od nowa (zatem tryb pracy działa poprawnie) jednak przerwanie w momencie osiągnięcia wartości zgodnej z tą zapisaną w OCR0 nie występuje...
    Program piszę w asemblerze.
    Ma ktoś jakiś pomysł co może być przyczyną braku generowanie tych przerwań?

    0 4
  • Pomocny post
    #2 12 Sie 2008 19:22
    ZbeeGin
    Poziom 38  

    A co na to symulacja programu?

    Taki program wgraj:

    Code:
    .nolist
    
    .include "m32def.inc"
    .list

    ; ## START #####################################################
    .cseg

    ;==============================================================
    ;= WEKTORY PRZERWAŃ                                           =
    ;==============================================================
            .org    0x0000
            rjmp    reset_vector                    ; po resecie systemu

            .org    0x0002       
            reti                                    ; INT0

            .org    0x0004
            reti                                    ; INT1

            .org    0x0006
            reti                                    ; INT2

            .org    0x0008       
            reti                                    ; T2COMP

            .org    0x000A       
            reti                                    ; T2OVF

            .org    0x000C       
            reti                                    ; T1CAP

            .org    0x000E       
            reti                                    ; T1COMPA

            .org    0x0010       
            reti                                    ; T1COMPB
       
            .org    0x0012
            reti                                    ; T1OVF





            .org    0x0014       
            rjmp   port_ma_kota                    ; T0COMP

            .org    0x0016       
            reti                                    ; T0OVF

            .org    0x0018       
            reti                                    ; SPI

            .org    0x001A       
            reti                                    ; URXC

            .org    0x001C       
            reti                                    ; URDE

            .org    0x001E       
            reti                                    ; UTXC

            .org    0x0020       
            reti                                    ; ADC

            .org    0x0022       
            reti                                    ; EERDY

            .org    0x0024       
            reti                                    ; ACI

            .org    0x0026       
            reti                                    ; TWI

            .org    0x0028       
            reti                                    ; SPMC

    reset_vector:
            cli                                     ; wyłącz przerwania
            ldi     r16, high(RAMEND-5)             ; ustawimy sobie stosik (z zapasem)
            out     SPH, r16
            ldi     r16, low(RAMEND-5)
            out     SPL, r16

          ser      r16
          out      DDRB, r16
          clr      r16
          out      PORTB, r16

    ;--------------------------------------------------------------
    ctc_setup:                                     
            ldi     r16, (1<<WGM01)|(0<<CS02)|(1<<CS01)|(0<<CS00)
            out     TCCR0, r16       
            ldi      r16, 0x0F                       ; licz do iluśtam
            out     OCR0, r16
             
    ;--------------------------------------------------------------
    int_setup:                                      ; konfiguruj przerwania
            in      r16, TIMSK                      ; wczytaj stan masek przerwań
            ori     r16, (1<<OCIE0)                 ; ustaw przerwania
            out     TIMSK, r16                      ; ustaw nową maskę przerwań
            sei
                                                    ; koniec przerwań

    ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    ; @                                                            @
    ; @ TU SIĘ ZACZYNA PĘTLA GŁÓWNA                                @
    ; @                                                            @
    ; @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    main_loop:
            nop

          rjmp   main_loop


    ;--------------------------------------------------------------
    port_ma_kota:
          push   r17
          push   r16
          ser      r17
          in      r16, PORTB
          eor      r16, r17
          out      PORTB, r16
          pop      r16
          pop      r17
          reti

    0
  • #3 12 Sie 2008 23:41
    ceZar PK
    Poziom 10  

    Już działa:)

    Jeżeli chodzi o same ustawienia i inicjalizację Timera0 oraz przerwań to okazało się tak jak mi się wydawało że wszystko miałem dobrze. Jak zwykle w takich przypadkach błąd okazał się błahy i leżał w zupełnie innym miejscu. Otóż przy definiowaniu wektorów przerwań nie używałem definiowania ".org". Początek mojego programu wyglądał tak:

    Code:
    .INCLUDE "m32def.inc"
    

    .CSEG

    .ORG 0x0000



    ; --------------------------
    ;  WEKTORY OBSŁUGI PRZERWAŃ
    ; --------------------------

             RJMP      Reset         ; Reset
             RJMP      Sekunda         ; External Interrupt Request 0
             RJMP      Klawiatura      ; External Interrupt Request 1
             RETI               ; External Interrupt Request 2
             RETI               ; Timer/Counter2 Compare Match
             RETI               ; Timer/Counter2 Overflow
             RJMP      CF_moc         ; Timer/Counter1 Capture Event
             RETI               ; Timer/Counter1 Compare Match A
             RETI               ; Timer/Counter1 Compare Match B      
             RJMP      Bajt_3         ; Timer/Counter1 Overflow      
             RJMP      Energia         ; Timer/Counter0 Compare Match
             RETI               ; Timer/Counter0 Overflow
             RETI               ; Serial Transfer Complete
             RETI               ; USART, Rx Complete
             RETI               ; USART Data Register Empty
             RETI               ; USART, Tx Complete
             RETI               ; ADC Conversion Complete
             RETI               ; EEPROM Ready
             RETI               ; Analog Comparator
             RETI               ; 2-wire Serial Interface
             RETI               ; Store Program Memory Ready

    Myślałem że zdefiniowanie .org 0x0000 na początku wystarczy. Zresztą przerwania "Sekunda" i "Klawiatura" działały....
    W każdym razie dzięki za podesłanie tego programu bo dzięki temu mogłem się tym pobawić, pomieszać z moi programem i dojść do tego co jest nie tak.

    0
  • #4 13 Sie 2008 16:56
    ZlyDotyk
    Poziom 19  

    Wystarczy jeden .org 0. Program nie działał bo użyłeś w tablicy wektorów przerwań rozkazów rjmp i reti które zajmują jedno słowo. Różnice pomiędzy poszczególnymi wektorami wynoszą dwa słowa, a to dlatego że rjmp nie zaadresujesz całej pamięci. Powinieneś tam użyć rozkazu jmp (dwa słowa) ewentualnie jak bardzo chcesz rjmp/reti dopełnić po jednym nop'ie.

    0
  • #5 13 Sie 2008 22:39
    ceZar PK
    Poziom 10  

    Zgadza się, dzięki za sugestie.

    0