AVR GCC ADC Werte ergeben keinen Sinn

OP #3452164
Lesenswert?

Sehr geehrtes Forum,
ich habe eine Frage bezüglich des ADCs.

Ich habe eine Vorrichtung mit einem ATMEGA 88 PA, mit RS232 Verbindung 
zum PC und folgendem Code in C:
1
// 19.12.2013 - 17:19 Uhr, Tests zur Kommunikation per RS232 in C
2

3
#include <avr/io.h>          
4
#include <util/delay.h>
5

6
#define BAUD  4800UL
7
#define F_CPU 1000000UL
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
9

10
//  Initialisierung des UART
11
void uart_init(void)
12
{
13
  // Baudrate einstellen
14
  UBRR0H = UBRR_VAL >> 8;
15
  UBRR0L = UBRR_VAL & 0xFF;
16
 
17
  // Verwendungsart einstellen
18
  UCSR0B  = (1<<TXEN0);  // UART TX einschalten
19
  UCSR0C  = (1<<UCSZ01)|(1<<UCSZ00);  // Asynchron 8N1 
20
  UCSR0B |= (1<<RXEN0);  // UART RX einschalten
21
}
22
//  Initialisierung des ADWC
23
void adc_init(void) 
24
{
25
  // die Versorgungsspannung AVcc als Refernz wählen:
26
  //ADMUX = (1<<REFS0);    
27
  // oder interne Referenzspannung als Referenz für den ADC wählen:
28
   ADMUX = (1<<REFS1) | (1<<REFS0);
29
 
30
  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
31
  // schon auf 0, also single conversion
32
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
33
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
34
 
35
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
36
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
37
 
38
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
39
  while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
40
  }
41
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
42
     Wandlung nicht übernommen. */
43
  (void) ADCW;
44
}
45

46
/* USART - Senden eines einzelnen Zeichens */
47
int uart_putc(unsigned char c)
48
{
49
    while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
50
    {
51
    }  
52

53
    UDR0 = c;                      /* sende Zeichen */
54
    return 0;
55
}
56
/* Zeichen empfangen */
57
uint8_t uart_getc(void)
58
{
59
    while (!(UCSR0A & (1<<RXC0)))   // warten bis Zeichen verfuegbar
60
        ;
61
    return UDR0;                   // Zeichen aus UDR an Aufrufer zurueckgeben
62
}
63

64
/* ADC Einzelmessung */
65
uint16_t adc_read( uint8_t channel )
66
{
67
  // Kanal waehlen, ohne andere Bits zu beeinflußen
68
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
69
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
70
  
71
  while (ADCSRA & (1<<ADSC) )     // auf Abschluss der Konvertierung warten
72
  { 
73
  }
74

75
  return ADCW;                    // ADC auslesen und zurückgeben
76
}
77

78
void welcome(void)
79
{
80
  uart_putc('T');
81
  uart_putc('E');
82
  uart_putc('S');
83
  uart_putc('T');
84
  uart_putc(' ');
85
  uart_putc('D');
86
  uart_putc('E');
87
  uart_putc('V');
88
  uart_putc('I');
89
  uart_putc('C');
90
  uart_putc('E');
91
  uart_putc(' ');
92
  uart_putc('R');
93
  uart_putc('E');
94
  uart_putc('A');
95
  uart_putc('D');
96
  uart_putc('Y');
97
}
98

99
int main (void) 
100
{    
101
  uart_init();
102
  adc_init();
103

104
  welcome();
105

106
  while(1)
107
  {
108
    uart_getc();
109

110
    uint16_t adw = adc_read(0);
111
    uint8_t lo_value = adw;
112
    uint8_t hi_value = (adw >> 8);
113

114
    uart_putc('>');
115
      uart_putc(lo_value);
116
      uart_putc(hi_value); 
117
  }              
118
  return 0;                 
119
}

Problem ist, die Ausgabe ist immer konstant, egal was ich an ADC Channel 
0 auch anschließe, z.B. GND oder VCC oder gar nichts.

Woran könnte es liegen, am Code, oder an der Hardware?
#3452187
Lesenswert?

K. R. schrieb:

Mach dir doch erst mal ein paar vernünftige Hilfsfunktionen. So was ....
1
  uart_putc('T');
2
  uart_putc('E');
3
  uart_putc('S');
4
  uart_putc('T');
5
  uart_putc(' ');
6
  uart_putc('D');
7
  uart_putc('E');
8
  uart_putc('V');
9
  uart_putc('I');
10
  uart_putc('C');
11
  uart_putc('E');
12
  uart_putc(' ');
13
  uart_putc('R');
14
  uart_putc('E');
15
  uart_putc('A');
16
  uart_putc('D');
17
  uart_putc('Y');

ist doch Unsinn.
1
void uart_puts( const char* str )
2
{
3
  while( *str )
4
    uart_putc( *str++ );
5
}

damit kannst du dann sofort erst mal schreiben
1
void welcome(void)
2
{
3
  uart_puts( "TEST DEVICE READY\r\n" );
4
}

Gut.
Weiters ist diese Funktion sofort nützlich, weil sich daraus sofort eine 
Zahlenausgabe zusammensetzen lässt
1
void uart_puti( uint16_t value )
2
{
3
  char buffer[8];
4
  utoa( value, buffer, 10 );
5
  uart_puts( buffer );
6
}

welche gleich mal hier ...
1
int main()
2
{
3
....
4

5
  while(1)
6
  {
7
    uart_getc();
8

9
    uint16_t adw = adc_read(0);
10
    uart_puti( adw );
11
    uart_puts( "\r\n" );
12
  }
zum Einsatz kommt.

Alternativ hätte man azum Testen auch so vorgehen können
1
...
2
int main()
3
{
4
  char buffer[20];
5
...
6
  while(1)
7
  {
8
    uart_getc();
9

10
    uint16_t adw = adc_read(0);
11
    sprintf( buffer, "ADC Wert: %u\r\n", adw );
12
    uart_prints( buffer );
13
  }
14
}

Probier beide mal aus. Mal sehen ob dein Problem nicht einfach nur darin 
besteht, dass du die Ausgabe in deinem Terminal fehlinterpretierst.
#3452198
Lesenswert?

Wenn du die Vcc an den ADC anschliessen willst, dann solltest du hier
1
void adc_init(void) 
2
{
3
  // die Versorgungsspannung AVcc als Refernz wählen:
4
  //ADMUX = (1<<REFS0);    
5
  // oder interne Referenzspannung als Referenz für den ADC wählen:
6
   ADMUX = (1<<REFS1) | (1<<REFS0);
7
...
dann aber auch die korrekte Referenzspannung dafür auswählen.

Wie ist der AREF Pin deines µC eigentlich beschaltet?
OP #3452204
Lesenswert?

Danke erstmal für eure Tipps.

Ich kriege eigentlich nur den einen konstanten Wert rein: 1023

Wenn ich AREF mit VCC (5V) verbinde (obwohl ich eine Interne Spannung 
verwende, hatte ich zumindest gedacht), dann habe ich ne leichte 
Varianz:
> wenn ich dann an Channel 0 z.B. 5V anschließe bin ich bei ca 430-390.
> Wenn ich Channel 0 an 0V (GND) anschließe, bin ich bei Werten ca. bei 350-360.

Ich hätte da schon etwas mehr an Variabilität erwartet. Sollten die 
Werte nicht bei AREF = 5V  zwischen 5V und 0V an Channel 0 nicht 
zwischen 0 und 2^14 liegen?

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