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

[Atmega8][ASM] Problem z przerwaniami zew. INT0

Lukis 28 Maj 2008 13:48 3863 8
REKLAMA
  • #1 5190269
    Lukis
    Poziom 11  
    Witam
    Piszę program, który ma mierzyć długość impulsu podawanego z zew. źródła jakim jest odbiornik RC, częstotliwość impulsów to 50Hz, a ich długość mieści sie w przedziale 1ms-2ms. To mój pierwszy program na AVR w którym obsługuje przerwania zew. i mam pewien problem, program już napisałem, sprawdziłem go na symulatorze i wydaje się działać poprawnie, tylko że musiałem ręcznie ustawiać flagę od przerwania INT0, po wgraniu do procesora nic sie nie dzieje tak jakby w ogóle nie było reakcji na sygnał. Nie wiem czy dobrze ustawiłem procesor, ale z tego co zrozumiałem z noty katalogowej to chyba tak ma być, poniżej zamieszczam część kodu:
    
    ;----------------------------------- Światła ----------------------------------------------
    
    .nolist 	  				;
    .include 	 "m8def.inc" 	;
    .list 	  					;
    .listmac 	  				;
    
    
    ;--------------------------------------------------------------------------------------------
    .def 	ACC = r16 				; r16 teraz ma nazwę acc
    .def	wskaznik = r17
    .def	ACC2 = r21
    .def	ACC3 = r28
    
    ;--------------------------------------------------------------------------------------------
    
    ;-------------------- Początek segmentu kodu (Code Segment) ---------------------------------
    
      	.cseg 	  					;
      	.org 	0 					;
      	rjmp 	ResetProcessor 		;
    
    
    ;----------------- Tabela wektorów przerwań (Interrupt Vectors) ----------------
    
    	.org	0x001		
    	rjmp	Sygnal						;INT0
    	.org	0X002		
    	rjmp	Przerwanie					;INT1
    	.org	0x003 		
    	rjmp	Przerwanie					;TIMER2-COMP
    	.org	0x004		
    	rjmp	Przerwanie					;TIMER2-OVF
    	.org	0x005		
    	rjmp	Przerwanie					;TIMER1-CAPT
    	.org	0x006		
    	rjmp	Przerwanie					;TIMER1-COMPA
    	.org	0x007		
    	rjmp	Przerwanie					;TIMER1-COMPB
    	.org	0x008		
    	rjmp	Przerwanie					;TIMER1-OVF
    	.org	0x009		
    	rjmp	Przerwanie					;TIMER0-OVF
    	.org	0x00A 		
    	rjmp	Przerwanie					;SPI-STC
    	.org	0x00B		
    	rjmp	Przerwanie					;USART-RXC
    	.org	0x00C		
    	rjmp	Przerwanie					;USART-UDRE
    	.org	0x00D		
    	rjmp	Przerwanie					;USART-TXC
    	.org	0x00E		
    	rjmp	Przerwanie					;ADCC
    	.org	0x00F		
    	rjmp	Przerwanie					;EE_RDY
    	.org	0x010 		
    	rjmp	Przerwanie					;ANA_COMP
    	.org    0x011			
    	rjmp	Przerwanie					;TWI
    	.org	0x012 		
    	rjmp	Przerwanie					;SPM_RDY
    
    Przerwanie:
    	reti
    
    
    
    ;---------------------------------------------------------------------------------------------
    	
    ;-----------------------------Ustawienia portów----------------------------------------------
    
    ResetProcessor: 	  			;
      	cli 	  					; zablokowanie przerwań
      	ldi 	ACC,HIGH(RAMEND) 	; inicjacja stosu
      	out 	SPH,ACC 			; programowego
    	ldi		ACC,LOW(RAMEND)
    	out		SPL,ACC
    
    	
    	ldi 	ACC,0x40 			;ustawienie bitu odpowiedzialnego za akceptcję
    	out 	GICR,ACC 			;przerwania INT0 w rejestrze GIMSK
    
    	ldi 	ACC,0x02 			;zbocze narastające na INT0 będzie
    	out 	MCUCR,ACC 			;generowac przerwanie
    
    	
      	ldi 	ACC,0x00 			
      	out 	DDRC,ACC 			;cały port C jako wejściowy
    	out		DDRD,ACC			;cały port D jako wejściowy 
      	out 	PORTC,ACC 			;wszystkie wyjścia portu C w stanie niskim
    	out 	PORTD,ACC 			;wszystkie wyjścia portu D w stanie niskim
    
      	ldi 	ACC,0xFF 			
      	out 	DDRB,ACC 			;cały port B jako wyjściowy 
    	ldi 	ACC,0x00 			
      	out 	PORTB,ACC 			;wszystkie wyjścia portu B w stanie niskim
    
    	ldi		wskaznik,0x01
    	ldi		r18,0xBC			;wartość porównawcza
    	ldi		r19,0x04
    	ldi		r22,0x01
    	ldi		r23,0x00
    	ldi		r24,0x01
    	ldi		r25,0x00
    	ldi		r26,0x01
    	ldi		r27,0x00
    	ldi		r20,0x00
    	ldi		r30,0x00
    
    	sei							;odblokowanie przerwań
    
    	rjmp 	Main
    


    Tak wygląda ustawienie procesora i tu właśnie nie wiem czy wszystko ustawiłem tak jak należy, sygnał wchodzi na nóżkę PD2 czyli INT0, przerwanie ma zostać wygenerowane podczas zbocza narastającego.

    A tu jest obsługa tego przerwania:

    
    ;--------------------------------Obsługa przerwania------------------------------------------------
    ;--------------------------------------------------------------------------------------------------
    Sygnal:
    	push	ACC
    	sbrs	r17,0
    	rjmp	opadajace
    	rjmp	narastajace
    
    narastajace:
    	ldi		ACC,0x03
    	out		MCUCR,ACC				;zbocze opadające
    	ldi		r17,0x00
    	ldi 	ACC,0x00 				;wpisz wartosć początkową licznika
    	out 	TCNT0,ACC
     	ldi 	ACC,0x03				;włącz timer0, prescaler 8
    	out 	TCCR0,ACC
    	rjmp	koniec
    
    opadajace:
    	ldi		ACC,0x02
    	out		MCUCR,ACC				;zbocze narastające
     	ldi 	ACC,0					;wyłącz timer0
    	out 	TCCR0,ACC
    	in		ACC,TCNT0				;pobierz liczbe z licznika T0
    	ldi		r17,0x01
    	
    	cp		ACC,r18
    	brlo	wylacz
    	brsh	zalacz
    
    zalacz:
    	cpi		r19,0x04
    	breq	zalaczenie
    	cpi		r19,0x02
    	breq	ladowanie
    	rjmp	koniec
    
    wylacz:
    	cpi		r19,0x03
    	breq	nic
    	cpi		r19,0x01
    	breq	wylaczenie
    	rjmp	koniec
    	
    wylaczenie:
    	ldi		r19,0x04
    	ldi		r20,0x01
    	rjmp 	koniec	
    
    zalaczenie:
    	dec		r19
    	ldi		r20,0x02
    	rjmp 	koniec
    
    ladowanie:
    	dec		r19
    	ldi		r20,0x03
    	rjmp 	koniec
    
    nic:
    	dec		r19
    koniec:
    	pop		ACC
    	reti
    


    W obsłudze przerwania włączam licznik T0 który liczy czas, i zmieniam typ reakcji na sygnał na zbocze opadające, które z kolei wyłącza T0 i z powrotem zmienia reakcje na zbocze narastające. Dokładność tego pomiaru nie jest aż tak znacząca bo muszę rozpoznać tylko czy sygnał jest mniejszy niż 1.5ms czy większy.

    Procesor działa na wew. rezonatorze 1MHz, co daje chyba 1us na wykonanie jednego rozkazu, czy się mylę? Tak pokazywał symulator.

    Może ktoś wie w czym tkwi problem i pomoże mi go rozwiązać?

    Dziękuje i pozdrawiam
    Łukasz
  • REKLAMA
  • #2 5190444
    zumek
    Poziom 39  
    Pierwszą nieścisłość jaką zauważyłem , to niezgodna z komentarzami w kodzie , konfiguracja zboczy na jakie ma reagować INT0.
       ldi    ACC,0x02          ;zbocze narastające na INT0 będzie
       out    MCUCR,ACC          ;generowac przerwanie
    

    Powyższe , ustawia reakcję INT0 , na zbocze opadające (Falling).
    Co to za tajemnicze urządzenie RC - odbiornik podczerwieni :?:
    Po czym poznajesz , że przerwania nie działają :?:
    Ponad to , dużym ułatwieniem dla czytających cudzy kod , jest używanie nazw symbolicznych np.
    LDI ACC , (1<<ISC01)



    To na razie tyle :D

    Piotrek
  • #3 5190593
    Lukis
    Poziom 11  
    Odwróciłem reakcje na zbocza, tam gdzie było opadające jest teraz narastające i odwrotnie, czyli tak jak było zamierzone, ale nadal nic.

    To tajemnicze urządzenie to modelarski 7 kanałowy odbiornik na pasmo 35MHz i to on generuje te impulsy.

    Co oznacza (1<<ISC01)? Bo jeszcze tego nie wiem.

    A wnioskuje, że problem jest z przerwaniami, ponieważ impuls poniżej 1.5ms wyłącza diody LED, a impuls powyżej 1.5ms ma powodować załączenie tych diod. Na symulatorze kiedy ręcznie włączałem flagę przerwania z INT0 następował skok do procedury obsługi tego przerwania i tam było wszystko ok. Więc problem jest chyba w tym że albo nie generuje tej flagi, albo mam coś pogmatwane z porównywaniem wartości zadaniej z tą zmierzoną.
    Przy częstotliwości 1MHz jeden rozkaz będzie sie wykonywał 1us - tak wskazuje symulator, czy 10us?
  • REKLAMA
  • #4 5190831
    zumek
    Poziom 39  
    Lukis napisał:
    ...A wnioskuje, że problem jest z przerwaniami, ponieważ impuls poniżej 1.5ms wyłącza diody LED, a impuls powyżej 1.5ms ma powodować załączenie tych diod...

    No to uprość tymczasem procedurę przerwania do niezbędnego minimum i sprawdź czy uC "wskoczył" do niej .
    Dopisz np.
    Sygnal:
    ;w zależności jak podłączyłeś LED-kę
       SBI    port_z_diodą_led , bit_z_diodą_led
    ;lub 
       CBI    port_z_diodą_led , bit_z_diodą_led
       RETI
    
       push   ACC
       sbrs   r17,0
       rjmp   opadajace
       rjmp   narastajace
    ;...


    Piotrek
  • #5 5191004
    Lukis
    Poziom 11  
    Zrobiłem żeby dioda mrugała co 1s około, przerwanie sie wykonuje, ale jest jeszcze inny problem :/, wykonuje sie ono nawet przy odłączonym odbiorniku i kablu wiszącym w powietrzu. Sprawdziłem miernikiem i tak:
    - przy mruganiu co 1s częstotliwość na nóżce INT0 wynosi około 50Hz
    - przy mruganiu co 2s częstotliwość na nóżce INT0 wynosi około 100Hz
    - przy mruganiu co 3s częstotliwość na nóżce INT0 wynosi około 150Hz

    Im dłużej czekam w przerwaniu odliczając czas w pętli tym większa jest częstotliwość na nóżce INT0.

    Po zwarciu wyprowadzenia INT0 do masy lub do plusa przerwanie sie nie wykonuje.

    Nóżka procka raczej nie jest upalona bo daje sie sterować, więc sam juz nie wiem.
  • REKLAMA
  • #6 5191076
    zumek
    Poziom 39  
    Lukis napisał:
    ...Nóżka procka raczej nie jest upalona bo daje sie sterować, więc sam juz nie wiem.

    Włącz wewnętrzny lub przylutuj zewnętrzny np. 10k0 pull-up(rezystor podciągający do VCC) na tym pinie i zobacz co się będzie działo.

    Piotrek
  • REKLAMA
  • #7 5191161
    Lukis
    Poziom 11  
    Chyba sie udało, z wiszącym kablem nic sie nie dzieje, po wpięciu do odbiornika dioda zaczyna mrugać.

    Teraz inne pytanie z kwarcem 1MHz ile trwa wykonanie jednego cyklu? Symulator pokazuje 1us a mi sie wydaje ze 10us.
  • Pomocny post
    #8 5191175
    zumek
    Poziom 39  
    Lukis napisał:
    ...Symulator pokazuje 1us a mi sie wydaje ze 10us.

    W tym wypadku , uwierz symulatorowi ;)

    Piotrek
  • #9 5192445
    Lukis
    Poziom 11  
    Wielkie dzięki Zumek za pomoc, wszystko już działa jak należy :) projekt można powiedzieć skończony :)
REKLAMA