Matthias Lipinsky schrieb:
>>Vielen Dank. Die Voraussetzung für die Methode mit Timer ist jedoch,
>>dass die Bearbeitungsdauer der A/D-Wandlung kürzer als 1ms sein muss.
>>Ich denke, dies wird immer erfüllt.
>
>
1 | > void 1ms_TimerInterrupt(void)
|
2 | >
|
3 | > ISR(ADC_vect)
|
4 | >
|
>
> Ich würde den ADC-Int weglassen und das ADC-Ergebnis einfach im nächsten
> 1ms-Int abholen, vor dem Start der nächsten Wandlung.
Im Gegenteil. Den ADC durch den Timer triggern lassen und optional,
falls der Timer Interrupt nicht verwendet wird (den benötigt man
eigentlich nicht) in der darauffolgenden ADC ISR das Interrupt-Flag des
Timer zurücksetzen. Das ergibt die genauesten Abtastintervalle die auf
einem AVR möglich sind, da nicht einmal mehr die zufällige Interrupt
Latency Time des Timer Interrupts eine Rolle spielt.
Ausschnitt einer ADC Initilisierung (für einen ATMega32)
1 | ...
|
2 | // ADC Trigger Source = Timer0 Compare Match
|
3 | SFIOR |= (1 << ADTS1) | (1 << ADTS0);
|
4 |
|
5 | ADCSRA = ADC_DIVISOR | // Pick the fastest sample frequency (smallest divisor) we can use
|
6 | _BV(ADEN)| // ADC an
|
7 | _BV(ADSC)| // Beginne mit der Konvertierung
|
8 | _BV(ADIE)| // ADC-Interrupt an
|
9 | _BV(ADATE); // Auto trigger on
|
10 | TIFR = _BV(OCF0); // Reset OCF0 - Flag
|
11 | ...
|
Und der zugehörigen ADC-ISR
1 | ...
|
2 | ISR(ADC_vect)
|
3 | {
|
4 | int16_t adc = ADCW; // ADC einlesen
|
5 |
|
6 | TIFR = _BV(OCF0); // Reset OCF0 - Flag
|
7 | ...
|
8 | }
|
9 | ...
|