Auf ADC warten im Interrupt?

Gast #2598112
Lesenswert?

Nabend,

ich bin noch ziemlich unerfahren in der Mikrocontroller-Programmierung 
und habe eine Frage. Und zwar möchte ich ein Programm schreiben welches 
4 mal pro Sekunde je 2-ADC-Kanäle einliest und die Werte in Variabeln 
speichert.

Mein erster Ansatz war nun einfach im Timer-OVF-Interrupt zuerst Kanal0 
einzulesen und abzuspeichern, anschliessend den Kanal umzuschalten und 
dann Kanal1 einzulesen. Nun habe ich allerdings gelesen, dass diese 
Methode eher schlecht sei, da man in den Interrupts nicht (auf die 
Wandlung) warten soll.

Was wäre denn jetzt die "elegantere" Methode um diese Aufgabe zu lösen?

Besten Dank,
Thomas
Gast #2598172
Lesenswert?

Ich skizzier mal wie ich das im letzten Projekt gemacht habe. War mit 
einem MSP430.
1
(Pseudocode)
2

3
timer_interrupt()
4
{
5
  timer_int_count++;
6

7
  if(timer_int_count == anzahl_interrupt_bis_adc_gelesen_werden_soll)
8
  {
9
    read_adc = 1;
10
    verlasse_sleepmodus_beim_verlassen_der_isr();
11
  }
12
}
13

14
adc_interrupt()
15
{
16
  adc_ready = 1;
17
  adc_tmp = ADC_MEMORY;
18

19
  verlasse_sleepmodus_beim_verlassen_der_isr();
20
}
21

22
int main()
23
{
24
  enter_sleepmodus();
25

26
  if(read_adc)
27
  {
28
    read_adc = 0;
29
    
30
    adc_kanal1_aktivieren();
31

32
    while(!adc_fertig)
33
    {
34
      enter_sleepmodus();
35
    }
36

37
    adc_fertig = 0;
38

39
    meine_adcwerte[0] = adc_tmp;
40
    adc_tmp = 0;
41

42
    adc_kanal2_aktivieren();
43

44
    while(!adc_fertig)
45
    {
46
      enter_sleepmodus();
47
    }
48

49
    adc_fertig = 0;
50

51
    meine_adcwerte[1] = adc_tmp;
52
    adc_tmp = 0;
53
  }
54
}

In meinem Fall brauchte ich aber im Programmablauf die ADC-Werte und 
konnte die auch nicht früher auslesen (wegen Spannungsschwankungen bei 
temporären Lasten) und habe deshalb immer auf die ADC-Werte gewartet.

Je nach Projekt kann man auch im ADC Interrupt direkt die Werte in die 
entsprechenden Variablen wegspeichern und dann im Programmablauf direkt 
darauf zugreifen. Also im Grunde so wie SNR schon meinte.
Gast #2598186
Lesenswert?

Wie oft brauchst du die ADC-Daten?

Wenn die Daten genügen, die beim vorigen
Timer-Interrupt (IRQ) angelegen haben, so wäre
es recht elegant, in einem IRQ die letzten
AD-Daten abzuholen und die nächste Wandlung
anzustoßen.

Muss natürlich zeitlich passen.
Gast #2598202
Lesenswert?

Bernd schrieb:
> Wie oft brauchst du die ADC-Daten?
Er schreibt 4 Mal pro Sekunde, also alle 250ms.

Bernd schrieb:
> Wenn die Daten genügen, die beim vorigen
> Timer-Interrupt (IRQ) angelegen haben, so wäre
> es recht elegant, in einem IRQ die letzten
> AD-Daten abzuholen und die nächste Wandlung
> anzustoßen.

Und wieso dann nicht gleich die aktuellen Werte benutzen?
In der main hat er mehr als genug Zeit.
Gast #2598243
Lesenswert?

Hallo,

mein Mikrocontroller langweilt sich warscheinlich zu tode, da er 
ansonsten nur 2 Taster abfragen und entprellen sowie ein paar Leds 
ansteuern muss. Warscheinlich hätte ich das komplette Programm in die 
ISR schreiben können ohne dass es Probleme gibt. Aber mich hat einfach 
mal interessiert wie sowas die Profis machen.

Habe jetzt mal Folgendes in Anlehung an Tobis Code ausgetüftelt:
1
ISR(TIMER1_OVF_vect)
2
{
3
  flag.adc_read  = 1;
4
}
5

6
ISR(ADC_vect)
7
{  
8
  flag.adc_ready  = 1;
9
}
10

11

12
  while(1) {
13

14
    if (flag.adc_read == 1) {
15

16
      flag.adc_read++;
17

18
      ADMUX  = 0;
19
      ADCSRA  |= (1<<ADSC);
20
    }  
21
    else if ((flag.adc_read == 2) & flag.adc_ready) {
22
      
23
      flag.adc_read++;
24
      flag.adc_ready  = 0;
25

26
      egt    = ADC;
27

28
      ADMUX  = 1;
29
      ADCSRA  |= (1<<ADSC);
30

31
      if (egt > 812) {
32
        flag.alarm  = 1;
33
      }
34
      else {
35
        flag.alarm  = 0;
36
      }  
37
      if (!flag.modus) {
38
        LED_egt();
39
      }
40
    }
41
    else if ((flag.adc_read == 3) & flag.adc_ready) {
42
      
43
      flag.adc_read  = 0;
44
      flag.adc_ready  = 0;
45

46
      bat    = ADC;
47

48
      if ((bat < 625)||(bat > 862)) {
49
        flag.alarm  = 1;
50
      }
51
      else {
52
        flag.alarm  = 0;
53
      }
54
      if (flag.modus) {
55
        LED_bat();
56
      }
57
    }
58
  }

Leider habe ich die Schaltung nicht hier sonst könnte ich das direkt mal 
ausprobieren.

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