-         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: Fragen zum A/D wandeln

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    05.05.2005
    Alter
    48
    Beiträge
    58

    Fragen zum A/D wandeln

    Anzeige

    So ich habe mich nun von der Bitverarbeitung zur Analogverarbeitun gekämpft und habe da einige Fragen.


    Was ist bei der Dimensionierung zu beachten? Mal abgesehen davon, dass die Referenzspannung nicht überschritten werden darf?

    Beschaltet werden muss bei Interner Referenzspannung nur AVCC (VCC) und AGND ohne Bauteile.

    Bei Externer Referenzspannung AGND AVCC (VCC) und AREF ohne Bauteile.
    AREF muss zwischen VREF (2,56V) und VCC liegen.

    Habe gelesen man kann nur einen der vier ADC´s nutzen?? Ist das so richtig (ATMega

    Da ich mich mit C noch nicht beschäftigt habe würde ich auch gerne noch den Code besprechen...


    Code:
     #include <avr/io.h>
    
    /* Analog/Digital Wandler initialisieren */
    void adc_init(void);
    
    unsigned int buffer;
    
    int main(void)
    {
    
    	/* A/D - Wandler initialisieren */
    	adc_init();
    
    	while (1)
    	{
    		/* Wandlung starten */
    		ADCSRA |= (1<<ADSC); // Setzt das ADSC Bit im ADCSRA Register Also eine einfache Wandlung steht an.
    		
    		/* Warten bis die AD-Wandlung abgeschloßen ist */
    		while ( !(ADCSRA & (1<<ADIF)) ) //Das ADCSRA wird mit dem ADIF Bit und verknüpft 
    		//Rückgabewert 1 Wenn die Wandlung abgeschlossen ist. Duch die Negation wir die While Schleife möglich.
    			;
    
    		/* AD-Wert auslesen */
    		buffer = (ADCH<<8) | ADCL; // Das ist mir überhaupt noch nicht klar???
    
    	}
    
    }
    
    /* Analog/Digital Wandler initialisieren */
    void adc_init(void)
    {
    
    	/* externe Referenzspannung und AD-Wandlerkanal 0 ( ADC0 ) auswählen */
    	ADMUX = 0;
    
    	/* AD-Wandler einschalten und Prescaler = 64 einstellen ( enstpricht 115 khz Wandlertakt ) */
    	ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); // Is klar ADEN triggert eine Messung... aber wie genau 
    	//wirkt sich der Wandlertakt aus?? Je langsamer je genauer???
    
    	/* Spezialfunktionen ausschalten */
    	SFIOR = 0; // Warum müssen alle Pull Up Widerstände ausgeschaltet werden?
    	
    }
    Das eigentliche Prg ist aus dem Netz gesaugt. Ausprobiert habe ich es aber noch nicht. Code den ich so nicht verstehe bringt mir leider nichts.

    Gruß Olli
    .... und ich lächelte und es kam Schlimmer!


    -= Rechtschreibfehler werden mit 0,50 Cent/Stk. berechnet. Bitte nach günstigen Großabnehmertarifen fragen! =-

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.145

    Re: Fragen zum A/D wandeln

    Zitat Zitat von Murphywareinoptimist
    Was ist bei der Dimensionierung zu beachten? Mal abgesehen davon, dass die Referenzspannung nicht überschritten werden darf?
    Außer, dass Du auch keine negativen Eingangsspannungen haben darfst nichts weiter.
    Beschaltet werden muss bei Interner Referenzspannung nur AVCC (VCC) und AGND ohne Bauteile.

    Bei Externer Referenzspannung AGND AVCC (VCC) und AREF ohne Bauteile.
    Um das ganze unempfindlicher gegen Rauschen zu machen, kannst Du an AVCC und AREF jeweils noch Kondensatoren gegen GND schalten. (Ich habe da immer je einen 10µF Elko und einen 100nF Keramikkondensator dran). Ist aber nicht zwingend notwendig.

    AREF muss zwischen VREF (2,56V) und VCC liegen.
    AREF muss zwischen 2,0V und VCC liegen.

    Habe gelesen man kann nur einen der vier ADC´s nutzen?? Ist das so richtig (ATMega
    Der Mega8 hat 8 ADC-Eingangspins (beim DIP-Gehäuse nur 6) aber de fakto nur einen ADC. Über einen Multiplexer kann man einstellen, welcher Kanal eingelesen werden soll. Das heißt, man kann zwar mehrere verschiedene Signale erfassen, aber nicht genau zum selben Zeitpunkt.


    Das Code-Erklären muss ich auf morgen früh verschieben, oder jemand anderes macht's. Muss jetzt weg.

    Gruß,
    askazo

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.145
    Ok, kommen wir zum Code.
    Ich fange mal mit der adc_init() an:
    Code:
    ADMUX = 0; // Hast Du ja völlig richtig erkannt.
    
    ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //Die Bits ADEN, ADPS2 ind ADPS1 o, ADCSRA-Register werden gesetzt.
    // ADEN ist nicht zum Triggern der Messung da, sondern schaltet den ADC erst mal generell ein.
    // ADPS1 und 2 setzten den Wandlertakt für den Free-Running-Mode. Die Eingestellte Frequenz sagt also aus, in welchen Zeitabständen der ADC seinen Eingang abfragt und sein Ergebnis aktualisiert. Je schneller der Takt, desto genauer wird Dein Signal abgetastet. Allerdings schlägt das dann auch auf die Performance des µP, da er logischerweise weniger Zeit für andere Sachen hat. In diesem Codebeispiel ist der Free-Running-Mode allerdings ausgeschaltet, die eingestellte Frequenz hat also keine Auswirkung. Jede Messung wird manuell gestartet.
    
    SFIOR = 0; //Ist meiner Ansicht nach überflüssig. Die PullUps und auch die anderen Einstellungen im SFIOR haben keine Auswirkung auf den ADC.
    So, nun zum Hauptprogramm.
    Code:
    adc_init(); //Ist ja schon klar.
    
    ADCSRA |= (1<<ADSC); //Startet eine einfache Wandlung.
    
    while (!(ADCSRA & (1<<ADIF)) ) //Fragt das ADIF Bit ab. Solange ADIF nicht 1 ist,
    ; //wird die leere while-Schleife ausgeführt, also gewartet.
    
    buffer = (ADCH<<8) | ADCL; //hier wird das Wandlungsergebnis in die Variable buffer geschrieben. Da das Ergebnis aus 2 8-Bit Registern besteht (HighByte ADCH und LowByte ADCL) wird zunächst das HighByte um 8 Stellen nach links geschoben und danach mit dem LowByte verknüpft. So steht auf den Bits 0-7 der Inhalt von ADCL und auf 8-15 der Inhalt von ADCH. Somit hat man das ursprünglich zweigeteilte Ergebnis zu einer verwertbaren Zahl zusammengefügt.
    So, das war's schon. Ich hoffe, ich konnte Dir weiterhelfen.

    askazo

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Code:
    buffer = (ADCH<<8) | ADCL;
    Das ist ein Kunstfehler. Die Reihenfolge, in der das ausgewertet wird, ist
    AFAIK nicht spezifiziert in C, so daß ADCL vor ADCH gelesen werden kann. Der Zugriff muss aber in einer bestimmten Reihenfolge getan werden. Das erreicht man, indem man auf ADC als 16-Bit-Register zugreift, und nicht, indem man es von Hand in zwei 8-Bit-Register zerbröselt.

    Klarere, einfacher zu lesen und auf jeden Fall korrekt ist also
    Code:
    buffer = ADC;
    . Schneller und codesparender ist's auch noch...
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.145
    Naja, man zerbröselt es ja nicht, es sind ja von Natur aus eigentlich 2 Register...
    Aber Du hast schon absolut Recht, hatte gar nicht mehr dran gedacht, dass man da eine Reihenfolge einhalten muss. Und mit dem Word-Zugriff ist's natürlich auch wesentlich einfacher und verständlicher.

    askazo

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    08.03.2006
    Beiträge
    22
    Das ist nen wichtiger Punkt, mit den Registern einlesen.
    Hab ich gerade bei mir festgestellt. Mit buffer = ADC läuft das Programm einwandfrei. Anders nicht!
    Hatte es auch zuerst anders ausprobiert. (Hatte den Befehl aus nem Tutorial)

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    08.08.2004
    Ort
    Zwolle
    Alter
    61
    Beiträge
    531
    Hallo,


    Laut Datenblatt sollte mann zuerst ADCL auslesen und danach ADCH.

    Denn nachdem ADCH ausgelesen ist wird die ADCH/ADCL register kombination freigegeben um von die AD-Wandler wieder actualisiert zu werden.

    Wenn mann zuerst ADCH ausliest, und damit die Register freigibt, konnte es sein dass inzwischen die AD-Wandler neue Daten in ADCL gespeichert hat!
    Wenn mann dann ADCL ausliest ist dass die Wert van einem andere Messung!

    Ich hab mich die compilierten code mahl angeschaut (GCC.EXE).

    --------------------

    die Code:

    buffer = (ADCH<<8 ) | ADCL;

    wird umgesetzt nach:

    in r24,37-0x20
    in r24,36-0x20

    --------------------


    die Code:

    buffer = ADC;

    wird umgesetzt nach:

    in r24,36-0x20
    in r25,(36)+1-0x20

    --------------------

    Die '36' ist ADCL und die '37' is ADCH.


    Da kann mann sehen dass die code '(ADCH<<8 ) | ADCL' ein potentialen Fehler
    verursachen kann denn ADCH wird zuerst gelesen und damit die Register freigegeben.


    Die code 'buffer = ADC' liest zuerst ADCL und danach ADCH.

    ==============================
    Ich benutzte immer:
    buffer = ADCL;
    buffer|=(ADCH<<8 );

    Ich hatte die code 'buffer = ADC' noch niemahls benutzt,

    Danke, schon wieder etwas gelernt!
    ==============================


    Gruss

    Henk

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Warum sich mühen, wenn avr-gcc die Arbeit macht...?

    Gleiches gilt auch für andere 16-Bit-Register wie TCNT1, etc, sowohl für's Schreiben als auch für's Lesen.
    Disclaimer: none. Sue me.

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    05.05.2005
    Alter
    48
    Beiträge
    58
    Hallo!

    Danke für die Antworten. Wie es so ist haben die Antworten noch mehr Fragen aufgeworfen.
    Hier erst einmal das modifiziert Programm:

    Code:
     #include <avr/io.h>
    
    
    void adc_init(void);
    
    unsigned int buffer;
    
    int main(void)
    {
    
    	adc_init();
    
    	while (1)
    	{
    	ADCSRA |= (1<<ADSC);
    		while ( !(ADCSRA & (1<<ADIF)) )
    	;buffer = ADC;
    
    	}
    
    }
    
    void adc_init(void)
    {
    
    	ADMUX = 0;
    	ADCSRA = (1<<ADEN);
    
    }
    ADCSRA |= (1<<ADSC);

    Hätte es hier nicht auch ein einfaches oder getan? Wenn nicht warum nicht?


    ADMUX = 0;
    Hier wird der Kanal bestimmt der gewandelt werden soll... wer lesen kann ist klar im Vorteil. Habe die DIL Variante ... habe nur PC4 & 5 ignoriert.

    Wenn ich die interne Referenzspannung nutzen möchte gebe ich hier also folgendes an?

    ADMUX = C0;

    Das Ergebnis ist ja 10 Bit breit. Also im HSB stehen nur zwei Bit mit relevanten Daten?

    Wenn ich ein 8 Bit genaues Ergebnis haben möchte (was ja die weitere Verarbeitung und Ausgabe sehr vereinfach) muss ich was tun?

    O-Ton:

    If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to
    read ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content
    of the Data Registers belongs to the same conversion. Once ADCL is read, ADC access
    to Data Registers is blocked. This means that if ADCL has been read, and a conversion
    completes before ADCH is read, neither register is updated and the result from the conversion
    is lost. When ADCH is read, ADC access to the ADCH and ADCL Registers is
    re-enabled.

    Wie kann das aber sein? Im ADCH steht doch nur ein Teil der auf 10 Bit bezogenen Messung oder??


    Ich habe nur die ATMEL AppNote, Assembler Befehlscode und Beschreibung Atmega8.
    Ich habe auch ein Buch über C. Was mir noch fehlt ist was über die speziellen Sachen für avr-gcc. Gibt es da was? Ich benutze zum Programmieren nur Programmers Notepad2 und gehe über eine normale ISP-Schnittstelle auf ein Experimentierboard.(Steckboard)


    Gruß Olli
    .... und ich lächelte und es kam Schlimmer!


    -= Rechtschreibfehler werden mit 0,50 Cent/Stk. berechnet. Bitte nach günstigen Großabnehmertarifen fragen! =-

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.145
    Zitat Zitat von Murphywareinoptimist
    ADCSRA |= (1<<ADSC);

    Hätte es hier nicht auch ein einfaches oder getan? Wenn nicht warum nicht?
    Es ist ja ein 'einfaches' oder. Der Befehl ist eine Kurzform von
    ADCSRA = ADCSRA | (1<<ADCS);

    Wenn Du ein Bit setzen willst, ohne den Rest des Registers zu verändern, ist das die einfachste Möglichkeit.
    ADMUX = 0;
    Hier wird der Kanal bestimmt der gewandelt werden soll... wer lesen kann ist klar im Vorteil. Habe die DIL Variante ... habe nur PC4 & 5 ignoriert.

    Wenn ich die interne Referenzspannung nutzen möchte gebe ich hier also folgendes an?

    ADMUX = C0;
    Richtig!
    Das Ergebnis ist ja 10 Bit breit. Also im HSB stehen nur zwei Bit mit relevanten Daten?
    In der Standart-Konfguration (ADLAR=0) auch richtig!
    Wenn ich ein 8 Bit genaues Ergebnis haben möchte (was ja die weitere Verarbeitung und Ausgabe sehr vereinfach) muss ich was tun?

    O-Ton:

    If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to
    read ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content
    of the Data Registers belongs to the same conversion. Once ADCL is read, ADC access
    to Data Registers is blocked. This means that if ADCL has been read, and a conversion
    completes before ADCH is read, neither register is updated and the result from the conversion
    is lost. When ADCH is read, ADC access to the ADCH and ADCL Registers is
    re-enabled.

    Wie kann das aber sein? Im ADCH steht doch nur ein Teil der auf 10 Bit bezogenen Messung oder??
    Wenn Du das ADLAR-Bit im ADMUX-Register setzt, wird das Ergebnis Links ausgerichtet. Das heißt, das im ADCH-Register die oberen 8 Bit des Ergebnisses stehen. Die unteren 2 Bit stehen dann im ADCL-Register auf Bit 6 und 7.
    Wenn Du also nur 8 Bit benutzen möchtest, ist es am sinnvollsten, die Linksausrichtung einzuschalten und nur ADCH auszuwerten.

    Ich habe nur die ATMEL AppNote, Assembler Befehlscode und Beschreibung Atmega8.
    Ich habe auch ein Buch über C. Was mir noch fehlt ist was über die speziellen Sachen für avr-gcc. Gibt es da was? Ich benutze zum Programmieren nur Programmers Notepad2 und gehe über eine normale ISP-Schnittstelle auf ein Experimentierboard.(Steckboard)
    Im WinAVR ist ein Manual als pdf enthalten, allerdings auf englisch.
    Ich glaube, es gibt auch eine deutsche Übersetzung. Wo man die bekommt, kann ich Dir aus dem Stehgreif nicht sagen.

    Gruß,
    askazo

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •