ADC - interne Refspannung

OP #2425169
Lesenswert?

Liebe Alle,

ich versuche mich derzeit am ADC. Den Schaltungsaufbau bei Nutzung der 
internen Referenzspannung des Atmega32 habe ich aus dem Tutorial (ARef 
über Kondensator an Masse, AGND über Kondensator an Masse, AVCC über 
Kondensator an Masse und 47 Ohm Widerstand an VCC).

Nun habe ich über einen Poti auf den Pin A0 unterschiedliche Spannungen 
geschickt und lasse mir den Rückgabewert des ADC über den UART ausgeben: 
leider derzeit konstant der 1023-ger Wert, der eigentlich für die 
Referenzspannung stehen sollte.

Ich hänge den Code an und wäre dankbar für einen Tipp was da im argen 
liegt.

Vielen Dank
Hans
1
#define F_CPU 8000000UL   
2

3
#include <stdlib.h>
4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
#include <util/delay.h>
7
#include <string.h>
8
#include <stdio.h>
9

10
#define UART_BAUDRATE  4800
11
#define UART_SETTING  ((F_CPU/16L/UART_BAUDRATE)-1)
12

13

14
volatile uint16_t sekunden, msekunden;
15

16

17

18
ISR(TIMER2_COMP_vect)
19
{
20
  static int count, count_sek;
21
  
22
  count_sek++;
23

24
  if(count_sek == 10)
25
  {
26
    msekunden++;
27
    count_sek = 0;
28

29
    if(msekunden == 1000)
30
    {
31
      sekunden++;
32
      msekunden = 0;
33
    }
34
  }
35
}
36

37
void init_time()
38
{
39
  TIMSK|=(1<<OCIE2);
40
  TCCR2 |= (1<<WGM21) | (1<<CS21);  
41
  OCR2 = F_CPU/8/10000;      
42
}
43

44

45

46
/* ADC initialisieren */
47
void ADC_Init(void) {
48
 
49
  uint16_t result;
50
 
51

52
  ADMUX = (1<<REFS1) | (1<<REFS0);      // interne Referenzspannung nutzen
53

54
  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
55
  // schon auf 0, also single conversion
56
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
57
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
58
 
59
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
60
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
61
 
62
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
63
 
64
  while (ADCSRA & (1<<ADSC) ) {}        // auf Abschluss der Konvertierung warten
65
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
66
     Wandlung nicht übernommen. */
67
  result = ADCW;
68
}
69
 
70
/* ADC Einzelmessung */
71
uint16_t ADC_Read( uint8_t channel )
72
{
73
  // Kanal waehlen, ohne andere Bits zu beeinflußen
74
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
75
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
76
  while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
77
  return ADCW;                    // ADC auslesen und zurückgeben
78
}
79
 
80
/* ADC Mehrfachmessung mit Mittelwertbbildung */
81
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t average )
82
{
83
  uint32_t result = 0;
84
 
85
  for (uint8_t i = 0; i < average; ++i )
86
    result += ADC_Read( channel );
87
 
88
  return (uint16_t)( result / average );
89
}
90

91
void setup_uart()
92
{
93
  UBRRH = (char) (UART_SETTING >> 8);
94
  UBRRL = (char) (UART_SETTING);
95
  UCSRB = (1<<RXEN) | (1<<TXEN);
96

97
  UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
98
}
99

100
void uart_putchar(char c)
101
{
102
  // Warten bis Buffer bereit ...
103
  while (!(UCSRA & (1 << UDRE)))
104
    ;
105

106
  // Senden...
107
  UDR = c;
108
}
109

110
void uart_putstring(char *str)
111
{
112
  unsigned char i;
113

114
  for (i=0;i<255;i++) 
115
  {
116
    if (str[i] != 0)
117
      uart_putchar(str[i]);
118
    else
119
      break; // Ende des Strings erreicht
120
  }
121
}
122

123

124

125
char uart_getchar()
126
{
127
  // Ist schon ein Zeichen im Buffer?
128
  if (bit_is_set(UCSRA, RXC))
129
    return UDR;
130
  else 
131
    return -1;
132
}
133

134
void uart_readline(char *str)
135
{
136
  char c;
137
  unsigned char index;
138
  
139
  index = 0;
140

141
  while (1)
142
  {
143
    c = uart_getchar();
144
    if (c != -1)
145
    {
146
    
147

148

149
      if (c == 13) 
150
      {
151
        str[index] = 0;
152

153
        return;
154
      }
155
      else 
156
      {
157

158
    
159
        str[index] = c;
160
        index++;
161
      }
162
    }
163
  }
164
}
165

166

167

168
 
169
int main()
170
{
171

172
  uint16_t adcval;
173

174
  int last_sek;
175
 
176
  char Buffer[25];
177
 
178

179
  ADC_Init();
180

181
  DDRB=0xff;
182
  PORTB=0x00;
183

184
  sei();                                // Interrupts global an
185
 
186
  last_sek = 0;
187
  sekunden = 0;
188
  msekunden = 0;
189

190

191
  init_time();
192
  setup_uart();
193

194
  uart_putstring("Setup UART: check\r\n");
195
  uart_putstring("Setup ADC: ");
196
 
197
  _delay_ms(1000);
198
  
199
  uart_putstring("check\r\n");
200

201

202
  while( 1 ) 
203
  {
204

205
    if(sekunden>last_sek)
206
    {
207
  last_sek = sekunden;
208
    adcval = ADC_Read_Avg(0,5); 
209

210

211
 
212
    sprintf( Buffer, "Wert: %d", adcval );
213

214
  uart_putstring(Buffer);
215
  }
216
 
217
  }
218
}
#2425235
Lesenswert?

Hans B. schrieb:
> Ach, und wenn ich schon am Fragen bin:
>
> Kann ich ADC0 auch im single ended inupt mit dem 10 x gain nutzen? Die
> Table 84 des Datenblatts verstehe ich anders.

Du vesrstehst die Tabelle richtig. Singel Ended gibt es keinen Gain.

> Da mein INA333 aber leider
> nur ne 1000fache Verstärkung liefert, würde ich gern noch den gain
> dazuschalten.

Du kannst ja auch deine eigene Referenzspannung zur Messung hernehmen, 
die dann eben nur 1/10 der bereitgestellten ausmacht. Das müssten dann 
allerdings 0.25 Volt sein. Und die reicht dir nicht, obowhl du dein 
Signal schon um das 1000-fache verstärkt hast? Was misst du da?

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