ATMEGA8 - 2 analoge Signale einlesen (2-Ch AD-Wandler)

Gast #2476457
Lesenswert?

Hallo zusammen,
ich möchte gerne zwei analoge Signale mit dem ATMEGA8 einlesen. Bei den 
einzelnen Kanälen klappt dies auch, aber eben leider nicht bei beiden 
gleichzeitig. Was gibt es da alles besonderes zu beachten. Anbei noch 
mein C-Code. Achja, die beiden Funktionen werden im Hauptprogramm 
nacheinander aufgerufen.
Vielen Dank.
Gruß Thomas

unsigned char U_poti_Eingang()
{
  DDRC &= 0b11111110;
  unsigned char U_poti=0;
  ADMUX |= 0b01100000;    // Einlesen des Kanals 0 usw.
  ADCSRA|= 0b11000000;
  while (ADCSRA &0b01100000)  // Überprüfung: Abschluss der Wandlung
  {}
  U_poti=ADCH;
  return U_poti;        // Wertebereich: 0-255
}


unsigned char U_LED_Eingang()
{
  DDRC &= 0b11111101;
  unsigned char U_LED=0;
  ADMUX |= 0b01100001;    // Einlesen des Kanals 1 usw.
  ADCSRA|= 0b11000000;
  while (ADCSRA &0b01100000)  // Überprüfung: Abschluss der Wandlung
  {}
  U_LED=ADCH;
  return U_LED;        // Wertebereich: 0-255
}
Gast #2476482
Lesenswert?

Krapao schrieb:
>>   ADMUX |= 0b01100000;    // Einlesen des Kanals 0 usw.
>
> Hier habe ich beim Lesen kapituliert.

Ja, sorry für die schlechte Beschreibung. Ja die letzten vier Bits 
beziehen sich auf den Anschluss zum Poti. Also MUX0-MUX3. Und da alle 
vier Bits Null sind ist es ja der Anschluß ADC0 des µC. War für mich ne 
Bezeichnung wo ich das Kabel anzuschließen habe.
Gast #2476692
Lesenswert?

Durch die absoluten Bitmasken ist es sau schwer direkt zu sehen, ob dein 
Code richtig ist.

Mit den symbolischen Bitnamen aus den Includefiles ist es wesentlich 
einfacher zu sehen, ob der Code dem bekannten Code z.B. im 
AVR-GCC-Tutorial entspricht.

Deinen Code kann man nur mit intensivem Lesen des Atmega8 Datenblatts 
überprüfen.

Bei der Stelle

>  while (ADCSRA &0b01100000)  // Überprüfung: Abschluss der Wandlung
>  {}

ist was faul. Ich erwarte da eine Bitmaske mit einem gesetzten Bit, 
nicht zwei wie in deinem Code.

Ich würde auch die bewährte Auftrennung in die einmalige 
ADC-Initialisierung und ggf. regelmäßige ADC-Kanalumschaltung/Auslesen 
beibehalten, so wie sie im Tutorial verwendet wird.
#2476718
Lesenswert?

Deine SChreibweise wurde ja schon zur Genüge angesprochen.

Zu noch einem Fehler (neben der Abfrage ob er fertig ist)
1
  ADMUX |= 0b01100001;    // Einlesen des Kanals 1 usw.

und wie erwartest du, dass das ganz rechte 1 Bit (für Kanal 1) jemals 
wieder gelöscht wird?
1
  ADMUX |= 0b01100000;    // Einlesen des Kanals 0 usw.
kann das nicht leisten. Mit einem Oder (|) kann man BIts nur auf 1 
zwingen, nicht jedoch auf 0 zurücksetzen.

Schau dir die ADC Routinen im AVR-GCC-Tutorial an, die 
berücksichtigen das. Und wenn du schon dabei bist könntest du auch ganz 
einfach die Routinen von dort verwenden. Die sind sauber geschrieben und 
berücksichtigen deine Kanalumschaltung. Im Prinzip weißt du ja wie's 
geht, daher spricht nichts dagegen, wenn du fix&fertige Funktionen dafür 
einsetzt, die dann auch noch die letzten Feinheiten berücksichtigt 
haben. Kein Grund das Rad neu zu erfinden und in 3 Anweisungen 4 
vermeidbare Fehler zu machen.
Gast #2476816
Lesenswert?

Hubert G. schrieb:
> Wenn du ADMUX|=(1<<REFS0)|(1<<ADLAR); schreibst dann muss sich der Leser
> nicht das Datenblatt heraussuchen um zu verstehen was du meinst.
> Warum aktivierst du das immer wieder, es genügt doch einmal im main.

