Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[AT91SAM7S64][c/Rowley Crossworks] ADC - separacja kanałów

14 Oct 2009 17:53 1364 6
  • Level 12  
    Witam.
    Mam następujący problem. Uruchamiam 6 kanałów ADC. 4 poza kontrolerem PIO i 2 przez PIO. do tych 2 ostatnich podpięte są dwa potencjometry suwakowe, każdy po 100k (do ścieżki oporowej +3.3V i GND, a do suwaka ADC) Problem w tym, że zauważalny jest znaczy wpływ suwaka 1 na suwak 2 i na odwrót. Czyli jeśli ustawimy 1 suwak to ruszając drugim zmienia się także wynik z suwaka 1, a tak być nie powinno. Dodam jeszcze, że na kanałach spoza PIO takiej sytuacji nie ma, a wszystkie kanały są inicjowane tak samo.

    Kod inicjacji:
    Code:

    void ADC_init(){          //Inicjacja kontrolera ADC
      ADC_CR = 1;             //Załączenie
      delay(1000);
      PIOA_PER = (1<<PIOA_PDR_P17_BIT) | (1<<PIOA_PDR_P18_BIT);   //Ustawienie Kontrolera IO
      PIOA_ODR = (1<<PIOA_PDR_P17_BIT) | (1<<PIOA_PDR_P18_BIT);   //Jako wejścia
      PIOA_PUDR = (1<<PIOA_PDR_P17_BIT) | (1<<PIOA_PDR_P18_BIT);  //Wyłączenie podciągania
      ADC_MR=(ADC_MR_LOWRES) | (2<<8) | (35<<ADC_MR_SHTIM_BIT);
      ADC_CHER = ADC_CHER_CH4;    //JOY1X       Uruchomienie kanałów
      ADC_CHER = ADC_CHER_CH5;    //JOY1Y
      ADC_CHER = ADC_CHER_CH6;    //JOY2X
      ADC_CHER = ADC_CHER_CH7;    //JOY2Y
      ADC_CHER = ADC_CHER_CH0;    //Suwak 1
      ADC_CHER = ADC_CHER_CH1;    //Suwak 2
      PMC_PCER = PMC_PCER_ADC;                //Załączenie zegara do ADC
    }


    Kod pobierania danych:

    Code:

    void GET_ADC(){               //Pobranie danych z odpowiednich kanałów ADC
       char z=0;          //zmienna pomocnicza
       ADC_CR = 2;        //Start ADC
       int i = (PIOA_PDSR & (1<<JOY2_C))>>JOY2_C;   //Sprawdzenie punktów centralnych Joysticków
      if (i == 1){
       while((ADC_SR & ADC_SR_EOC4)>>ADC_SR_EOC4_BIT != 1){z++;if(z>200){break;}}
       while((ADC_SR & ADC_SR_EOC5)>>ADC_SR_EOC5_BIT != 1){z++;if(z>200){break;}}
       JOY2Y = ADC_CDR4 + JOY2Y_Z;
       JOY2X = ADC_CDR5 + JOY2X_Z;}
      else{
       while((ADC_SR & ADC_SR_EOC4)>>ADC_SR_EOC4_BIT != 1){z++;if(z>200){break;}}
       while((ADC_SR & ADC_SR_EOC5)>>ADC_SR_EOC5_BIT != 1){z++;if(z>200){break;}}
       JOY2Y = ADC_CDR4;
       JOY2X = ADC_CDR5;
        JOY2Y_Z=0x80 - JOY2Y;
        JOY2X_Z=0x80 - JOY2X;
        JOY2X = 0x80;
        JOY2Y = 0x80;}
      if (((PIOA_PDSR & (1<<JOY1_C))>>JOY1_C) == 1){
       while((ADC_SR & ADC_SR_EOC6)>>ADC_SR_EOC6_BIT != 1){z++;if(z>200){break;}}
       while((ADC_SR & ADC_SR_EOC7)>>ADC_SR_EOC7_BIT != 1){z++;if(z>200){break;}}
       JOY1Y = ADC_CDR6 + JOY1Y_Z;
       JOY1X = ADC_CDR7 + JOY1X_Z;}
      else{
       while((ADC_SR & ADC_SR_EOC6)>>ADC_SR_EOC6_BIT != 1){z++;if(z>200){break;}}
       while((ADC_SR & ADC_SR_EOC7)>>ADC_SR_EOC7_BIT != 1){z++;if(z>200){break;}}
       JOY1Y = ADC_CDR6;
       JOY1X = ADC_CDR7;
        JOY1Y_Z=0x80 - JOY1Y;
        JOY1X_Z=0x80 - JOY1X;
        JOY1X = 0x80;
        JOY1Y = 0x80;}
       while((ADC_SR & ADC_SR_EOC0)>>ADC_SR_EOC0_BIT != 1){z++;if(z>200){break;}}
       z=0;
       while((ADC_SR & ADC_SR_EOC1)>>ADC_SR_EOC1_BIT != 1){z++;if(z>200){break;}}
       Suwak1 = ADC_CDR0;
       if (Suwak1 == 0x00){Suwak1=0x01;}
       Suwak2 = ADC_CDR1;
       if (Suwak2 == 0x00){Suwak2=0x01;}}


    Pozdrawiam i bardzo proszę o pomoc w odseparowaniu tych kanałów
    [Szkolenie 22.06.2021, g.9.30] Zabezpieczenia Internetu Rzeczy (IoT) programowe i sprzętowe. Zarejestruj się za darmo
  • User removed account  
  • Level 12  
    Problem w tym, że mierzyłem napięcie i nawet nie drgnie, nie ma żadnych szpilek, sinusów, dziwnych odchyłek itp. po prostu kreska na oscyloskopie i ani drgnie, zasilanie i Vref to samo. Nic sie nie zmienia między jednym a drugim kanałem. a w programie w zmiennych są odchyłki rzędu 10% - 15%. Procka zmieniłem i nic nie dało:/
  • Level 43  
    A nie powinieneś przed każda pętlą While zerować zmiennej "z"?
    Rozumiem że to jest taki TimeOut.
    Nie zerujesz jej i pod koniec procedury (czyli tam gdzie jest konwersja z CH0 i CH1) "z" może mieć dużą wartość i może wartość z ADC jest pobierana przed zakończeniem konwersji. Pod koniec konwersji wytwarzane są najmłodsze bity. Pobranie wyniku zbyt wcześnie może spowodować że pobierzesz starsze bity z właściwego kanału a młodsze (jeszcze nie nadpisane przez nową konwersję) ze starszego. Powinien być jakiś bufor w ADC i zapis powinien być dokonywany w całości, ale nie wiem jak to jest zrobione w tym procesorze. Może właśnie bez bufora i zbyt wczesny odczyt da taki objaw.
  • MCUs specialist
    Jest oczekiwanie na konwersję:

    while((ADC_SR & ADC_SR_EOC1)>>ADC_SR_EOC1_BIT != 1)

    a zmienna z jest wyzerowana po raz pierwszy na samym początku:

    char z=0;

    Problemem może być to, że jeśli używasz jakiejś optymalizacji, to kompilator na 99% wykasuje zmienną z. Do jej deklaracji dołóż słówko "volatile".

    4\/3!!
  • User removed account