www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATMEGA 324PA ADC Kanalumschaltung


Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich versuche mit einem ATmega324PA zwei analoge Kanäle 
abwechselnd einzulesen:

Hierzu folgender Code:
#pragma vector=ADC_vect
__interrupt static void adc_isrConvComplete (void);

#define ADC_PRESCALER_VAL_128     0x07
#define ADC_AUTO_TRIGGER_ENABLE   0x20
#define ADC_TRIGGER_FREE_RUNNING  0x00
#define ADC_REFERENCE_AVCC        0x40
#define ADC_INTERRUPT_ENABLE      0x08
#define ADC_ENABLE                0x80
#define ADC_START                 0x40
#define ADC_CHANNEL_MASK          0xE0

#define ADC_STATE_STABILIZE_CHANNEL_0   0x00
#define ADC_STATE_READ_CHANNEL_0        0x01
#define ADC_STATE_STABILIZE_CHANNEL_1   0x02
#define ADC_STATE_READ_CHANNEL_1        0x03
#define ADC_CONVS_TO_STABILIZE          0x00

static UINT8 mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_0;
static UINT8 mg_u8StableTimeCtr = ADC_CONVS_TO_STABILIZE;

typedef struct {
  UINT16 u16Channel_0;
  UINT16 u16Channel_1;
} ADC_CONVERSION_RESULTS;
ADC_CONVERSION_RESULTS adc_sConversionResults;


#pragma vector=ADC_vect
__interrupt static void adc_isrConvComplete (void)
{
  switch (mg_u8AcquisitionState)
  {
  /* In diesem Zustand wird gewartet, bis sich der Wandlungswert stabilisiert hat*/
  case ADC_STATE_STABILIZE_CHANNEL_0:
      if (0 != mg_u8StableTimeCtr) 
      {
        mg_u8StableTimeCtr --;
        adc_vStart();
      }
      else 
      {
        mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_0;
        mg_u8StableTimeCtr = ADC_CONVS_TO_STABILIZE;
        adc_vStart();
      }
    break;
    
    /* Hier wird Kanal 0 ausgelesen und dann auf Kanal 1 umgeschaltet */
    case ADC_STATE_READ_CHANNEL_0:
      adc_sConversionResults.u16Channel_0 = adc_u16Read();
      adc_vStop();
      adc_vChannelSelect(MG_ADC_CHANNEL_1);
      mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_1;
      adc_vStart();
    break;
    
     /* In diesem Zustand wird gewartet, bis sich der Wandlungswert stabilisiert hat*/
    case ADC_STATE_STABILIZE_CHANNEL_1:
      if (0 != mg_u8StableTimeCtr) 
      {
        mg_u8StableTimeCtr --;
        adc_vStart();
      }
      else 
      {
        mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_1;
        mg_u8StableTimeCtr = ADC_CONVS_TO_STABILIZE;
        adc_vStart();
      }
    break;
    
    /* Hier wird Kanal 1 ausgelesen und dann auf Kanal 0 umgeschaltet */
    case ADC_STATE_READ_CHANNEL_1:
      adc_sConversionResults.u16Channel_1 = adc_u16Read();
      adc_vStop();
      adc_vChannelSelect(MG_ADC_CHANNEL_0);
      mg_u8AcquisitionState = ADC_STATE_STABILIZE_CHANNEL_0;
      adc_vStart();
    break;
  }
}

void adc_vInit()
{
  ADCSRA = (ADC_PRESCALER_VAL_128
           |ADC_INTERRUPT_ENABLE);
  ADCSRB = ADC_TRIGGER_FREE_RUNNING;
  ADMUX  = ADC_REFERENCE_AVCC;   
  ADCSRA |= ADC_ENABLE;
}

void adc_vStart()
{
  ADCSRA |= (ADC_START | ADC_ENABLE);
}

void adc_vStop()
{
  ADCSRA &= ~(ADC_START | ADC_ENABLE);
}

void adc_vChannelSelect(UINT8 u8Channel)
{
  ADMUX = (ADMUX & ADC_CHANNEL_MASK) |  u8Channel;
}

UINT8 adc_u8ReadSelectedCannel ()
{
  /* Gibt den derzeit ausgewaelten ADC Kanal zurueck */
  return (ADMUX & ~ADC_CHANNEL_MASK);
}

UINT16 adc_u16Read()
{ 
  /* Gibt den Wert der letzten AD-Wandlung zurueck */
  return ((ADCH<<8)|ADCL);
}

Das Ganze benimmt sich extrem seltsam: geht man im Single Step durch die 
ISR landen die richtigen Werte vom ADC an der richtigen Stelle von 
adc_sConversionResults. Im normalen Betrieb ist der Wert von Kanal 0 in 
beiden Kanalvariablen. Setzt man einen Breakpoint auf den Anfang der ISR 
kommt es relativ zufällig ab und zu vor, dass der Wert von Kanal 1 in 
beiden Kanalvariablen steht (So selten, das das im laufenden Btrieb 
nicht auffällt, ich kann die Daten über die UART ausgeben). Mittlerweile 
bis ich ziemlich ratlos. Hat jemand vielleicht eine Idee, wo das Problem 
liegen könnte?

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.