Ah okay, wird diese Art der Schreibweise "(1<<REFS0)|(1<<ADLAR)" als 
"symbolische Bitnamen" benannt? Hab davor gedacht die absolute 
Schreibweise ist eindeutiger. Ich wollte damit nur ausschließen, dass 
mir durch das Kompilieren oder durch andere Programme die Register 
verändert werden.

Danke für die vielen Hinweise. Werde mich dann jetzt erst nochmals mit 
der Kanalumschaltung ausführlich befassen.
Gast #3604839
Lesenswert?

Hallo Freunde,

ich möchte gerne mit einem Atmega16 zwei verschiedene Analogsignale an 
den Pins PA0 und PA1 abtasten.
Leider bin ich noch Anfänger und muss noch viel herum probieren und 
lesen dazu. Aber jetzt komme ich wirklich nicht mehr weiter.
Vielleicht kann mir ja mal einer einen Tip geben und sagen, was an dem 
unten aufgeführten Code nicht richtig ist. Wenn ich nur über den ADC PA0 
einlese funktioniert es, was ich dann über das PWM TImer1 auch sauber 
angezeigt bekomme. Möchte ich jedoch beide Pins abtasten, reagiert er 
wieder nur auf PA0 und lässt PA1 scheinbar außer acht.

Danke im Voraus.
Jens






#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 4000000UL
#define ADATE 5
#endif
#include <util/delay.h>



int main(void)
{

uint16_t wert1;
uint16_t wert2;


  DDRB |= (1 << DDB3);      // Setup PB0 as output

  while(1)
  {

//erstes Abtasten

  ADMUX |= (1<<REFS0);
  ADCSRA |= (1<<ADEN)|(1<<ADATE)|(1<<ADPS2)|(1<<ADSC);

  while(!(ADCSRA&(1<<ADSC))); // Wait until a conversion is finished

  wert1 = ADC;

//zweites Abtasten

  ADMUX |= (1<<REFS1);
        ADCSRA |= (1<<ADEN)|(1<<ADATE)|(1<<ADPS2)|(1<<ADSC);

  while(!(ADCSRA&(1<<ADSC))); // Wait until a conversion is finished

  wert2 = ADC;

//über PWM Timer1 ausgeben


  DDRD |= (1 << DDB4);
  DDRD |= (1 << DDB5);


  TCCR1A = (1<<WGM10)|(1<<WGM11)|(1<<COM1A1)|(1<<COM1B1);

  TCCR1B = (1<<WGM12)|(1<<CS11)|(1<<CS10);

  OCR1A = wert1;
  OCR1B = wert2;


  }

  return 0;

}
Gast #3604863
Lesenswert?

Hi

>//erstes Abtasten
>  ADMUX |= (1<<REFS0);

>//erstes Abtasten
>  ADMUX |= (1<<REFS0);

Damit schaltest du die Referenzspannungsquelle aber nicht die Kanäle um. 
Außerdem konfiguriert man den ADC nicht ständig in der while-Schleife. 
das macht man einmal davor. In der Schleife brauchst du nur die 
ADMUX-Bits und ADSC anfassen.

MfG spess
#3604883
Lesenswert?

1
  ADMUX |= 0b01100000;  
2
...
3
  ADMUX |= 0b01100001;

Das mit dem "|=" ist keine gute Idee! Damit wird irgendwann mal der 
Kanal auf 1 gestellt und "|= 0" macht das nicht rückgängig! Du mußt 
entweder Deinen Code auf "=" umstellen oder vor dem "|=" mit "&= ..." 
die Kanalbits löschen.
Gast #3604907
Lesenswert?

Max fragte:
>Was war an diesem Hienweis nicht verständlich?

Wo ist Deine Hilfe? Ich sehe sie nicht.
Bist Du einer der Typen, die den TO, wenn er wirklich einen neuen 
Beitrag
verfasst hätte, auch nur auf die Suchfunktion hinweisen und nicht helfen
wollen oder können?

Ist es Deiner Meinung nach sinnvoll, 10 gleichartige Threads mit nicht
Einer Lösung des Problemes zu haben?

Das mußte mal raus....
Gast #3605944
Lesenswert?

@ Max H. (hartl192)
was lässt du dich als registrierter User hier von so einem Blockwart 
denunzieren? setz den auf die Ignoliste und gut ist,
oder suche seine Beiträge hier, der kann nur Rummosern - fachl. 
Tiefflieger
Gast #3605957
Lesenswert?

Jens schrieb:
> Sorry, ich hatte das verteilt. Ja ich werd dazu was komplett neues
> erstellen.

Dann schreib doch gleich den Link - wer soll sich da sonst noch zurecht 
finden.

Oder ein Mod erbarmt sich und löscht hier den ganzen, an den alten 
Thread rangeklatschten Mist.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren