2016-06-20 6 views
0

Ich versuche, einige PWM-Wellen mit einem TC-Timer in Arduino Due zu erstellen. Mein Problem ist, dass ich mit diesen Timern keine genauen Frequenzen erzeugen kann.So erstellen Sie einen genauen Timer in Arduino Due

Hier ist ein einfacher Code für das, was ich versuche zu tun:

alle
static void setupTimer(uint32_t freq_desired) 
{ 

uint32_t ul_div; 
uint32_t ul_tcclks; 
uint32_t ul_sysclk = sysclk_get_cpu_hz(); 
uint32_t counts; 

// Configure PMC 
pmc_enable_periph_clk(ID_TC); 

// Configure TC for the given frequency and trigger on RC compare. 
tc_find_mck_divisor(
    (uint32_t)freq_desired, // The desired frequency as a uint32. 
    ul_sysclk,    // Master clock freq in Hz. 
    &ul_div,    // Pointer to register where divisor will be stored. 
    &ul_tcclks,    // Pointer to reg where clock selection number is stored. 
    ul_sysclk);    // Board clock freq in Hz. 

tc_init(TC0, CHANNEL, ul_tcclks | TC_CMR_CPCTRG); 

// Find the best estimate of counts, then write it to TC register C. 
counts = (ul_sysclk/ul_div)/freq_desired; 

tc_write_rc(TC0, 0, counts); 

// Enable interrupts for this TC, and start the TC. 
tc_enable_interrupt(TC0, CHANNEL0, TC_IER_CPCS);    // Enable interrupt. 

tc_start(TC0,CHANNEL0);   // Start the TC. 

NVIC_DisableIRQ(TC_IRQn); 
NVIC_ClearPendingIRQ(TC_IRQn); 
NVIC_SetPriority(TC_IRQn,configMAX_PRIORITIES); 
NVIC_EnableIRQ(TC_IRQn); 
} 

dann auf den Timer des Handle, was ich tun, um eine Ausgangsstift Auslösung mit:

ioport_toggle_pin_level(OUT_PIN); 

Das Problem ist, Wenn ich zum Beispiel versuche, eine 1000 Hz-Welle zu erzeugen (was natürlich 2000 Hz für den Timer bedeutet), funktioniert es gut. Aber wenn ich versuche, wie 3427Hz, dann erzeugt es nur 3420Hz oder etwas ähnliches.

Haben Sie bitte eine Idee, wie Sie das beheben? Ich habe versucht, Runde() für die Berechnung der 'counts' Variable Wert hinzuzufügen, half es ein wenig, aber immer noch nicht sehr genau.

Vielen Dank im Voraus.

+0

Ich glaube nicht, dass Sie es genau machen können, weil 16.000.000 (Systemtaktfrequenz) durch 3427 unteilbar ist. – MikeCAT

+0

Denken Sie wie @MikeCAT. Wahrscheinlich ist das Problem die Vielfalt mit 16MHz ... – jabujavi

+0

Ja, das ist es, was ich auch dachte (ich benutze die Due, also ist die Uhr 84MHz). Gibt es einen anderen Weg, um diese Genauigkeit mit anderen Mechanismen als die TC-Timer zu erreichen? –

Antwort

0

Ich vermute, dass TC0 ist ein 8-Bit-Timer? Sie werden keine gute Präzision in "ungewöhnlichen" Intervallen mit nur 256 Möglichkeiten erhalten.

Versuchen Sie es mit einem 16-Bit-Timer. Ich habe mehrere "Due Timer" auf GitHub gesehen, wenn Sie sie brauchen.

Aus meinen Berechnungen:

Holen Sie sich einen 8-Bit-Teiler mit einem prescale von 256:

84MHz/3427/256 = 95.75 divisor, round to 96 

die

84MHz/256/96 = 3,417.96 Hz 

Aber mit 16 Bit erzeugt, keine prescale:

84MHz/3427 = 24,511.23 divisor, truncate to 24511 

die

84MHz/24511 = 3,427.03 Hz 

Da der berechnete Teiler von 24511 paßt in einem 16-Bit-Wert erzeugt, haben Sie viel näher an den gewählten Rate bekommen.

Und natürlich, wenn TC0 tatsächlich ein 16-Bit-Timer ist, dann ist da noch etwas falsch! ;-) Viel Glück!

0

TC0 ist 24 Bit. alle Zeitgeber-Register auf dem fälligen sind 24 Bit. Wenn Sie pwm verwenden, sind die Zählerperiodenregister 16 Bit

Verwandte Themen