mikrocontroller.net

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


Autor: T. F. (n3ssaja)
Datum:

Bewertung
0 lesenswert
nicht 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:
short int get_adc(void)
{
  short int value;
  
  PCB_PINSEL1|=(1<<26);      // ADC 2: PIN P0.29 ausgewählt
  PCB_PINSEL1&=~(1<<27);  
  AD0_ADCR|=(1<<2);          // Kanal 2 vom ADC
  
  AD0_ADCR|=(1<<8);          // 60MHZ/4,5MHZ = 13MHZ eingestellt
  AD0_ADCR|=(1<<10);          // 60MHZ/4,5MHZ = 13MHZ eingestellt
  AD0_ADCR|=(1<<11);          // 60MHZ/4,5MHZ = 13MHZ eingestellt
  
  AD0_ADCR|(1<<16);          // ADC wird sofort gestartet
  AD0_ADCR|=(1<<21);          // ADC einschalten
  
  AD0_ADCR&=(0<<17);          // 10 Bit Auflösung  
  AD0_ADCR&=(0<<18);          // 10 Bit Auflösung  
  AD0_ADCR&=(0<<19);          // 10 Bit Auflösung  
  
  while((AD0_ADDR2&(1<<31))!=(1<<1)){};  // Warten bis Wandlung zu Ende
  
  value= (AD0_ADDR2>>16);        // ADC Ergebnis von Kanal 2
  
  return value;
}


Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da fehlt wohl ne 3 ;)

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

Autor: T. F. (n3ssaja)
Datum:

Bewertung
0 lesenswert
nicht 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
AD0_ADGDR
 ??
Auch wenn ich es aus dem Register lese klappts nicht:
 while ((AD0_ADGDR & 0x80000000) == 0); 

Autor: T. F. (n3ssaja)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat niemand eine Idee?

Autor: T. F. (n3ssaja)
Datum:

Bewertung
0 lesenswert
nicht 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:
void get_adc(void)
{
  uint32_t ADC_Val;
  PCB_PINSEL1|=(1<<26);        // ADC PIN P0.29 (AD0.2) ausgewählt
  PCB_PINSEL1 &=~(1<<27);  
  AD0_ADCR|=(1<<2);          // Kanal 2 vom ADC
  AD0_ADCR|=(1<<9)|(1<<11)|(1<<12);  // Clock etwa 4,3 MHZ
  AD0_ADCR|=(1<<21);          // ADC einschalten    
  AD0_ADCR|=(1<<16);          // ADC Burst Modus = Permanente Abfrage  

  ADC_Val = ((ADC_Val >>6) & 0x000003FF);   // extract result
  return(ADC_Val);  
}

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.

Autor: Michael G. (let)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: T. F. (n3ssaja)
Datum:

Bewertung
0 lesenswert
nicht 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:

#include "lpc210x_gnuarm.h"
#include "config.h"
#include "uart.h"

/*Prototypen*/
void get_adc(void);


/*Main-Funktion*/
int main(void)
{   
  for(;;)  
  {
        get_adc(void);              
        uart0Putch(AD0_ADGDR>>8);  // Gibt das ADC Ergebnis über UART aus
  }
  return 0;
}

/*ADC*/

void get_adc(void)
{
  PCB_PINSEL1|=(1<<26);        // ADC PIN P0.29 (AD0.2) ausgewählt
  PCB_PINSEL1 &=~(1<<27);  
  AD0_ADCR|=(1<<2);          // Kanal 2 vom ADC
  AD0_ADCR|=(1<<9)|(1<<11)|(1<<12);  // Clock etwa 4,3 MHZ
  AD0_ADCR|=(1<<21);          // ADC einschalten    
  AD0_ADCR|=(1<<16);          // ADC Burst Modus = Permanente Abfrage
}

Autor: Michael G. (let)
Datum:

Bewertung
0 lesenswert
nicht 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:
    stamp = currentTimer();

    PINSEL1 |= (1<<26);        // ADC PIN P0.29 (AD0.2) ausgewählt
    PINSEL1 &= ~(1<<27);
    AD0CR |= (1<<2);           // Kanal 2 vom ADC
    AD0CR |= (1<<9)|(1<<11)|(1<<12);  // Clock etwa 4,3 MHZ
    AD0CR |= (1<<21);          // ADC einschalten
    AD0CR |= (1<<16);          // ADC Burst Modus = Permanente Abfrage

    while (1) {
      if (elapsedTime(stamp) > 1000) {
          stamp = currentTimer();
          rprintf("ADC=%u\n", (AD0GDR>>6)&1023);
      }
    }

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.

Autor: T. F. (n3ssaja)
Datum:

Bewertung
0 lesenswert
nicht 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:
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?
 rprintf("ADC=%u\n", (AD0GDR>>6)&1023);

Autor: Robert Teufel (robertteufel)
Datum:

Bewertung
0 lesenswert
nicht 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:
>
>
> 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?
>
>  rprintf("ADC=%u\n", (AD0GDR>>6)&1023);
> 
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.