Forum: Mikrocontroller und Digitale Elektronik ADC/RS232 mit ATmega32


von Christoph A. (shadowrunner93)


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!
1
/*Analog-Digital-Converter (ADC)
2
  ATmega32 @ 8 Mhz
3
  (c) Christoph Anlauf
4
  3AN
5
6
  
7
  ************************************************
8
  Spannungsrefernz über AREF
9
  Am PINA0 wird die Spannung gemessen
10
  ************************************************
11
*/
12
13
#include <avr/io.h>
14
#include <stdio.h>
15
16
#ifndef F_CPU
17
#define F_CPU 8000000UL  //Taktfrequenz definieren
18
#endif
19
20
#include <util/delay.h> //Delay
21
22
23
void USART_Init(const uint16_t baud);
24
void USART_Transmit( uint8_t data );
25
void USART_Puts(char* string);
26
27
void ADC_Init(void);
28
unsigned int ADC_Conversion();
29
30
void main(void)
31
{   
32
  uint16_t i=0;
33
  
34
  uint8_t z;
35
    char buffer[40]; 
36
  //Lokale Variablen
37
  
38
  const uint16_t baud=51;
39
  //Der "Baud-Rate Parameter" wird durch die Frequenz und
40
  //der vorhergesehen Baud-Rate berechnet (siehe Datenblatt S.143)
41
  
42
  PORTA=0x00;     
43
  //PORTA als Eingang
44
  PORTD=0xF1;
45
  //RS232 Schnittstelle
46
  
47
  USART_Init(baud);
48
  ADC_Init();
49
50
  while(1)
51
  {
52
    for(z=0;z<100;z++)
53
      _delay_ms(5);
54
55
    sprintf(buffer,"Messung %i:%i",i+1,ADC_Conversion());
56
    
57
    USART_Puts(buffer);  
58
    i++;
59
  }
60
}
61
62
63
void USART_Init(const uint16_t baud)
64
{
65
  UCSRC |= (0<<UPM1) | (1<<UCSZ1) | (1<<UCSZ0);
66
  /*
67
  Asynchrone Operation UMSEL
68
  Gerade Parität UPM1
69
  1 Stoppbit USBS
70
  8-bit Wortlänge UCSZ1 u. UCSZ0
71
  */
72
73
  UBRRH = (unsigned char)(baud>>8);
74
  UBRRL = (unsigned char)baud;
75
76
  UCSRB = (1<<TXEN);
77
  //Transmitter aktivieren
78
}
79
void USART_Transmit( uint8_t data  )
80
{
81
  // Auf leeren Transmit-Buffer warten
82
  while ( !( UCSRA & (1<<UDRE)) );
83
  
84
  // Daten in den Buffer legen ->senden
85
  UDR = data;
86
}
87
void USART_Puts(char* string)
88
{
89
  while(*(string) != 0)
90
  {
91
    USART_Transmit(*(string));
92
    string++;
93
  }
94
}
95
96
void ADC_Init(void)
97
{
98
  ADCSRA = (1<<ADEN) | (1<<ADPS2);
99
  /*
100
  ADEN  ->ADC Enable
101
  ADPS2 ->Teilungsfaktor 16
102
  */
103
}
104
unsigned int ADC_Conversion()
105
{
106
  unsigned int result;
107
108
  ADCSRA |= (1<<ADSC);
109
  //Startet eine Konversation
110
111
  while(!(ADCSRA & 0x10));
112
  //Warten bis ADIF gesetzt ist (5. Bit)
113
  
114
  result = ADCL;
115
  result |= (ADCH <<8);
116
  //Ergebnis abspeichern
117
  
118
119
  ADCSRA |= (1<<ADIF);
120
  //Bit löschen, in dem es auf 1 gesetzt wird
121
  
122
  return result;
123
   
124
}

von spess53 (Gast)


Lesenswert?

Hi

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

Du hast eine Referenzspannung an AREF?

MfG Spess

von Philipp R. (relaxxo)


Lesenswert?

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

von Christoph A. (shadowrunner93)


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

von jfjbcxvb (Gast)


Angehängte Dateien:

Lesenswert?

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

Gast

von Christoph A. (shadowrunner93)


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  =)
1
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

von Karl H. (kbuchegg)


Lesenswert?

Christoph A. schrieb:

> Nur eine kleine Anmerkung am Rande  =)
>
>
1
> ADMUX = (1<<REFS0 | 0<<REFS1);
2
>
>
> 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.

von Karl H. (kbuchegg)


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.

von Christoph A. (shadowrunner93)


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.

von Christoph A. (shadowrunner93)


Lesenswert?

Karl heinz Buchegger schrieb:
> Christoph A. schrieb:
>
>> Nur eine kleine Anmerkung am Rande  =)
>>
>>
1
>> ADMUX = (1<<REFS0 | 0<<REFS1);
2
>>
>>
>> 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.

von Volker S. (volkerschulz)


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

von Christoph A. (shadowrunner93)


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 =)

von Christoph A. (shadowrunner93)


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

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.