如何在Arduino中创建一个准确的定时器

时间:2016-06-20 09:29:28

标签: c timer arduino pwm arduino-due

我正在尝试使用Arduino Due中的TC定时器创建一些PWM波。我的问题是我无法使用这种计时器生成准确的频率。

这是我正在尝试做的简单代码:

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);
}

然后在Timer的Handle上我所做的就是触发输出引脚:

ioport_toggle_pin_level(OUT_PIN);

问题在于,当我尝试生成1000Hz波(当然为计时器提供2000Hz)时,它工作正常。但是当我尝试时,如3427Hz,那么它只产生3420Hz或类似的东西。

你有任何想法如何解决这个问题吗?我试图添加round()来计算'计数'变量值,它有点帮助,但仍然不是非常准确。

提前致谢。

2 个答案:

答案 0 :(得分:0)

我猜测TC0是一个8位定时器?你不会在"不寻常的"只有256个选项的间隔。

尝试使用16位定时器。如果你需要,我在GitHub上看过几个" Due Timer"

根据我的计算:

获得一个8位除数,预分频比为256:

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

生成

84MHz / 256 / 96 = 3,417.96 Hz

但是有16位,没有预分频:

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

生成

84MHz / 24511 = 3,427.03 Hz

由于计算的除数24511符合16位值,因此您已经接近所选择的利率。

当然,如果TC0实际上是一个16位定时器,那么还有其他错误! ;-)祝你好运!

答案 1 :(得分:0)

TC0是24位。 到期时的所有定时器周期寄存器都是24位。 如果使用pwm,则计数器周期寄存器为16位