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
Adc von Timer triggern lassen und dann im Adc Interrupt die Werte wegspeicher.
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.
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.
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.
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.
Sind noch ein paar Syntax- und Logikfehler mit drinne seh ich gerade ;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.