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

[ATtiny13][C] - dziwne zachowanie, oraz przerwania zew.

Dragas 16 Gru 2010 19:33 1345 4
REKLAMA
  • #1 8876892
    Dragas
    Poziom 26  
    Witam
    Próbuję zrobić tak, aby po naciśnięciu 1 z 4 switchy zapalała się dioda led, i w zależności który wciśniemy, zaświeciła się dioda określoną ilość razy.

    Kod:
    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/signal.h> 
    
    #define SET_OUT_LED DDRB |= (1<<PB3) //inicjacja
    #define SET_LED PORTB |= (1<<PB3)  //włącza
    #define CLR_LED PORTB &= (0<<PB3)  //gasi
    
    int main(void)
    {
    	PORTB &= ~(0<<PB0);
    	PORTB &= ~(0<<PB1);
    	PORTB &= ~(0<<PB2);
    	PORTB &= ~(0<<PB4);
    
    	const int przerwa1 = 250;
    	const int przerwa3 = 1500;
    	
    	char licz = 0;
    	
    	SET_OUT_LED;
    	
        while (1) 
        {
    		licz = 1;
    		if((!(PINB & _BV(2))) && licz == 1)
    		{
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa3);// 1
    			licz = 0;
    		}
    		if((!(PINB & _BV(1))) && licz == 1)
    		{
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa1);// 1
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa3);// 2
    			licz = 0;
    		}
    		
    		if((!(PINB & _BV(0))) && licz == 1)
    		{
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa1);// 1
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa1);// 2
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa3);// 3
    			licz = 0;
    		}
    		
    		if((!(PINB & _BV(4))) && licz == 1)
    		{
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa1);// 1
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa1);// 2
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa1);// 3
    			SET_LED;
    			_delay_ms(przerwa1);
    			CLR_LED;
    			_delay_ms(przerwa3);// 4
    			licz = 0;
    		}
        }
    }

    I problem polega na tym, że po podłączeniu zasilania uC sprawdza, który switch został włączony, i wtedy zapala led'a z przerwami, ale po skończeniu tego, pomimo, że nic nie jest włączone, cały czas, w pętli wykonuje, to co dostał na początku, nie wiadomo dlaczego?

    Jeśli ktoś widzi jakiś błąd, to proszę o pomoc.
  • REKLAMA
  • #2 8876935
    mirekk36
    Poziom 42  
    a wyjaśnij nam co to jest to coś?

    
       PORTB &= ~(0<<PB0); 
       PORTB &= ~(0<<PB1); 
       PORTB &= ~(0<<PB2); 
       PORTB &= ~(0<<PB4); 
    


    bo mi tu pachnie totalnym nieporozumieniem. Sam się zastanów po pierwsze co to miało robić i czy nie chodziło ci tutaj przypadkiem o podciąganie do VCC.

    Dodano po 28 [sekundy]:

    co tu robią w ogóle zera? ;)
  • REKLAMA
  • #3 8876943
    Dragas
    Poziom 26  
    
       PORTB &= ~(0<<PB0);
       PORTB &= ~(0<<PB1);
       PORTB &= ~(0<<PB2);
       PORTB &= ~(0<<PB4);
    

    To ustawić piny jako wejściowe, przynajmniej tak mi się zdaje, że takie jest tego zadanie.
  • REKLAMA
  • Pomocny post
    #4 8876979
    mirekk36
    Poziom 42  
    Po pierwsze to po resecie mikrokontrolera piny są ustawione jako wejścia więc nawet nie trzeba tego robić

    Po drugie to kierunek ustala się za pomocą rejestru DDRx a nie PORTx (to nie Bascom)

    Po trzecie to musisz doczytać jeszcze o przesunięciach bitowych bo szybko na tym polegniesz w C. To podstawa.

    Po czwarte to klawisze (słicze) musisz mieć albo podciągnięte zewn rezystorem do VCC ale po co skoro można programowo wystawiając jedynkę na pin słicza

    tyle że np tak:

    
    #define KL1 (1<<PB0)
    #define KL2 (1<<PB1)
    
    // ustawiamy kierunek jeśli już chcemy na siłę ;)
    DDRB &= ~( KL1 | KL2 );
    
    // podciągamy do VCC
    PORTB |= KL1 | KL2;
    
  • #5 8877095
    Dragas
    Poziom 26  
    Bez podciągnięcia switchy do Vcc, układ sam zapala led'a. Ale pod podciągnięciu VCC, częściowo jest dobrze. Jednakże jest ten sam problem. Kiedy nacisnę 1 raz któryś switch, to ta instrukcja wykonuje się w nieskończoność. Jak temu zaradzić?

    Dodano po 12 [minuty]:

    Udało mi się rozwiązać problem w następujący sposób:
    Po wykonaniu danej operacji, na nowo podciągam piny switchy do VCC, i w ten sposób, program działa poprawnie(przynajmniej jak na razie).

    Na chwilę obecną problem uważam za rozwiązany, jednak przy okazji chciałbym się dowiedzieć, w jaki sposób zbudzić uC, jeśli dam mu tryb power-down. Chciałem zrobić tak jak atmegaX, z INT, ale jest tylko PCINT, które niestety, ale nie reaguje.

    
    #######WYKONANIE PRZERWANIA########
    ISR(PCINT0_vect)
    {
    	cli();
    	set_sleep_mode(SLEEP_MODE_PWR_SAVE);
    	sleep_mode()
    }
    
    
    ######Włączenie przerwań zew.#######
    MCUCR = (1<<ISC01);
    GIMSK = (1<<PCINT0);
    
    
    Po linku krotnym wykonaniu kodu, program przechodzi i tryb power-down:
    sei();
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_mode();
    
    


    Pozdrawiam Dragas
REKLAMA