www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC/RS232 mit ATmega32


Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute!

Ich finde Interrupts/Timer usw sind um einiges anspruchsvoller, wie der 
ADC. Trotzdem bringe ich ihn nicht fertig..

Der ADC spuckt folgende Werte bei folgenden Zuständen aus:

400 bei GND
961 bei irgendein anderes höheres Potential
Wenn der Pin in der Luft hängt, werden beliebige Werte zwischen 400 und 
961 ausgegeben.

Wenn ich AREF auf Masse hänge, stimmt der Wert, nämlich 1023.

An der USART-Funktion liegt es sicher nicht, die funktioniert 
einwandfrei.
sprintf ist auch nicht daran Schuld.

Die äußere Beschaltung ist sehr wahrscheinlich auch richtig. Der 
ATmega32 steckt im STK500. Dieses liefert an AREF 4,9V,an VCC 4,9V und 
an AVCC 4,9V.

In meinem Fall liegt es entweder an irgendeinen "Logik-Fehler", den ich 
nicht finde und/oder die ADC-Funktion tut nicht was sie soll.



Wäre nett wenn ihr mal ein Auge auf den Code wirft =)
Danke schonmal!
/*Analog-Digital-Converter (ADC)
  ATmega32 @ 8 Mhz
  (c) Christoph Anlauf
  3AN

  
  ************************************************
  Spannungsrefernz über AREF
  Am PINA0 wird die Spannung gemessen
  ************************************************
*/

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

#ifndef F_CPU
#define F_CPU 8000000UL  //Taktfrequenz definieren
#endif

#include <util/delay.h> //Delay


void USART_Init(const uint16_t baud);
void USART_Transmit( uint8_t data );
void USART_Puts(char* string);

void ADC_Init(void);
unsigned int ADC_Conversion();

void main(void)
{   
  uint16_t i=0;
  
  uint8_t z;
    char buffer[40]; 
  //Lokale Variablen
  
  const uint16_t baud=51;
  //Der "Baud-Rate Parameter" wird durch die Frequenz und
  //der vorhergesehen Baud-Rate berechnet (siehe Datenblatt S.143)
  
  PORTA=0x00;     
  //PORTA als Eingang
  PORTD=0xF1;
  //RS232 Schnittstelle
  
  USART_Init(baud);
  ADC_Init();

  while(1)
  {
    for(z=0;z<100;z++)
      _delay_ms(5);

    sprintf(buffer,"Messung %i:%i",i+1,ADC_Conversion());
    
    USART_Puts(buffer);  
    i++;
  }
}


void USART_Init(const uint16_t baud)
{
  UCSRC |= (0<<UPM1) | (1<<UCSZ1) | (1<<UCSZ0);
  /*
  Asynchrone Operation UMSEL
  Gerade Parität UPM1
  1 Stoppbit USBS
  8-bit Wortlänge UCSZ1 u. UCSZ0
  */

  UBRRH = (unsigned char)(baud>>8);
  UBRRL = (unsigned char)baud;

  UCSRB = (1<<TXEN);
  //Transmitter aktivieren
}
void USART_Transmit( uint8_t data  )
{
  // Auf leeren Transmit-Buffer warten
  while ( !( UCSRA & (1<<UDRE)) );
  
  // Daten in den Buffer legen ->senden
  UDR = data;
}
void USART_Puts(char* string)
{
  while(*(string) != 0)
  {
    USART_Transmit(*(string));
    string++;
  }
}

void ADC_Init(void)
{
  ADCSRA = (1<<ADEN) | (1<<ADPS2);
  /*
  ADEN  ->ADC Enable
  ADPS2 ->Teilungsfaktor 16
  */
}
unsigned int ADC_Conversion()
{
  unsigned int result;

  ADCSRA |= (1<<ADSC);
  //Startet eine Konversation

  while(!(ADCSRA & 0x10));
  //Warten bis ADIF gesetzt ist (5. Bit)
  
  result = ADCL;
  result |= (ADCH <<8);
  //Ergebnis abspeichern
  

  ADCSRA |= (1<<ADIF);
  //Bit löschen, in dem es auf 1 gesetzt wird
  
  return result;
   
}

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>ADCSRA = (1<<ADEN) | (1<<ADPS2);

Du hast eine Referenzspannung an AREF?

MfG Spess

Autor: Philipp R. (relaxxo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst im ADMUX Register den Kanal auswählen (MUX3:0)

Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In meinem Fall muss ich bei dem ADMUX-Register garnichts machen. Alle 
Bits haben den "default" Wert 0. Ich will die Spannung am PINA0 messen, 
also MUX0:MUX4 sind 0.
Ich will das Ergbis rechtsbündig haben, also ist das ADLAR-Bit auch 0.
Spannungsreferenz ist bei AREF -> REFS1:REFS0 sind auch null.

Mfg

Autor: jfjbcxvb (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es gerade mal getestet, das anhaengende leicht veraenderte 
Beispiel funktioniert bei mir prima.

Gast

Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jfjbcxvb schrieb:
> Ich habe es gerade mal getestet, das anhaengende leicht veraenderte
> Beispiel funktioniert bei mir prima.
>
> Gast

Vielen Dank dass du dir die Mühe gemacht hast es auszuprobieren =)

Also hast du die ADC-Ergebnisse auch über das USART ausgelesen?

Bei mir klappt es immer noch nicht, trotz AVCC als Referenz.
Vll hilft es wenn du mir in deinem Fall die äußere Beschaltung erklärst. 
Womöglich ich habe ich da einen Fehler.

Nur eine kleine Anmerkung am Rande  =)
ADMUX = (1<<REFS0 | 0<<REFS1);  

