Forum: Mikrocontroller und Digitale Elektronik ADC und Ausgabe auf LCD


von Toni (Gast)


Lesenswert?

Guten Abend zusammen,

trotz Lesens aller möglichen Seiten gelingt es mir nicht,
das beiliegende Prg. so zu gestalten, wie ich's gern hätte.
Hardware STK200, ATmega88, LCD an PortD.
Die Hardware funktioniert mit Bascom wie gewünscht.
LCD Library v. Peter Fleury (PORT geändert). Auch das zugehörige
Testprogramm funktioniert einwandfrei.
Problem: lcd_puts(buffer); gibt nicht die erwarteten 0....1023 aus
sondern eine eher zufällige zweistellige Zahl.
Wo kann der Fehler liegen, im ADC Wandlerteil oder bei der Umwandlung 
mit utoa?
Danke für ev. Hinweise

Toni


#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <avr/io.h>
#include <inttypes.h>
#include "lcd.h"

uint16_t readADC(uint8_t channel)
 {
  uint8_t i;
  uint8_t ADC_temp;
  uint8_t ADCH_temp;
  uint16_t result = 0;


  // Den ADC aktivieren und Teilungsfaktor auf 64 stellen
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

  // Kanal des Multiplexers waehlen
  // Avcc als Referenzspannung verwenden
  ADMUX = channel  | (0<<REFS1) | (1<<REFS0);

  // Den ADC initialisieren und einen sog. Dummyreadout machen
  ADCSRA |= (1<<ADSC);
  while(ADCSRA & (1<<ADSC));

  // Jetzt 3x die analoge Spannung am Kanal "channel" auslesen
  // und dann Durchschnittswert ausrechnen.
  for(i=0; i<3; i++) {
    // Eine Wandlung
    ADCSRA |= (1<<ADSC);
    // Auf Ergebnis warten...
    while(ADCSRA & (1<<ADSC));

    //Ergebnisregister auslesen
        ADC_temp = ADCL;
        ADCH_temp = ADCH;
    ADC_temp += (ADCH_temp << 8);

    result += ADC_temp;
  }


  // ADC wieder deaktivieren
  ADCSRA &= ~(1<<ADEN);

  result /= 3;

  return result;
}

int main(void)
 {

  char buffer[7];
  //Auslesen der analogen Spannung an ADC0,
  //In result steht das Ergebnis.
  uint16_t result = readADC(0);


  //initialize display, cursor blinkt
    lcd_init(LCD_DISP_ON_CURSOR_BLINK);

  //clear display and home cursor
    lcd_clrscr();

  //integer in ASCII umwandeln
  utoa( result , buffer, 10);

  lcd_puts("Ergebnis:\n");
  lcd_puts(buffer);

  return 0
  }

von Dieter F. (Gast)


Lesenswert?

Toni schrieb:
> ADC_temp += (ADCH_temp << 8);

ADC_temp ist 8 Bit deklariert und Du versuchst einen 16 Bit Wert zu 
addieren.


btw - Du könntest auch die Formatierung einsetzen - dann ist Dein Code 
etwas lesbarer:
1
C-Code

von Toni (Gast)


Lesenswert?

Servus Dieter,

kaum macht man es richtig, schon funktioniert es!

Vielen Dank und liebe Grüße

Toni

von Karl H. (kbuchegg)


Lesenswert?

In C brauchst du diesen 'komplizierten' Teil
1
ADC_temp = ADCL; ADCH_temp = ADCH;
2
ADC_temp += (ADCH_temp << 8);
3
result += ADC_temp;

überhaupt nicht. Du verwendest einfach das Pseudo-Register 'ADC' und der 
Compiler dröselt das alles richtig auf und setzt die Werte für dich 
zusammen
1
  for(i=0; i<3; i++) {
2
    // Eine Wandlung
3
    ADCSRA |= (1<<ADSC);
4
    // Auf Ergebnis warten...
5
    while(ADCSRA & (1<<ADSC));
6
    //Ergebnisregister auslesen
7
    result += ADC;
8
  }

Siehe auch den ADC Abschnitt im AVR-GCC-Tutorial

von Toni (Gast)


Lesenswert?

Das hatte ich auch versucht, aber irgendwie trotzdem
die falsch deklarierte Variable im Spiel gehabt!

Nochmals Danke für die Hilfe

Toni

von Karl H. (kbuchegg)


Lesenswert?

Toni schrieb:
> Das hatte ich auch versucht, aber irgendwie trotzdem
> die falsch deklarierte Variable im Spiel gehabt!

:-)
Wie kann eine Variable, die gar nicht gebraucht wird und daher im Code 
gar nicht mehr existiert, falsch deklariert sein?
:-)

(genau das ist der springende Punkt. Da geht es nicht nur darum, dass 
der Code kürzer wird. Es geht auch darum, dass durch die Vereinfachung 
auch Fehlerquellen wegfallen)

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.