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

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.