Davon abgesehen dass die Bits standartmäßig auf 0 sind, hat es keinen 
Sinn einen Wert mit 0 zu "verODERn". Der Wert bleibt so wie er war.

Mfg
Christoph

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph A. schrieb:

> Nur eine kleine Anmerkung am Rande  =)
>
>
> ADMUX = (1<<REFS0 | 0<<REFS1);
> 
>
> Davon abgesehen dass die Bits standartmäßig auf 0 sind, hat es keinen
> Sinn einen Wert mit 0 zu "verODERn". Der Wert bleibt so wie er war.

Im Prinzip hast du recht.
Für die Maschine macht es keinen Unterschied.
Für jemanden, der das Programm liest kann es aber einen Unterschied 
machen. So sieht man auf Anhieb, dass die Absicht war, REFS0 auf 1 und 
REFS1 auf 0 zu setzen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph A. schrieb:

> Bei mir klappt es immer noch nicht, trotz AVCC als Referenz.
> Vll hilft es wenn du mir in deinem Fall die äußere Beschaltung erklärst.
> Womöglich ich habe ich da einen Fehler.

Eingangsspannung an ADC0
AVcc an Vcc
ARef über 100nF mit GND verbunden.

Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Christoph A. schrieb:
>
>> Bei mir klappt es immer noch nicht, trotz AVCC als Referenz.
>> Vll hilft es wenn du mir in deinem Fall die äußere Beschaltung erklärst.
>> Womöglich ich habe ich da einen Fehler.
>
> Eingangsspannung an ADC0
> AVcc an Vcc
> ARef über 100nF mit GND verbunden.

So sieht meine Konfiguration auch aus... bis auf den C auf Masse, aber 
an der Entkopplung wird es wohl nicht scheitern...

Vll habe ich ja meinen ATmega-ADC zerschossen. Werde mal ein anderes 
Exemplar probieren.

Viele Dank für eure Hilfe bis jetzt.

Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Christoph A. schrieb:
>
>> Nur eine kleine Anmerkung am Rande  =)
>>
>>
>> ADMUX = (1<<REFS0 | 0<<REFS1);
>> 
>>
>> Davon abgesehen dass die Bits standartmäßig auf 0 sind, hat es keinen
>> Sinn einen Wert mit 0 zu "verODERn". Der Wert bleibt so wie er war.
>
> Im Prinzip hast du recht.
> Für die Maschine macht es keinen Unterschied.
> Für jemanden, der das Programm liest kann es aber einen Unterschied
> machen. So sieht man auf Anhieb, dass die Absicht war, REFS0 auf 1 und
> REFS1 auf 0 zu setzen.

Stimmt, auf die Idee dass das Absicht gewesen sein könnte bin ich nicht 
gekommen^^
So wäre es von meiner Seite auch besser gewesen etwas mit dem 
ADMUX-Register hinzuschreiben, auch wenn alle Bits auf 0 sein sollen.

Autor: Volker Schulz (volkerschulz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph A. schrieb:
> Wenn ich AREF auf Masse hänge, stimmt der Wert, nämlich 1023.

Wenn Du AREF auf Masse haengst, dann stimmt so ziemlich jeder Wert (oder 
auch eben nicht). Division by zero. Undefiniert... ;)

Wenn Du A0 auf GND legst sollte der Wert 0 sein, wenn Du A0 auf Vref 
legst, sollte er 1023 sein (bei 10-Bit Aufloesung).

Volker

Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker Schulz schrieb:
> Christoph A. schrieb:
>> Wenn ich AREF auf Masse hänge, stimmt der Wert, nämlich 1023.
>
> Wenn Du AREF auf Masse haengst, dann stimmt so ziemlich jeder Wert (oder
> auch eben nicht). Division by zero. Undefiniert... ;)
>
> Wenn Du A0 auf GND legst sollte der Wert 0 sein, wenn Du A0 auf Vref
> legst, sollte er 1023 sein (bei 10-Bit Aufloesung).
>
> Volker

Schon klar =)

Autor: Christoph A. (shadowrunner93)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob ihr es glaubt oder nicht, der ATmega war Schuld.^^

Mit einem 2ten Examplar läuft der Code einwandfrei. Sogar extrem genau 
-> Bei einem Spannungsteiler von 1:1, ist der Wert 511. Also ziemlich 
genau die Hälfte..

Nja, aufjedenfall kann ich heute beruhigt schlafen, vielen Dank an euch 
=)

Mfg

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.