logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega32] przerwania od timera

ceZar PK 12 Sie 2008 18:30 2508 4
REKLAMA
  • #1 5432834
    ceZar PK
    Poziom 11  
    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ń?
  • REKLAMA
  • Pomocny post
    #2 5432986
    ZbeeGin
    Poziom 39  
    A co na to symulacja programu?

    Taki program wgraj:

    .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
  • REKLAMA
  • #3 5433998
    ceZar PK
    Poziom 11  
    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:
    .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.
  • REKLAMA
  • #4 5435722
    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.
  • #5 5436975
    ceZar PK
    Poziom 11  
    Zgadza się, dzięki za sugestie.
REKLAMA