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

[atmega8][C] Nie działa Timer razem z A/C

BugsdBunny 17 Lut 2009 01:08 1624 3
  • #1 6161330
    BugsdBunny
    Poziom 14  
    
    
    #include <avr/io.h>
    #include <util/delay.h>    
    #include <avr/interrupt.h>        
    #include <avr/signal.h>  
    
    
    #define F_CPU 1000000
    #define PORT_AD PORTC		// Port z wejściami analogowymi	
    #define DDR_AD DDRC			
    #define PORT_OUT PORTB		// Port do którego przyłączone są diody LED
    #define DDR_OUT DDRB
    #define PORT_F PORTD		// Port do którego przyłączony jest przycisk. Bit 4 tego portu
    					// jest wykorzystany jako flaga naciśnięcia klawisza
    #define DDR_F DDRD
    #define PIN_F PIND
    
    
    uint8_t sign[] = 
    {
    	_BV(0) | _BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5) ,  // 0
    	_BV(1) | _BV(2) ,  // 1
    	_BV(0) | _BV(1) | _BV(6) | _BV(4) | _BV(3) ,  // 2
    	_BV(0) | _BV(1) | _BV(2) | _BV(3) | _BV(6) ,  // 3
    	_BV(5) | _BV(6) | _BV(1) | _BV(2) ,  // 4
    	_BV(0) | _BV(5) | _BV(6) | _BV(2) | _BV(3) ,  // 5
    	_BV(0) | _BV(5) | _BV(4) | _BV(3) | _BV(2) | _BV(6),  // 6
    	_BV(0) | _BV(1) | _BV(2) ,  // 7
    	_BV(0) | _BV(1) | _BV(2) | _BV(3) | _BV(4) | _BV(5) | _BV(6),  // 8
    	_BV(0) | _BV(1) | _BV(2) | _BV(3) | _BV(5) | _BV(6),  // 9
    
    };
    
    
    unsigned int pomiar;		// Zmienna do przechowywania wyniku pomiaru
    
    unsigned int cyf1;
    unsigned int cyf10;
    unsigned int cyf100;
    unsigned int cyf1000;
    unsigned int liczba;
    
    
    ISR(TIMER1_COMPA_vect)
    {
    		//ADCSRA |= _BV(ADSC);     		    // Rozpoczęcie przetwarzania
    		//	while(bit_is_set(ADCSRA,ADSC)){};	 // Oczekiwanie na zakończenie przetwarzania
    		//	pomiar=ADCH;					     // Zapisanie starszych 8 bitów wyniku konwersji do 
    			
    			liczba = 0;
    								    // zmiennej "pomiar" 
    			liczba += (pomiar & _BV(0));
    			liczba += (pomiar & _BV(1))*2;
    			liczba += (pomiar & _BV(2))*4;
    			liczba += (pomiar & _BV(3))*8;
    			liczba += (pomiar & _BV(4))*16;
    			liczba += (pomiar & _BV(5))*32;
    			liczba += (pomiar & _BV(6))*64;
    			liczba += (pomiar & _BV(7))*128;
    			liczba = 2123;
    			cyf1 = liczba % 10;
    			cyf10 = (liczba / 10) % 10;
    			cyf100 = (liczba / 100) % 10;
    			cyf1000 = (liczba / 1000) % 10;
    	
    }
    
    void Inicjalizacja(void)
    {
    	DDR_AD=0x3C;		// Port jako wejścia
    	PORT_AD=0x00;		// Wejścia bez podciągania
    	DDR_OUT=0xFF;		// Port jako wyjścia 
    	PORT_OUT=0xFF;		// Wyjścia w stanie wysokim
    	DDR_F=0xF0;		// Młodsza połowa portu jako wejścia, starsze cztery bity jako wyjścia
    	PORT_F=0xFF;		// Wejścia z podciąganiem wyjścia w stanie wysokim
    		
    // Wybranie wewnętrznego żródła napięcia odniesienia	
    	ADMUX |= _BV(REFS0);		
    	ADMUX |= _BV(REFS1);
    //	Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)	
    	ADMUX |= _BV(ADLAR);		
    // Zezwolenie na konwersję	
    	ADCSRA |= _BV(ADEN);		
    // Wybranie częstotliwości dla taktowania przetwornika   
    	ADCSRA |= _BV(ADPS0);	 
    	ADCSRA |= _BV(ADPS1);	
    	
    	
    	TCCR1B |= (1 << WGM12); // Ustawia timer w tryb CTC
    	OCR1A = 1565; // Ustawia wartość pożądaną na 1Hz dla preskalera 64
    	TCCR1B |= ((1 << CS10) | (1 << CS11)); // Ustawia timer z preskalerem Fcpu/64
    	TIMSK |= (1 << OCIE1A); // Zezwolenie na przerwania dla CTC
    	
    	   GIMSK = _BV(INT0);
    
    MCUCR = _BV(ISC01)|_BV(ISC11);
    }
    
    
    int main(void)
    {
    	Inicjalizacja();  // Inicjalizacja kontrolera
    	
    	
    	sei();
    	while(1)
    	{
    		
    
    			PORT_AD |= _BV(2);
    			PORT_OUT=~sign[cyf1]; 
    			_delay_us(10);
    			PORT_AD &= ~_BV(2);
    			
    			PORT_AD |= _BV(3);
    			PORT_OUT=~sign[cyf10]; 
    			_delay_us(10);
    			PORT_AD &= ~_BV(3);
    			
    			PORT_AD |= _BV(4);
    			PORT_OUT=~sign[cyf100]; 
    			_delay_us(10);
    			PORT_AD &= ~_BV(4);
    			
    			PORT_AD |= _BV(5);
    			PORT_OUT=~sign[cyf1000];
    			PORT_OUT &= ~ _BV(7);
    			_delay_us(10);
    		
    		
    	}
    }
    
    


    Jeżeli odczyt z ISR(TIMER1_COMPA_vect) wstawie do WHILE(1) to wszystko działą i wartośc odczytaną z wejścia A/C 0 pokaże na wyświetlaczu. Chciałem jednak opóźnić odczyt używając TIMER no i cały czas mam zera ....a powinno się pojawić 2123. Co jest nie tak ??
  • #2 6161570
    chudybyk
    Poziom 31  
    Witam!
    Ciut namieszane w kodzie, ale myślę, że to, co najbardziej szkodzi, to deklaracja zmiennych, które używasz w przerwaniu i w programie głównym jednocześnie. Spróbuj wszystkie takie zmienne zadeklarować jako "volatle", czyli
    volatile unsigned int pomiar;
    itd. ...
    Ta deklaracja spowoduje, że odwołania do niej będą realizowane wprost, bez optymalizacji.
    Pozdrawiam!
  • #3 6162204
    BugsdBunny
    Poziom 14  
    Już śmiga.

    Nasuwa mi się jednak takie pytanie niezwiązane z tematem. Jeżeli dodam do tego układu WATCHDOG to co z moimi zmiennymi ?? Tzn czy jezeli mam zmienna wartosc1 która sobie jakoś na buttonach ustawiłem wartość po resecie WATCHDOGa wszystko się wyzeruje ?? Jezeli tak to jak zachować pamięć (niezewnętrzną)
  • #4 6162272
    chudybyk
    Poziom 31  
    Zdaje się, że zmienne globalne są przy starcie inicjowane na zero przez kompilator. Reset z WatchDoga spowoduje ponowne uruchomienie programu, więc również procedur inicjacyjnych zerujących zmienne.
    Spróbuj zadeklarować tablicę, nawet 1-elementową. Zawartości takiej tablicy nic nie powinno zmienić po resecie.
    Dla formalności jednak zaznaczę, że zadziałanie układu Watchdog ma za zadanie wyciągnąć program z błędnego stanu, więc w normalnej pracy nie powinien wystąpić. Zwykle jest efektem błędu programisty.
REKLAMA