Forum: Mikrocontroller und Digitale Elektronik Auf ADC warten im Interrupt?


von Thomas (Gast)


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

von SNR (Gast)


Lesenswert?

Adc von Timer triggern lassen und dann im Adc Interrupt die Werte 
wegspeicher.

von Tobi (Gast)


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.

von Bernd (Gast)


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.

von SNR (Gast)


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.

von Thomas (Gast)


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.

von Thomas (Gast)


Lesenswert?

Sind noch ein paar Syntax- und Logikfehler mit drinne ;)

von Thomas (Gast)


Lesenswert?

Sind noch ein paar Syntax- und Logikfehler mit drinne seh ich gerade ;)

von SNR (Gast)


Lesenswert?

Wieso lässt Du den Adc nicht direkt vom Timer starten.Erledigt der uC in 
Hardware für Dich! Den 2.Adc startest du dann per Software direkt im 
Anschluss zur ersten Messung in der Adc  ISR.

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.