Forum: Mikrocontroller und Digitale Elektronik Wert von ADC ändert sich nicht im Interrupt-Handler


von Henrik R. (searinox)


Lesenswert?

Hallo!
Ich probiere etwas mit dem ADC meines Atmega8 herum, und bin auf
folgendes Problem gestoßen:
Wenn ich den ADC in den Free-Running-Mode schalte und Interrupts
aktiviere, dann kann ändert sich der Wert von ADC innerhalb des
Interrupt-Handlers scheinbar nicht, er bleibt immer gleich.
Benutze ich einen Timer-Interrupt, dann kann ich den korrekten Wert von
ADC jeweils im Interrupt auslesen.
Hintergrund ist, dass ich einen gleitenden Mittelwert errechnen will
und dafür jedes Wandelergebnis in ein Array schreiben möchte.

Hier sind die wichtigen Codeteile:
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/signal.h>
4
5
...
6
7
#define AVERAGE_VAL 100
8
9
volatile uint16_t vals[AVERAGE_VAL];
10
volatile uint8_t ind = 0;
11
12
SIGNAL(SIG_ADC)
13
{
14
  /* Read the new value into the average array */
15
  if (ind > AVERAGE_VAL)
16
    ind = 0;
17
18
  vals[ind] = ADC;
19
  ind++;
20
}
21
22
...
23
24
void adc_init(void)
25
{
26
  /* Enable ADC and set prescaler to 64 */
27
  ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1);
28
29
  /* Use interrupts and free-running mode */
30
  ADCSRA |= _BV(ADFR) |_BV(ADIE);
31
32
  /* Use input channel 0 (PORTC0) */
33
  ADMUX = 0;
34
  
35
  /* Start conversion */
36
  ADCSRA |= _BV(ADSC);
37
}

Ich verwende einen Timer, der sich in gewissen abständen den Inhalt des
Arrays ansieht und den Mittelwert berechnet.
Mit der obigen Methode bleibt der Wert immer gleich (anscheinend das
erste Wandelergebnis).
Verschiebe ich den Code aus SIGNAL(SIG_ADC) in den Timerhandler,
funktioniert es.

Danke für Hilfe!

von noname (Gast)


Lesenswert?

>>   if (ind > AVERAGE_VAL)
würde hier >= benutzen, sonst pointerst Du mit
vals[AVERAGE_VAL]=ADC außerhalb Deines Arrays.

noch ein Tip:
wenn du den gleitenden Mittelwert berechnen willst, kannst Du das auch
gleich in der Int.-Routine erledigen. Dazu eine Variable, z.B. Mittel
nehmen und dann jedesmal davon den am weitesten zurückliegenden Wert
aus dem Array subtrahieren und den neusten Wert addieren.

von Henrik R. (searinox)


Lesenswert?

Hallo,
Die Zeile heißt nun
1
if (ind >= AVERAGE_VAL)
;)

leider ändert das nichts am Ergebnis. Auch das direkte Berechnen im
SIG_ADC-Handler hat nichts genützt.

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.