www.mikrocontroller.net

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


Autor: Henrik Ronellenfitsch (searinox)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <stdint.h>
#include <avr/io.h>
#include <avr/signal.h>

...

#define AVERAGE_VAL 100

volatile uint16_t vals[AVERAGE_VAL];
volatile uint8_t ind = 0;

SIGNAL(SIG_ADC)
{
  /* Read the new value into the average array */
  if (ind > AVERAGE_VAL)
    ind = 0;

  vals[ind] = ADC;
  ind++;
}

...

void adc_init(void)
{
  /* Enable ADC and set prescaler to 64 */
  ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1);

  /* Use interrupts and free-running mode */
  ADCSRA |= _BV(ADFR) |_BV(ADIE);

  /* Use input channel 0 (PORTC0) */
  ADMUX = 0;
  
  /* Start conversion */
  ADCSRA |= _BV(ADSC);
}

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!

Autor: noname (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Henrik Ronellenfitsch (searinox)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Die Zeile heißt nun
if (ind >= AVERAGE_VAL)
;)

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

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.