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

Cuda z przerwaniami. Ciągle wraca do reti. Listing.

elektrokuba 27 Lut 2011 13:47 1121 4
REKLAMA
  • #1 9211087
    elektrokuba
    Poziom 12  
    Witam

    Mam niezrozumiały dla mnie problem z przerwaniami. Do tej pory ich nie używałem ale że rozwijać się trzeba pora i na nie. A więc mam kod jak poniżej (nie wklejam całego bo symulator nawet dalej nie dochodzi) i w momencie odblokowania przerwań "sei" a dokładniej w linijce

    nie wiem czemu przeskakuje do 8 od dołu "reti" po czym dochodzi do pętli głównej i co drugi krok wraca do tego nieszczęsnego "reti". Nie mówiąc już o tym że nie reaguje na przerwania na które powinien :/

    
    .include "m16def.inc" 
    .equ granica = 10 ; wartosc graniczna dla timera
    .cseg 
    .org 0x00
    
    
    
    rjmp reset
    rjmp ext_int0
    reti
    reti
    reti
    reti
    rjmp timer_po37ms
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    
    
    	reset:
    
    
    	cli 							;wyłączenie zezwolenia na przerwania
    
    ;wskaznik stosu na koncu ramu
    
    	ldi		r16,high(RAMEND) 
    	out		SPH,r16 
    	ldi		r16,low(RAMEND)
    	out		SPL,r16
    
    ; porty 
    	ldi 	r16,0b11111111 ; same wyjscia
    	out 	DDRB, r16
    	ldi 	r16,0b11111111
    	out 	PORTB,r16
    	ldi 	r16,0b10000000 ; same wejscia
    	out 	DDRD, r16
    	ldi 	r16,0b00000000
    	out 	PORTD,r16
    
    
    ;konfiguracja przerwania od wejscia zewnętrznego
    
    	ldi r16,0b01000000
    	out gicr,r16
    	ldi r16,0b00000010
    	out mcucr,r16
    
    ; konfiguracja przerwania związanego z timerem 
    
    	ldi r16,0				; ustawienie pracy timera bez trybu PWM oraz wyzerowanie go
    	out tccr1a,r16
    	out tcnt1h,r16
    	out tcnt1l,r16
    	ldi r16,0b00001001		; ustawienie trybu CTC itp.
    	out tccr1b,r16		
    	ldi r16,high(granica)		; załadowanie żądanego czasu resetu timera (37ms)
    	out ocr1ah,r16
    	ldi r16,low(granica)	
    	out ocr1al,r16			
    	ldi r16,0b00010000		; ustawienie typu przerwania
    	out timsk,r16
    
    sei										; zezwolenie na przerwania					
    
    	ldi r17,0
    	ldi r18,0
    
    ;==================================================
    ; PĘTLA GŁÓWNA
    ;==================================================
    
    
    	petla:
    		out PORTB,r19
    		rjmp petla
    



    Ktoś mi to może wytłumaczy?
    Będę wdzięczny za pomoc i dobre rady.

    Proszę uściślić temat.
    Robak
  • REKLAMA
  • Pomocny post
    #2 9211215
    Andrzej__S
    Poziom 28  
    Cytat:

    nie wiem czemu przeskakuje do 8 od dołu "reti" po czym dochodzi do pętli głównej i co drugi krok wraca do tego nieszczęsnego "reti"

    Tam nie powinno być reti, a poza tym jako wektrów przerwań dla ATmega16 musisz używać instrukcji 'jmp', a nie 'rjmp'. Spróbuj zrobić tak:
    
    .....
    .org 0x00
    jmp reset 
    jmp ext_int0 
    jmp def_vect
    jmp def_vect
    jmp def_vect
    jmp def_vect
    jmp timer_po37ms 
    jmp def_vect
    jmp def_vect
    ........
    jmp def_vect
    
    ......
    
    def_vect:
       reti
    


    W ATmega16 wektory przerwań zajmują 2 słowa 16 bitowe, a instrukcje 'reti' i 'rjmp' zajmują tylko jedno słowo, w efekcie czego instrukcje skoku do procedury obsługi przerwań znajdują się pod nieodpowiednim adresem w pamięci flash.

    P.S. Jeszcze jedna uwaga. Zamiast:
    
       ldi r16,0b00001001      ; ustawienie trybu CTC itp.
       out tccr1b,r16
    

    naucz się korzystać z nazw bitów:
    
       ldi r16, (1<<WGM12) | (1<<CS10)
       out TCCR1B, r16
    

    W takim kodzie łatwiej ocenić poprawność i domyślić się, co autor programu chciał osiągnąć. Jak napiszesz 0b00001001 to trzeba za każdym razem sięgać do datasheet, bo wątpię, żeby ktoś znał numery bitów we wszystkich rejestrach wszystkich procesorów na pamięć. Za to nazwa bitu np. WGM12 już coś mówi.

    Poza tym rejestry też można sobie jakoś ponazywać, zgodnie z przeznaczeniem:
    
    .equ granica = 10 ; wartosc graniczna dla timera
    ......
    .def tmp1 = r16 ; rejestr tymczasowy
    .def moja_zmienna = r4
    ......
       ldi tmp1, granica
       mov moja_zmienna, tmp1
    

    To też znacznie zwiększa czytelność kodu.
  • REKLAMA
  • #3 9211719
    elektrokuba
    Poziom 12  
    DZIAŁA!
    Bardzo dziękuję! Sam bym tego na pewno nie wymyślił.
    Cenne uwagi też sobie wezmę do serca.
    Coraz bardziej mi się podobają te przerwania :)
    Jeszcze raz dziękuję za zainteresowanie i poświęcony czas.
    Temat można zamknąć.
  • REKLAMA
  • #4 9215604
    LordBlick
    VIP Zasłużony dla elektroda
    Dodam moj przepis na ładną tablicę wektorów (przykład dotyczy ATtiny2313) :
    .cseg
    ;———————————————————————————————————————————————————————————
    .org	0x00 ; Reset Handle
    	rjmp RESET
    ;————————————————————————————————————————————————————————————
    	.org	INT0addr ; External Interrupt0 Handle = 0x0001
    .ifdef EXT_INT0 ; Do not rename to INT0 - same name bit defined in GICR
    	rjmp EXT_INT0
    	.message "* EXT_INT0 Vector exist"
    .else
    	reti
    .endif	; .ifdef EXT_INT0
    ;————————————————————————————————————————————————————————————
    .org	INT1addr ; External Interrupt1 Handle = 0x0002
    .ifdef EXT_INT1 ; Do not rename to INT1 - same name bit defined in GICR
    	rjmp EXT_INT1
    	.message "* EXT_INT1 Vector exist"
    .else
    	reti
    .endif	; .ifdef EXT_INT1
    ;————————————————————————————————————————————————————————————
    .org	ICP1addr ; Input Capture1 (Timer/Counter1 Capture Event) Interrupt Handle = 0x0003
    .ifdef TIMER1_CAPT
    	rjmp  TIMER1_CAPT
    	.message "* TIMER1_CAPT Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER1_CAPT
    ;————————————————————————————————————————————————————————————
    .org	OC1Aaddr ; Output Compare1A (Timer/Counter1 Compare Match A)Interrupt Handle = 0x0004
    .ifdef TIMER1_COMPA
    	rjmp TIMER1_COMPA
    	.message "* TIMER1_COMPA Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER1_COMPA
    ;————————————————————————————————————————————————————————————
    .org	OVF1addr ; Timer/Counter1 Overflow Interrupt Handle = 0x0005
    .ifdef TIMER1_OVR
    	rjmp TIMER1_OVR
    	.message "* TIMER1_OVR Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER1_OVR
    ;————————————————————————————————————————————————————————————
    .org	OVF0addr ; Timer/Counter0 Overflow Interrupt Handle = 0x0006
    .ifdef TIMER0_OVR
    	rjmp TIMER0_OVR
    	.message "* TIMER0_OVR Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER0_OVR
    ;————————————————————————————————————————————————————————————
    .org	URXCaddr ; USART Receive Complete Interrupt Handle = 0x0007
    .ifdef USART_RXC
    	rjmp USART_RXC
    	.message "* USART_RXC Vector exist"
    .else
    	reti
    .endif	; .ifdef USART_RXC
    ;————————————————————————————————————————————————————————————
    .org	UDREaddr ; USART Data Register Empty Interrupt Handle = 0x0008
    .ifdef USART_DDRE
    	rjmp USART_DDRE
    	.message "* USART_DDRE Vector exist"
    .else
    	reti
    .endif	; .ifdef USART_DDRE
    ;————————————————————————————————————————————————————————————
    .org	UTXCaddr ; USART Transmit Complete Interrupt Handle = 0x0009
    .ifdef USART_TXC
    	rjmp USART_TXC
    	.message "* USART_TXC Vector exist"
    .else
    	reti
    .endif	; .ifdef USART_TXC
    ;————————————————————————————————————————————————————————————
    .org	ACIaddr ; Analog Comparator Interrupt Handle = 0x000a
    .ifdef ANA_COMP
    	rjmp ANA_COMP
    	.message "* ANA_COMP Vector exist"
    .else
    	reti
    .endif	; .ifdef ANA_COMP
    ;————————————————————————————————————————————————————————————
    .org	PCIaddr ; Pin Change Interrupt Handle	= 0x000b
    .ifdef PC_INT
    	_jmp PC_INT
    	.message "* PC_INT Vector exist"
    .else
    	reti
    .endif	; .ifdef PC_INT
    ;————————————————————————————————————————————————————————————
    .org	OC1Baddr ; Output Compare1B (Timer/Counter1 Compare Match B) Interrupt Handle = 0x000c
    .ifdef TIMER1_COMPB
    	rjmp TIMER1_COMPB
    	.message "* TIMER1_COMPB Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER1_COMPB
    ;————————————————————————————————————————————————————————————
    .org	OC0Aaddr ; Output Compare0A (Timer/Counter0 Compare Match A) Interrupt Handle = 0x000d
    .ifdef TIMER0_COMPA
    	rjmp TIMER0_COMPA
    	.message "* TIMER0_COMPA Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER0_COMPA
    ;————————————————————————————————————————————————————————————
    .org	OC0Baddr ; Output Compare0B (Timer/Counter0 Compare Match B) Interrupt Handle = 0x000e
    .ifdef TIMER0_COMPB
    	rjmp TIMER0_COMPB
    	.message "* TIMER0_COMPB Vector exist"
    .else
    	reti
    .endif	; .ifdef TIMER0_COMPB
    ;————————————————————————————————————————————————————————————
    .org	USI_STARTaddr	; USI Start Condition Interrupt Handle	= 0x000f
    .ifdef USI_START
    	rjmp USI_START
    	.message "* USI_START Vector exist"
    .else
    	reti
    .endif	; .ifdef USI_START
    ;————————————————————————————————————————————————————————————
    .org	USI_OVFaddr	; USI Overflow Interrupt Handle	= 0x0010
    .ifdef USI_OVERFLOW
    	rjmp USI_OVERFLOW
    	.message "* USI_OVERFLOW Vector exist"
    .else
    	reti
    .endif	; .ifdef USI_OVERFLOW
    ;————————————————————————————————————————————————————————————
    .org	ERDYaddr ; EEPROM Ready Interrupt Handle	= 0x0011
    .ifdef EE_RDY
    	rjmp EE_RDY
    	.message "* EE_RDY Vector exist"
    .else
    	reti
    .endif	; .ifdef EE_RDY
    ;————————————————————————————————————————————————————————————
    .org	WDTaddr	; Watchdog Timer Overflow Interrupt Handle	= 0x0012
    .ifdef WDT_OVERFLOW
    	rjmp WDT_OVERFLOW
    	.message "* WDT_OVERFLOW Vector exist"
    .else
    	reti
    .endif	; .ifdef WDT_OVERFLOW
    ;————————————————————————————————————————————————————————————
    Oczywiście w większych µC trzeba sobie skoki przerobic na dłuzsze, tam, gdzie to konieczne, lub użyć makra :
    .macro _jmp
    	.if FLASHEND>0x0fff && (@0-pc>2048 || pc-@0>2047)
    		jmp @0
    	.else
    		rjmp @0
    	.endif
    // 	(abs(@0-pc)>2048)?jmp:rjmp  @0
    .endmacro
  • #5 9463782
    elektrokuba
    Poziom 12  
    zamykam
REKLAMA