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

[C][Atmega8] Odczyt ADC z PC4

tomasz_wilko 18 Kwi 2009 19:36 1989 7
  • #1 6430007
    tomasz_wilko
    Poziom 14  
    Witam
    Jestem w trakcie pisania softu dla urządzenia które będzie kontrolowało 2 napięcia. Wykorzystuje multiplexowanie portów A/C Atmegi
    PC2 i PC4.
    Problem w tym, że nie dokonuje się odświeżanie bufora ADC który zmierzony został z PC4.
    kod programu:

    
    //*****************************************************************************
    //   
    // 
    //*****************************************************************************
    
    /*biblioteki*/
    
    #include <avr/io.h>             
    //#include <avr/delay.h> 
    
    #include "const_bit.h"
    #include "wait.h"
    
    unsigned int adc_data = 0;
    
    #define t1	0
    #define LED1 BIT0
    #define LED2 BIT7
    #define LED3 BIT6
    #define LED4 BIT5
    #define PORT_LED1 PORTB
    #define PORT_LED2 PORTD
    #define PORT_LED3 PORTD
    #define PORT_LED4 PORTD
    #define PORT_LED234 PORTD
    
    #define BUZER BIT1
    #define PORT_BUZER PORTC
    //------------------------------------------------------------------------------
    //                          Tester 
    //------------------------------------------------------------------------------
    
    //#################################### Test 
    void test2(void)
    {
    	int x;
    	ADMUX &= ~7;
    	ADMUX |= 2; //kanał  
    	ADCSRA |= _BV(ADSC); //Start 
    
        while (ADCSRA & _BV(ADSC) ) {}// czekaj na koniec konwersji
        adc_data = ADCW;    // pobrano wartosc ADC
    
    	PORT_LED1 = LED1; //CZYSC LEDY
    	    if( adc_data>778) // >3.8V
    		{	
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    		}
    	    else if(adc_data>737) // >3.6V
    		{
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    		}
    	    else if(adc_data>717) // >3.5V
    		{	
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    		}
    	    else if(adc_data>676) // >3.3V
    		{
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    		}
    		else 	//brak baterii
    		{
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    			PORT_LED1 &= ~LED1; wait_ms(t1); PORT_LED1 |= LED1; wait_ms(t1);
    		}
    }
    
    //#################################### Test Baterii 2
    void test4(void)
    {
    	int x;
    	ADMUX = 4; //kanał 
    	ADCSRA |= _BV(ADSC); //Start 
    
        while (ADCSRA & _BV(ADSC) ) {}// czekaj na koniec konwersji
        adc_data = ADCW;    // pobrano wartosc ADC
    
    	PORT_LED2 = LED2+LED3+LED4; //CZYSC LEDY
    	    if( adc_data>778) // >3.8V
    		{	
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    		}
    	    else if(adc_data>737) // >3.6V
    		{
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    		}
    	    else if(adc_data>717) // >3.5V
    		{	
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    		}
    	    else if(adc_data>676) // >3.3V
    		{
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    		}
    		else 	//brak baterii
    		{	PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    			PORT_LED2 &= ~LED2; wait_ms(t1); PORT_LED2 |= LED2; wait_ms(t1);
    		}
    }
    
    
    //------------------------------------------------------------------------------
    //                         
    //------------------------------------------------------------------------------
    
    void adc_init(void)
    {
    	// 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  (1/8 częstotliwosci zegara kontrolera) 
    	ADCSRA |= _BV(ADPS0);	 
    	ADCSRA |= _BV(ADPS1);	//
    }
    
    //------------------------------------------------------------------------------
    //                          
    //------------------------------------------------------------------------------
    int main (void) 
    {
      DDRB = 0XFF;
      DDRD = 0XFF;	
      
      PORTB = 0XFF;
      PORTD = 0XFF;
    
       adc_init();
      for (;;) {  
      test2();
      wait(1);
      test4();
      wait(1);
      }
    
    }
    
    
    


    Czy ktoś ma jakiś pomysł dlaczego nei ma odświeżania wartości z PC4??
    Kanał PC2 chodzi super, PC4-za 1 razem odczyta wartość prawdziwą ,ale nadal pozostaje ona w buforze.
    proszę o pomoc
    dzięki


    Poprawiłem tytuł - Regulamin. [c_p]
  • #2 6430085
    BoskiDialer
    Poziom 34  
    void test2(void)
    {
    	// ..
    	ADMUX &= ~7;
    	ADMUX |= 2; //kanał  
    	// ...
    }
    
    void test4(void)
    {
    	// ...
    	ADMUX = 4; //kanał 
    	// ...
    }
    
    void adc_init(void)
    {
    	// 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);		
    	// ...
    }
    

    Zastanawiam się, czy nie przełączasz czasem ADC na zewnętrzne źródło odniesienia oraz wyrównanie do prawej, wpisując 4 do ADMUX zamiast manipulować bitami.
  • #3 6430149
    Dawid_20
    Poziom 17  
    void test2(void) 
    { 
       // .. 
       ADMUX &= ~_BV(2); 
       ADMUX |= _BV(1); //kanał  
       // ... 
    } 
    
    void test4(void) 
    { 
       // ... 
       ADMUX &=~_BV(1);
       ADMUX |= _BV(2); 
       // ... 
    } 


    A ADLAR bym sobie darował go ruszać i odczytywał poprostu ADCW
  • #4 6430331
    tomasz_wilko
    Poziom 14  
    Niestety zmiana z ADCL ADCH na ADCW nie zmienia niczego:/
  • #5 6430421
    Dawid_20
    Poziom 17  
    Nie robi różnicy czy odczytujesz ADCL ADCH czy ADCW,chodzi tylko o wyrównanie bitów przez ADLAR. Ale to tak na marginesie,bo to nie jest powodem, że nie czyta ci z kanału 4. Nie stosuj bezpośrednich zapisów pod ADMUX tak jak np ADMUX = 4; bo automatycznie zmieniasz konfiguracje przetwornika. Zobacz jak ja korzystam z pierwszych czterech kanałów:

    Inicjalizacja:
    ADCSRA = _BV(ADEN) |_BV(ADPS0)|_BV(ADPS1);


    Odczyt:
    void pomiar_ADC(uint8_t kanal)
    {
    	uint8_t i;
    	if(kanal==0) { ADMUX &= ~_BV(0); ADMUX &= ~_BV(1); }
    	if(kanal==1) { ADMUX |= _BV(0); ADMUX &= ~_BV(1); }
    	if(kanal==2) { ADMUX &= ~_BV(0); ADMUX |= _BV(1); }
    	if(kanal==3) { ADMUX |= _BV(0); ADMUX |= _BV(1); }
    
    		POMIAR[kanal]=0;
    		for(i=0;i<10;i++)
    		{
    			ADCSRA |= _BV(ADSC);
    			while(bit_is_set(ADCSRA,ADSC));
    			POMIAR[kanal]+=ADCW;
    		}
    		POMIAR[kanal]/=10;
    }


    Mam nadzieje, że się przyda:)
  • #6 6431919
    tomasz_wilko
    Poziom 14  
    Witam
    BoskiDialer:
    Cytat:
    ...czy nie przełączasz czasem ADC na zewnętrzne źródło odniesienia oraz wyrównanie do prawej, wpisując 4 do ADMUX zamiast manipulować bitami

    Zmieniłem tę część na :
    	ADMUX &= ~7;
    	ADMUX |= 2; //kanał  

    - niestety, to chyba jednak nie to.
    Dawid_20 : dzięki za kod, ale nadal ten problem występuje.
    Może mam coś źle w kompilatorze ustawione,... nie mam pojęcia kompletnie.

    Postaram się zdobyć ICE 2 programator i zdebugować procesor.
    Na razie dzięki za pomoc, może ktoś jeszcze ma coś co pomoże?? , proszę o wskazówki .
  • #7 6434918
    dawid512
    Poziom 32  
    A może po prostu masz uszkodzony ten kanał? Próbowałeś na innym kanale/uc?
  • #8 6436137
    rrata
    Poziom 19  
    tomasz_wilko napisał:
    Witam
    BoskiDialer: Cytat:
    ...czy nie przełączasz czasem ADC na zewnętrzne źródło odniesienia oraz wyrównanie do prawej, wpisując 4 do ADMUX zamiast manipulować bitami


    Zmieniłem tę część na : Kod:
    ADMUX &= ~7;
    ADMUX |= 2; //kanał


    - niestety, to chyba jednak nie to.
    Czyli na to samo co w funkcji test2. Dwa razy czytasz ten sam kanał.
REKLAMA