Forum: Mikrocontroller und Digitale Elektronik Win AVR adc ansprechen


von Fuzzy F. (fuzzy)


Lesenswert?

Hallo Leute,

ich wollte mal fragen ob mir jemand einen Quellcode schicken kann den 
ich in WinAVR in der Programmiersprache c/c++ einsetzen kann um den 
ad-Wandler anzusprechen bzw die werte auszulesen. Habe schon einiges 
probiert aber kenne den genauen Quellcode nicht.
Für jede Antwort danke ich im vorraus!

mfg
Fuzzy

von Danny (Gast)


Lesenswert?

Schau mal im AVR-Tutorial nach, da steht alles drin

von guru (Gast)


Lesenswert?

bzw. Codesammlung

von Fuzzy F. (fuzzy)


Angehängte Dateien:

Lesenswert?

Habe ich schon klappt aber nicht. Kriege keine Werte aus den ADC heraus!

Hier mein Quellcode als Anhang!!

von Dirk (Gast)


Lesenswert?


von johnny.m (Gast)


Lesenswert?

Nimm für Deine Variable "x" besser einen unsigned int. Da kommen eh nur 
positive Werte rein. Bei signed-Variablen kann bei Schiebe-Operationen 
alles Mögliche passieren, je nachdem, was der Compiler draus macht.

von irgendein Rahul (Gast)


Lesenswert?

>Nimm für Deine Variable "x" besser einen unsigned int.

Genau.

Und dann machst du nicht

>  x = ADCL;
>  x += (ADCH<<8);

sondern

x = ADC;

von Michael R. (rubi)


Lesenswert?

Hallo

x = ADC;
Ist immer gut!
Wenn man die Register in der falschen Reihenfolge ausliest kommt nämlich 
nur
Müll raus. Hat mich einmal einen halben Tag gekostet dem auf den Grund 
zu gehen. Habe ein Tutorial verwendet und da stand es verkehrt rum 
drinnen.
Erst nach Blick ins Datenblatt ist mir dies dann aufgefallen,...

Daher wer Probleme vermeiden will liest am besten gleich das ganze 16 
Bit Register aus und überläst GCC die Details.

LG
Michael

