Forum: Mikrocontroller und Digitale Elektronik ADC Wert für ARM7 LPC2136 auslesen


von T. F. (n3ssaja)


Lesenswert?

Hallo zusammen,

Habe Probleme mit dem ADC auslesen auf einem LPC 2136.
Er hängt in der While Schleife und bekommt nicht das Flag, das die 
Umwandlung abgeschlossen ist. Den Burst Modus habe ich einmal an und 
einmal ausgeschaltet. Beides führte zu keinem Erfolg. Hat jemand 
Erfahrung wie ich den ADC initialisieren muss?
Hier mein Code:
1
short int get_adc(void)
2
{
3
  short int value;
4
  
5
  PCB_PINSEL1|=(1<<26);      // ADC 2: PIN P0.29 ausgewählt
6
  PCB_PINSEL1&=~(1<<27);  
7
  AD0_ADCR|=(1<<2);          // Kanal 2 vom ADC
8
  
9
  AD0_ADCR|=(1<<8);          // 60MHZ/4,5MHZ = 13MHZ eingestellt
10
  AD0_ADCR|=(1<<10);          // 60MHZ/4,5MHZ = 13MHZ eingestellt
11
  AD0_ADCR|=(1<<11);          // 60MHZ/4,5MHZ = 13MHZ eingestellt
12
  
13
  AD0_ADCR|(1<<16);          // ADC wird sofort gestartet
14
  AD0_ADCR|=(1<<21);          // ADC einschalten
15
  
16
  AD0_ADCR&=(0<<17);          // 10 Bit Auflösung  
17
  AD0_ADCR&=(0<<18);          // 10 Bit Auflösung  
18
  AD0_ADCR&=(0<<19);          // 10 Bit Auflösung  
19
  
20
  while((AD0_ADDR2&(1<<31))!=(1<<1)){};  // Warten bis Wandlung zu Ende
21
  
22
  value= (AD0_ADDR2>>16);        // ADC Ergebnis von Kanal 2
23
  
24
  return value;
25
}

von holger (Gast)


Lesenswert?

Da fehlt wohl ne 3 ;)

  while((AD0_ADDR2&(1<<31))!=(1<<31)){};  // Warten bis Wandlung zu Ende

von T. F. (n3ssaja)


Lesenswert?

Stimmt, die 31 ist korrekt an der Stelle. Leider führte das noch nicht 
zum Ziel. Welche Ursache kann es noch haben?
Wozu benötigt man eigentlich das Register
1
AD0_ADGDR
 ??
Auch wenn ich es aus dem Register lese klappts nicht:
1
 while ((AD0_ADGDR & 0x80000000) == 0);

von T. F. (n3ssaja)


Lesenswert?

Hat niemand eine Idee?

von T. F. (n3ssaja)


Lesenswert?

Ich probiere es nochmal, da ich immer noch keine Lösung habe.

Ich möchte am PIN 0.29 meines LPC2136 den AD Wandler benutzen (Kanal 2) 
und initialisiere die Register folgendermaßen:
1
void get_adc(void)
2
{
3
  uint32_t ADC_Val;
4
  PCB_PINSEL1|=(1<<26);        // ADC PIN P0.29 (AD0.2) ausgewählt
5
  PCB_PINSEL1 &=~(1<<27);  
6
  AD0_ADCR|=(1<<2);          // Kanal 2 vom ADC
7
  AD0_ADCR|=(1<<9)|(1<<11)|(1<<12);  // Clock etwa 4,3 MHZ
8
  AD0_ADCR|=(1<<21);          // ADC einschalten    
9
  AD0_ADCR|=(1<<16);          // ADC Burst Modus = Permanente Abfrage  
10
11
  ADC_Val = ((ADC_Val >>6) & 0x000003FF);   // extract result
12
  return(ADC_Val);  
13
}

Wo kann der fehler stecken? Am AD Eingang des µC lege ich eine Spannung 
zwischen 0 und 3V an. Als Wandelergebnis kommt ständig Null.

von Michael G. (let)


Lesenswert?

In dem zuletzt geposteten Code wird das Datenregister gar nicht 
ausgelesen. Bei der Initialisierung des control registers wird nur 
"dazugeodert". Sicher das da vorher eine 0 drin steht?
PCONP wird nicht beschrieben. Wird das woanders gemacht? Das wäre Bit 12
um den ADC zu bestromen.

Gerade beim ARM bitte compilierbaren Code posten. Ich habe diverse 
Boards hier (LPC21/23/24/11/13/17), kann also recht viel probieren und 
gezielt suchen. So kann ich nur raten.

von T. F. (n3ssaja)


Lesenswert?

Hallo Michael,
Danke das du mir deine Hilfe anbietest. Das ADC Register lese ich in der 
Main aus und verschicke es über UART an ein Terminal Programm. (Die UART 
Funktion klappt auch einwandfrei). Ist das Control Register nicht 
standardmäßig Null am Anfang?
PCONP habe ich nicht beschrieben, da ich das Register in keinem 
Bsp-Programm gesehen habe. Wozu dient das genau?
Hier ist nochmal mein Programm. Ziel ist es wie gesagt nur einen 
Spannungswert zwischen 0 - 3V über PIN 0.29 (AD0.2) einzulesen und über 
UART an mein Terminal Programm zu verschicken.
Ich habe meinen Code nochmal etwas abgeändert:

1
#include "lpc210x_gnuarm.h"
2
#include "config.h"
3
#include "uart.h"
4
5
/*Prototypen*/
6
void get_adc(void);
7
8
9
/*Main-Funktion*/
10
int main(void)
11
{   
12
  for(;;)  
13
  {
14
        get_adc(void);              
15
        uart0Putch(AD0_ADGDR>>8);  // Gibt das ADC Ergebnis über UART aus
16
  }
17
  return 0;
18
}
19
20
/*ADC*/
21
22
void get_adc(void)
23
{
24
  PCB_PINSEL1|=(1<<26);        // ADC PIN P0.29 (AD0.2) ausgewählt
25
  PCB_PINSEL1 &=~(1<<27);  
26
  AD0_ADCR|=(1<<2);          // Kanal 2 vom ADC
27
  AD0_ADCR|=(1<<9)|(1<<11)|(1<<12);  // Clock etwa 4,3 MHZ
28
  AD0_ADCR|=(1<<21);          // ADC einschalten    
29
  AD0_ADCR|=(1<<16);          // ADC Burst Modus = Permanente Abfrage
30
}

von Michael G. (let)


Lesenswert?

Compilieren kann ich den Code so immer noch nicht. Ich habe mir also ein 
vorhandenes Programm von mir geschnappt und einen ADC Test in main() 
eingebaut:
1
    stamp = currentTimer();
2
3
    PINSEL1 |= (1<<26);        // ADC PIN P0.29 (AD0.2) ausgewählt
4
    PINSEL1 &= ~(1<<27);
5
    AD0CR |= (1<<2);           // Kanal 2 vom ADC
6
    AD0CR |= (1<<9)|(1<<11)|(1<<12);  // Clock etwa 4,3 MHZ
7
    AD0CR |= (1<<21);          // ADC einschalten
8
    AD0CR |= (1<<16);          // ADC Burst Modus = Permanente Abfrage
9
10
    while (1) {
11
      if (elapsedTime(stamp) > 1000) {
12
          stamp = currentTimer();
13
          rprintf("ADC=%u\n", (AD0GDR>>6)&1023);
14
      }
15
    }

Die Register heißen bei mir etwas anders, ansonsten stammt die 
Initialisierung des ADCs aus deinem Programm.
In der while() Schleife lese ich nun im Sekundentakt den ADC aus. Und 
bei mir funktioniert das auch.

Du hast weiter oben eines der separaten Ergebnisregister des ADCs 
verwendet. Soweit ich weiß gibt es die nur bei der /01 Revision der 
LPC213x.

Mit PCONP kann man einzelne Peripherieeinheiten ein- oder ausschalten. 
Der ADC ist beim 213x aber standardmäßig aktiviert. Beim 23xx muß man 
den manuell einschalten.

Vielleicht solltest du doch noch etwas compilierbares posten. Wenn es 
aber nicht für den arm-gcc ist, kann ich nicht viel damit anfangen.

von T. F. (n3ssaja)


Lesenswert?

Hallo Michael,

Danke für deine Antwort. Ich habe jetzt endlich die Zeit gefunden mich 
nochmals mit dem ADC beim ARM LPC2136 µController zu beschäftigen. Dein 
Programm war sehr hilfreich, aber ich habe ein weiteres Problem.
Ich lege an dem ADC Eingang nun eine Spannung von 0V-3V.
Wenn ich mir nun die ersten 8 Bitstellen des Ergebnisregisters mittels 
eines Hyperterminals ansehe:
1
rprintf("ADC=%u\n", (AD0GDR>>6);

sind bei mir die obersten drei Bit immer standardmäig Eins, sprich das 
Ergebnis sieht wie folgt aus: 1110 0000.  Nur die unteren Bitstellen 
ändern sich. Wo kann das drann liegen? EIgentlich sollte vom ADC doch 
bei Anlegen von 0V auch ein Ergebnis mit Null herauskommen.

@Michael: Zudem versteh ich nicht ganz, warum du bei der Ausgabe das 
Ergebnis nochmals mit 1023 verundest?
1
 rprintf("ADC=%u\n", (AD0GDR>>6)&1023);

von Robert T. (robertteufel)


Lesenswert?

T. F. schrieb:
> Hallo Michael,
>
> Danke für deine Antwort. Ich habe jetzt endlich die Zeit gefunden mich
> nochmals mit dem ADC beim ARM LPC2136 µController zu beschäftigen. Dein
> Programm war sehr hilfreich, aber ich habe ein weiteres Problem.
> Ich lege an dem ADC Eingang nun eine Spannung von 0V-3V.
> Wenn ich mir nun die ersten 8 Bitstellen des Ergebnisregisters mittels
> eines Hyperterminals ansehe:
>
>
1
> rprintf("ADC=%u\n", (AD0GDR>>6);
2
>
>
> sind bei mir die obersten drei Bit immer standardmäig Eins, sprich das
> Ergebnis sieht wie folgt aus: 1110 0000.  Nur die unteren Bitstellen
> ändern sich. Wo kann das drann liegen? EIgentlich sollte vom ADC doch
> bei Anlegen von 0V auch ein Ergebnis mit Null herauskommen.
>
> @Michael: Zudem versteh ich nicht ganz, warum du bei der Ausgabe das
> Ergebnis nochmals mit 1023 verundest?
>
1
>  rprintf("ADC=%u\n", (AD0GDR>>6)&1023);
2
>
Das User Manual und speziell das Kapitel ueber ADC ist Dein Freund und 
beantwortet beide Fragen.
Die oberen bits haben Zusatzinformationen, eine verundung mit 1023 
blended diese aus und laesst nur die "Nettodaten" ueber.

Ist wirklich nicht so schwierig zu finden!

Robert

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.