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 przetwornikiem A/C Atmega8 [C]

jaros85 07 Mar 2010 18:51 1702 7
REKLAMA
  • #1 7797592
    jaros85
    Poziom 20  
    Witam oto mój kod obsługi przetwornika A/C i niestety jest problem w terminalu odbieram tylko same jedynki.

    #define F_CPU 8000000
    #define UART_BAUD	4800
    #define UBRR	(F_CPU/(16ul*UART_BAUD)-1)
    
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    #include <string.h>
    #include <stdlib.h>
    
    
    
    
    
    //Inicjalizacja UARTU
    void USARTInit(unsigned int ubrr)
    {
    UBRRH = (ubrr>>8);
    UBRRL = (unsigned char) ubrr;
    //Włączenie nadawania i odbioru oraz przerwania dla odbioru
    UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
    //Włączono dostęp do ubbh ustawiono 8 bitów danych parzystość oraz 2 bity stopu
    UCSRC=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)|(1<<UPM1)|(1<<USBS);
    sei();
    } 
    //Wysłanie pojedynczego znaku
    void nadajznak (char dana1)
    {
    while(!(UCSRA & (1<<UDRE)));
    UDR=dana1;
    }
    
    //Zliczanie liter w wyrazie i wysyłanie ich do funkcji nadajznak
    void nadajstring (char *dana)
    {
    int dlugosc,i=0;
    dlugosc = strlen(dana);
    for(i=0;i<dlugosc;i++)
    	{
    	nadajznak(dana[i]);
    	}
    }
    
    //Odbieranie znaku przez UART
    SIGNAL (SIG_UART_RECV)
    {
    nadajznak(UDR);
    }
    
    
    
    
    volatile unsigned int value=0x00;
    
    SIGNAL(SIG_ADC)                        
    {
      value = ADCL;
      PORTB = ~(value>>2);
    }
    
    int main(void)
    {
      char wyslij[10];
      USARTInit(UBRR);
      DDRB = 0xFF;
    
      ADCSR = (1<<ADEN)|(1<<ADIE)|(1<<ADFR)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
                                     
    	ADMUX=(0<<REFS1)|(0<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
      
      sei();
    
      while(1)
      {
    	itoa(value,wyslij,2);
        nadajstring(wyslij);
        nadajznak(32);
      }
    }
    


    Połączenia są następujące do wejścia PC0 jest podłączony opornik 10kohm i do niego potencjometr którym reguluje napięcie z zakresu od 0 do 5V.

    Proszę o pomoc co może być nie tak
  • REKLAMA
  • #2 7797859
    michalko12
    Specjalista - Mikrokontrolery
    A co z bitem ADSC?
    
    
    SIGNAL(SIG_ADC)                        
    {
      value = ADCL;
      PORTB = ~(value>>2);
      ADCSR |= (1<<ADSC);
    
    }


    Poprawka;
    Nie zauwazyłem że masz ustawiony ADC Free Running Select

    To jeszcze napisz co masz na pinie AREF
    bo masz ustawione REFS1=0 i REFS0=0
  • REKLAMA
  • #3 7798037
    tmf
    VIP Zasłużony dla elektroda
    Tak sie dzieje bo czytasz tylko ADCL. Zeby dokonac kolejnego przetworzenia musisz wczesniej odczytac ADCH. Albo po prostu caly ADC.
  • #4 7798119
    jaros85
    Poziom 20  
    Na pinie AREF jest kondensator 100nF połączony z masą.

    Trochę zmieniłem kod.
    W pętli while nic niema a w obsłudze przerwań jest taki kod:
    SIGNAL(SIG_ADC)                       
    {
      char wyslij[10];
      value = ADCL;
      PORTB = value;
      itoa(value,wyslij,2);
      nadajstring(wyslij);
      nadajznak(10);
      nadajznak(13);
    }


    Ale tak czy inaczej jest w terminalu osiem jedynek

    Preskaler jest oczywiście dobrze ustawiony ?
    (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0)
    8MHz/64=125kHz
  • REKLAMA
  • Pomocny post
    #5 7798190
    michalko12
    Specjalista - Mikrokontrolery
    jaros85 napisał:
    Na pinie AREF jest kondensator 100nF połączony z masą.

    Trochę zmieniłem kod.
    W pętli while nic niema a w obsłudze przerwań jest taki kod:
    SIGNAL(SIG_ADC)                       
    {
      char wyslij[10];
      value = ADCL;
      PORTB = value;
      itoa(value,wyslij,2);
      nadajstring(wyslij);
      nadajznak(10);
      nadajznak(13);
    }


    Ale tak czy inaczej jest w terminalu osiem jedynek

    Preskaler jest oczywiście dobrze ustawiony ?
    (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0)
    8MHz/64=125kHz


    No to masz jeszcze dwa błędy jeden to ten co Ci tmf napisał a drugi to to że nie masz napiecia referencyjnego

    Ustaw REFS0 =1
    i procedura przerwania z pierwszego przykładu powinna tak wygladać
    SIGNAL(SIG_ADC)                       
    {
      value = ADCL;
      ADCH;
      PORTB = ~(value>>2);
    }
  • REKLAMA
  • #6 7799304
    jaros85
    Poziom 20  
    Dzięki michalko12 rzeczywiście wystarczyło ustawić bit REFS0 =1

    Teraz już wszystko śmiga.

    Procedura obsługi przerwania wygląda następująco:
    SIGNAL(SIG_ADC)                       
    {
      char wyslij[10];
      value = ADC;
    
      PORTB = ~(value>>2); 
      itoa(value,wyslij,2);
      nadajstring(wyslij);
      nadajznak(10);
      nadajznak(13);
    }


    Mam jeszcze jedno pytanie mogę sczytać całą wartość rejestru ADC jak to jest wyżej ale jak chce sczytać oddzielnie ADCL i ADCH to jest problem.
    Próbowałem tak:

    value = ADCH;
    value=value<<8;
    value=ADCL;


    Ale niestety nie działa. Jak to można inaczej w jednej zmiennej zapisać ?
  • Pomocny post
    #7 7799596
    michalko12
    Specjalista - Mikrokontrolery
    Jest to spowodowane złą kolejnością odczytu. Odczytując ADCL jako drugi blokujesz dostęp do tego rejestru przetwornikowi.


    Cytat:
    The ADC generates a 10-bit result which is presented in the ADC Data Registers, ADCH and
    ADCL. By default, the result is presented right adjusted, but can optionally be presented left
    adjusted by setting the ADLAR bit in ADMUX.If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
    ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data
    Registers belongs to the same conversion. Once ADCL is read, ADC access to Data Registers
    is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is
    read, neither register is updated and the result from the conversion is lost. When ADCH is read,
    ADC access to the ADCH and ADCL Registers is re-enabled.



    To co napisałeś jest oczywiście bez sensu
    value = ADCH;
    value=value<<8;
    value=ADCL;


    rozumiem:
    value = ADCH;
    value=value<<8;     //value <<= 8;
    value |=ADCL;
    

    lub
    value = ADCH<<8 | ADCL; // jeśli value jest 16b


    ale jeśli chcesz odczytać rejestr i nigdzie go nie zapisywać wystarczy podać jego nazwę.

    value = ADCL;
    ADCH;
  • #8 7799670
    jaros85
    Poziom 20  
    Dzięki michalko12
REKLAMA