von Branko Golubovic (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Ich verwende ADC Funktionen auch mit Differential-Eingänge  und 
deswegen ist Ruckgabewert signed int.
Sogar ist Zeitverzögerung von 125µS(Datenblatt,Changing Channel or 
Reference Selection)bei umschalten von Singel-Ended auf
Differential-Input mitberücksichtigt.
Damit sind auch solche Konstruktionen problemlos möglich:
…
x=read_adc(2);  //ADC 2, Single Ended
y=read_adc(9);  //Diff-Input ADC0-ADC1; Gain 10

Grüß Branko

von Branko Golubovic (Gast)


Angehängte Dateien:

Lesenswert?

und Headerfile

von irgendein Rahul (Gast)


Lesenswert?

@Branko: Das ist der unübersichtlichste (dafür aber universellste) Code, 
den ich seit langem gesehen habe. (ob der einem Anfänger hilft, 
bezweifle ich aber sehr).

von Fuzzy F. (fuzzy)


Lesenswert?

Hallo Branko

ich habe gerade ausprobiert dein Programm zu benutzen. Aber es klappt 
leider nicht Er gibt folgende Fehlermeldungen aus:

adc.c: In function `read_adc':
adc.c:188: error: `B_ADC_VREF_TYPE' undeclared (first use in this 
function)
adc.c:188: error: (Each undeclared identifier is reported only once
adc.c:188: error: for each function it appears in.)
adc.c: In function `adc_init':
adc.c:251: error: `B_ADC_VREF_TYPE' undeclared (first use in this 
function)
adc.c:254: error: `B_ADC_PRESCALER' undeclared (first use in this 
function)

Die Header-Datei habe ich in den Ordner in dem das C-Programm steht 
eingefügt. Ist das überhaupt richtig?
Des weiteren lese ich über den AD-Wandler einen Potiwert ein (nur zur 
Info).
Wie erkenne ich die Pins und Ports in dem Programm?
vielleicht benutze ich einfach die falschen Pins?

Kann ich das Programm überhaupt für meinem atmega16 benutzen?

Fragen über fragen!!!

Für hilfreiche Tipps danke ich im vorraus!!

mfg
Fuzzy

von Michael R. (rubi)


Lesenswert?

MANN FUZZY

Wieso gehtst Du nicht zu diesem Link und kopierst den Beispiel Code?
Oder noch besser vergleichst den Code mit deinem ?

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Die Library von Branko würde ich ers mal verwenden wenn ich die 
Basisfunktionalität verstanden habe.

ansonsten würde ich nur mal zum test folgendes im c file einfügen
(ohne mir den code angesehen zu haben).

bool B_ADC_PRESCALER=0;
bool B_ADC_VREF_TYPE=0;

LG
Michael

von Branko Golubovic (Gast)


Lesenswert?

@Fuzzy

Hast du Headerfile auch ins Hauptprogramm inkludiert?
#include<avr/io.h>
#include "adc.h"

int main (void)
{
 adc_init(); // ADC initialisieren
....

und in Makefile auch eingefügt?
# MCU name
MCU = atmega16

# Target file name (without extension).
TARGET = ADC_AVR

# List C source files here. (C dependencies are automatically 
generated.)
SRC = $(TARGET).c  adc.c

Bei ATmega16 sind ADC Eingänge(DIP40):
PIN  ADCIN
40   ADC0
39   ADC1
38   ADC2
..
33   ADC7
32   AREF
32   GND
31   AVCC  //Mit VCC verbinden!

und benützt wird einfach mit:
x=read_adc(0) // Spannung von PIN40(ADC0)
y=read_adc(1) // Spannung von PIN39(ADC1)
..
z=read_adc(7) // Spannung von PIN33(ADC7)
d=read_adc(16) // Spannungsdifferenz zwischen ADC0 und ADC1

von Fuzzy F. (fuzzy)


Lesenswert?

Hab jetzt schon einiges probiert, und was ist das Resultat?!??
Der ATmega16 macht nichts mehr und sein Nachfolger der ATmega32 auch 
nicht!!!
Hier der Quelltext. Da ist doch alles richtig??
Versteht´s nicht???

#include <avr/io.h>
#include <inttypes.h>


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


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

  // Kanal des Multiplexers waehlen
  ADMUX = channel;
  // Interne Referenzspannung verwenden (also 2,56 V)
  ADMUX |= (1<<REFS1) | (1<<REFS0);

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

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

  PORTB=result;
  return result;
}

int main(void) {
for(;;){
  uint16_t result = readADC(0);  //Auslesen der analogen Spannungen an 
Pin 0,
          // also ADC0. In result steht das Ergebnis.
  return 0;
  }
}


Hab da noch ne Frage muss ich ADCSRA &= ~(1<<ADEN); überhaupt 
verwenden???

Hoffe, es kann mir jemand helfen!!!!

mfg Fuzzy

von Michael R. (rubi)


Lesenswert?

Hallo

Das return 0 würde ich aus der for Schleife nehmen,
sonst mißt Du nur ein mal.
Sonst konnte ich auf die Schnelle keinen Fehler finden.

Das ist super schlechter Stil:

 while(ADCSRA & (1<<ADSC));
         result = ADCW;



Bitte gewöhn Dir das erst gar nicht an.
Besser so:

 while(ADCSRA & (1<<ADSC))
 {
    ;
 }
result = ADCW;

Besonders die Einrückung der Zeile  result = ADCW;
ist Fatal, da glaubt man schnell die gehört zu er while Schleife.
So eine Geschichte kann Dir Stunden des Debuggens kosten.

LG
Michael

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.