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

Problem z zewnętrznym przerwaniem

mati1988k 31 Gru 2010 19:38 1188 3
REKLAMA
  • #1 8940779
    mati1988k
    Poziom 13  
    Witam.

    Podłączyłem klawiaturę do uc, naciśniecie przycisku powoduje zmianę stanu wejścia PD2 przez co uc wskakuje w przerwanie. W nim sprawdza po kolei który dokładnie przycisk jest wciśnięty poprzez podłączenie wyjść switchy do GND co ma spowodować spadek napięcia na PD2 czyli logiczne 0. W przerwanie dobrze wykrywa który przycisk jest wciśnięty, sygnalizuje to ilość zapalonych diod podłączonych pod PA. Następnie czeka na puszczenie przycisku i 10ms aby wyeliminować drganie styków i ponowne wejście w przerwanie. Po odczekaniu 10ms nie wiem czemu ale na porcie A ustawiana jest jakaś dziwna wartość tj. 0b11111110 nie mam pojęcia czemu się tak dzieje.

    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    #define SetBit(x,y)	x |= (1<<y)
    #define ClrBit(x,y) x &= ~(1<<y)
    #define NegBit(x,y) x ^= (1<<y)
    
    volatile int p=0;
    
    ISR (INT0_vect) 
    {
    		_delay_ms(5);
    		p=0;
    
    		NegBit(PORTA, 4);
    
    		ClrBit(DDRD, 7);
    			_delay_ms(5);
    			if(bit_is_set(PIND, 2)) p=4;
    		SetBit(DDRD, 7);
    			_delay_ms(5);
    
    
    		ClrBit(DDRD, 6);
    			_delay_ms(5);
    			if(bit_is_set(PIND, 2)) p=3;
    		SetBit(DDRD, 6);
    			_delay_ms(5);
    
    
    		ClrBit(DDRD, 5);
    			_delay_ms(5);
    			if(bit_is_set(PIND, 2)) p=2;
    		SetBit(DDRD, 5);
    			_delay_ms(5);
    
    
    		ClrBit(DDRD, 4);
    			_delay_ms(5);
    			if(bit_is_set(PIND, 2)) p=1;
    		SetBit(DDRD, 4);
    			_delay_ms(5);
    
    		DDRD=0b11110000;
    
    
    		if(p==1)
    		{
    			PORTA=0b01111111;
    			p=0;
    		}
    
    		if(p==2)
    		{
    			PORTA=0b00111111;
    			p=0;
    		}
    
    		if(p==3)
    		{
    			PORTA=0b00011111;
    			p=0;
    		}
    
    		if(p==4)
    		{
    			PORTA=0b00001111;
    			p=0;
    		}
    
    
    		while(bit_is_clear(PIND, 2))
    		{
    			NegBit(PORTA, 3); 
    			_delay_ms(100);
    		}
    
    		_delay_ms(20);
    }
    
    
    int main(void)
    {
    	DDRD=0xf0;
    	PORTD=0b00001100;
    	DDRA=0xff;
    	PORTA=0b01010101;
    
    	// Przyciski//
    	MCUCR = (1<<ISC01);
    	GIMSK |= (1<<INT0);
    
    	sei();
    
    	while(1)
    	{
    
    	}
    }
    


    Schemat wygląda mniej więcej tak z tym, że klawiatura podłączona jest pod inne WE/WY.

    Problem z zewnętrznym przerwaniem
  • REKLAMA
  • #2 8940793
    mirekk36
    Poziom 42  
    Witam,

    Niestety ale strasznie źle podchodzisz do tego zagadnienia bo w przerwaniu dajesz jakieś masakryczne opóźnienia i pętle, które mogą się nie skończyć nigdy. Zdecydowanie odradzam takie pomysły.

    Przerwania dla klawiatury matrycowej, owszem można używać ale postaraj się skorzystać z flag i te sprawdzania, które tu wykonujesz w przerwaniu przenieś do pętli głównej to od razu będzie lepszy efekt - jeśli chodzi o takie testy oczywiście. Bo generalnie to i tak tego typu obsługa będzie blokująca z uwagi na te wszystkie _delay'e.
  • REKLAMA
  • #3 8943364
    maly_elektronik
    Poziom 23  
    Poco delay w przerwaniu :?: Nie lepiej pomanipulować preskalerem :?:
    A te wszystkie przyciski to po prostu przed diodę i na wejście przerwania :)
    Kliknięcie któregokolwiek z przycisków spowoduje wejście w przerwania a tam prosty chociażby switch + volatile załatwi sprawę rozpoznania przycisku (pinu)

    Pozdrawiam maly_elektronik
  • #4 8943941
    Fredy
    Poziom 27  
    Czemu ty robisz tam taką konstrukcję:

    ClrBit(DDRD, 4); 
             _delay_ms(5); 
             if(bit_is_set(PIND, 2)) p=1; 
          SetBit(DDRD, 4); 


    Mylisz rejestry - powinieneś zmieniać stan rejestrów PORT a nie DDR.
    DDR ustaw na zawsze jako wyjściowe.
REKLAMA