Forum: Mikrocontroller und Digitale Elektronik ATMEGA 324PA ADC Kanalumschaltung


von Manuel (Gast)


Lesenswert?

Hallo, ich versuche mit einem ATmega324PA zwei analoge Kanäle 
abwechselnd einzulesen:

Hierzu folgender Code:
1
#pragma vector=ADC_vect
2
__interrupt static void adc_isrConvComplete (void);
3
4
#define ADC_PRESCALER_VAL_128     0x07
5
#define ADC_AUTO_TRIGGER_ENABLE   0x20
6
#define ADC_TRIGGER_FREE_RUNNING  0x00
7
#define ADC_REFERENCE_AVCC        0x40
8
#define ADC_INTERRUPT_ENABLE      0x08
9
#define ADC_ENABLE                0x80
10
#define ADC_START                 0x40
11
#define ADC_CHANNEL_MASK          0xE0
12
13
#define ADC_STATE_STABILIZE_CHANNEL_0   0x00
14
#define ADC_STATE_READ_CHANNEL_0        0x01
15
#define ADC_STATE_STABILIZE_CHANNEL_1   0x02
16
#define ADC_STATE_READ_CHANNEL_1        0x03
17
#define ADC_CONVS_TO_STABILIZE          0x00
18
19
static UINT8 mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_0;
20
static UINT8 mg_u8StableTimeCtr = ADC_CONVS_TO_STABILIZE;
21
22
typedef struct {
23
  UINT16 u16Channel_0;
24
  UINT16 u16Channel_1;
25
} ADC_CONVERSION_RESULTS;
26
ADC_CONVERSION_RESULTS adc_sConversionResults;
27
28
29
#pragma vector=ADC_vect
30
__interrupt static void adc_isrConvComplete (void)
31
{
32
  switch (mg_u8AcquisitionState)
33
  {
34
  /* In diesem Zustand wird gewartet, bis sich der Wandlungswert stabilisiert hat*/
35
  case ADC_STATE_STABILIZE_CHANNEL_0:
36
      if (0 != mg_u8StableTimeCtr) 
37
      {
38
        mg_u8StableTimeCtr --;
39
        adc_vStart();
40
      }
41
      else 
42
      {
43
        mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_0;
44
        mg_u8StableTimeCtr = ADC_CONVS_TO_STABILIZE;
45
        adc_vStart();
46
      }
47
    break;
48
    
49
    /* Hier wird Kanal 0 ausgelesen und dann auf Kanal 1 umgeschaltet */
50
    case ADC_STATE_READ_CHANNEL_0:
51
      adc_sConversionResults.u16Channel_0 = adc_u16Read();
52
      adc_vStop();
53
      adc_vChannelSelect(MG_ADC_CHANNEL_1);
54
      mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_1;
55
      adc_vStart();
56
    break;
57
    
58
     /* In diesem Zustand wird gewartet, bis sich der Wandlungswert stabilisiert hat*/
59
    case ADC_STATE_STABILIZE_CHANNEL_1:
60
      if (0 != mg_u8StableTimeCtr) 
61
      {
62
        mg_u8StableTimeCtr --;
63
        adc_vStart();
64
      }
65
      else 
66
      {
67
        mg_u8AcquisitionState = ADC_STATE_READ_CHANNEL_1;
68
        mg_u8StableTimeCtr = ADC_CONVS_TO_STABILIZE;
69
        adc_vStart();
70
      }
71
    break;
72
    
73
    /* Hier wird Kanal 1 ausgelesen und dann auf Kanal 0 umgeschaltet */
74
    case ADC_STATE_READ_CHANNEL_1:
75
      adc_sConversionResults.u16Channel_1 = adc_u16Read();
76
      adc_vStop();
77
      adc_vChannelSelect(MG_ADC_CHANNEL_0);
78
      mg_u8AcquisitionState = ADC_STATE_STABILIZE_CHANNEL_0;
79
      adc_vStart();
80
    break;
81
  }
82
}
83
84
void adc_vInit()
85
{
86
  ADCSRA = (ADC_PRESCALER_VAL_128
87
           |ADC_INTERRUPT_ENABLE);
88
  ADCSRB = ADC_TRIGGER_FREE_RUNNING;
89
  ADMUX  = ADC_REFERENCE_AVCC;   
90
  ADCSRA |= ADC_ENABLE;
91
}
92
93
void adc_vStart()
94
{
95
  ADCSRA |= (ADC_START | ADC_ENABLE);
96
}
97
98
void adc_vStop()
99
{
100
  ADCSRA &= ~(ADC_START | ADC_ENABLE);
101
}
102
103
void adc_vChannelSelect(UINT8 u8Channel)
104
{
105
  ADMUX = (ADMUX & ADC_CHANNEL_MASK) |  u8Channel;
106
}
107
108
UINT8 adc_u8ReadSelectedCannel ()
109
{
110
  /* Gibt den derzeit ausgewaelten ADC Kanal zurueck */
111
  return (ADMUX & ~ADC_CHANNEL_MASK);
112
}
113
114
UINT16 adc_u16Read()
115
{ 
116
  /* Gibt den Wert der letzten AD-Wandlung zurueck */
117
  return ((ADCH<<8)|ADCL);
118
}

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?

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.