Hallo,
Ich hab ein Problem mit einem Atmel SAM3S4B. Datenblatt:
http://www.atmel.com/Images/doc6500.pdf
Die Timer sind ab Seite 743 zu finden.
Folgendes Vorhaben:
- Timer 0 erzeugt ein Signal mit ~1ms Periode und 4 * 5us an-Zeit.
- in diesen 4 * 5us wird die Clock für Timer 2 freigegeben.
- Timer 2 macht dann 4 Perioden zu je 5us und triggert jedes Mal den
ADC.
- (Timer 0 und 2 haben den selben Prescaler und sind synchronisiert).
Ich will also alle 1ms 4 ADC-Shots. Danach einen Interrupt.
Das klappt auch mehr oder weniger gut. Immer die erste Periode von Timer
0 erzeugt einen Puls zu wenig an Timer 2. Und ich verstehe nicht, warum.
Anbei Aufzeichnungen von meinem Logcanalyzer.
led_rt: active low im Interrupt - also nach 4 ADC-Shots.
TIOA2: Trigger-Signal an den ADC.
1.png: der gesamte Ablauf.
Bei den Pulsen im gelben Kreis beginnt der ganze Ablauf. Die Pulse davor
sind vom vorherigen Ablauf und uninteressant.
Hier wird Timer 0 angestoßen und löst das erste mal beim orangen Kreis
aus.
Beim organgen Kreis würde ich dann auch den ersten Interrupt erwarten.
Wie in 2.png und 3.png zu sehen ist, passiert das aber nicht, weil der
TIOA2 den ADC nur 3 mal triggert und nicht 4 mal.
Erst ab dem zweiten Auslösen des Timers 0 läuft alles wie gewollt - zu
sehen in 4.png.
Die eigentliche Frage: warum hat der Timer 2 beim ersten Auslösen von
Timer 0 nur drei Perioden anstatt vier.
Der Code zum Timer-Setup:
1 | #define ADCSHOTS 4
|
2 |
|
3 | PMC_ENABLE_PC(TC0IRQ);
|
4 | PMC_ENABLE_PC(TC2IRQ);
|
5 |
|
6 | /*
|
7 | * timer2 as the adc trigger source
|
8 | * burst mode for ADC_SHOTS samples at 200kHz
|
9 | */
|
10 | TCB0_BASE->TC[2].TC_CMR = TCMCK2 | BurstXc2 | WAVE | CPCTRG | \
|
11 | (ClearOutput << B_ACPA) | (SetOutput << B_ACPC);
|
12 | TCB0_BASE->TC[2].TC_RC = sys_clock / 2 / 200000;
|
13 | TCB0_BASE->TC[2].TC_RA = TCB0_BASE->TC[2].TC_RC / 2;
|
14 |
|
15 | /*
|
16 | * timer0 as the tc2 gate
|
17 | * 1000Hz sampling rate
|
18 | */
|
19 | TCB0_BASE->TC[0].TC_CMR = TCMCK2 | BurstNone | WAVE | CPCTRG | \
|
20 | (SetOutput << B_ACPA) | (ClearOutput << B_ACPC);
|
21 | TCB0_BASE->TC[0].TC_RC = sys_clock / 2 / 1000;
|
22 | TCB0_BASE->TC[0].TC_RA = TCB0_BASE->TC[0].TC_RC - (TCB0_BASE->TC[2].TC_RC * ADC_SHOTS);
|
23 |
|
24 | /* gate clk of tc2 by tc0 */
|
25 | TCB0_BASE->TC_BMR = TIOA0XC2;
|
Gestartet werden die Timer damit:
1 | di();
|
2 | TCB0_BASE->TC[0].TC_CCR = CLKEN;
|
3 | TCB0_BASE->TC[2].TC_CCR = CLKEN;
|
4 | TCB0_BASE->TC_BCR = TCSYNC;
|
5 | ei();
|
Grüße,
Michael