简体   繁体   English

如何在Arduino Due中创建准确的计时器

[英]How to create an Accurate Timer in Arduino Due

I'm trying to create some PWM waves using a TC timer in Arduino Due. 我正在尝试使用Arduino Due中的TC计时器创建一些PWM波。 My problem is that I cannot generate accurate frequencies using this kind of timers. 我的问题是我无法使用这种计时器生成准确的频率。

Here's a simple code for what I'm trying to do : 这是我要执行的操作的简单代码:

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

Then on the Timer's Handle all what I do is triggering an output pin with : 然后在计时器的句柄上,我所做的所有事情都是通过以下方式触发输出引脚:

ioport_toggle_pin_level(OUT_PIN);

The problem is that when I try for instance to generate a 1000Hz wave (giving 2000Hz for the timer of course), it works fine. 问题是,例如,当我尝试生成1000Hz的电波(当然给计时器提供2000Hz的电波)时,它工作正常。 But when I try, like 3427Hz, then it generate only 3420Hz or something like that. 但是当我尝试时,例如3427Hz,则它仅产生3420Hz或类似的频率。

Do you have please any idea how to fix that ? 您是否知道如何解决该问题? I tried to add round() for calculating the 'counts' variable value, it helped a bit, but still not extremely accurate. 我试图添加round()来计算'counts'变量值,这虽然有所帮助,但仍然不够准确。

Thanks in advance. 提前致谢。

I'm guessing that TC0 is an 8-bit timer? 我猜TC0是一个8位定时器? You won't get good precision at "unusual" intervals with only 256 choices. 只有256个选择,您将无法以“异常”的间隔获得良好的精度。

Try using a 16-bit timer. 尝试使用16位计时器。 I've seen several "Due Timer"s on GitHub if you need them. 如果需要,我已经在GitHub上看到了几个“到期计时器”。

From my calculations: 根据我的计算:

Get an 8-bit divisor with a prescale by 256: 获得一个预分频为256的8位除数:

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

which generates 产生

84MHz / 256 / 96 = 3,417.96 Hz

But with 16 bits, no prescale: 但是只有16位,没有预分频:

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

which generates 产生

84MHz / 24511 = 3,427.03 Hz

Since the calculated divisor of 24511 fits inside a 16-bit value, you've gotten a lot closer to your chosen rate. 由于计算出的24511除数适合16位值,因此您已接近选择的速率。

And, of course, if TC0 is in fact a 16-bit timer, then there's something else wrong! 而且,当然,如果TC0实际上是一个16位定时器,那么还有其他错误! ;-) Good luck! ;-) 祝好运!

TC0 is 24 bit. TC0是24位。 all timer period registers on the due are 24 bit. 到期的所有定时器周期寄存器均为24位。 if using pwm the counter period registers are 16 bit 如果使用pwm,则计数器周期寄存器为16位

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM