我目前正在将我的DCF77 库(您可以在 GitHub 上找到源代码)从 Arduino(基于 AVR)移植到 Arduino Due(ARM Cortex M3)。
该库需要精确的 1ms 时序。一个明显的候选者是使用 systicks。方便的是,Arduino Due 已经为 1 kHz 的 systicks 设置好了。
但是,我的(AVR)DCF77 库一旦锁定到 DCF77 就能够调整时序。这是通过像这样操作计时器重新加载值来完成的
void isr_handler() {
cumulated_phase_deviation += adjust_pp16m;
// 1 / 250 / 64000 = 1 / 16 000 000
if (cumulated_phase_deviation >= 64000) {
cumulated_phase_deviation -= 64000;
// cumulated drift exceeds 1 timer step (4 microseconds)
// drop one timer step to realign
OCR2A = 248;
} else if (cumulated_phase_deviation <= -64000) {
// cumulated drift exceeds 1 timer step (4 microseconds)
// insert one timer step to realign
cumulated_phase_deviation += 64000;
OCR2A = 250;
} else {
// 249 + 1 == 250 == 250 000 / 1000 = (16 000 000 / 64) / 1000
OCR2A = 249;
}
DCF77_Clock_Controller::process_1_kHz_tick_data(the_input_provider());
}
我想把它移植到 ARM 处理器上。在 ARM 信息中心,我找到了以下文档。
配置 SysTick
...
要配置 SysTick,您需要使用 SysTick 事件之间所需的间隔加载 SysTick Reload Value 寄存器。定时器中断或 COUNTFLAG 位(在 SysTick 控制和状态寄存器中)在从 1 到 0 的转换时被激活,因此它每 n+1 个时钟周期激活一次。如果需要 100 的周期,则应将 99 写入 SysTick 重载值寄存器。SysTick 重载值寄存器支持 1 到 0x00FFFFFF 之间的值。
如果您想使用 SysTick 以定时间隔(例如 1 毫秒)生成事件,您可以使用 SysTick 校准值寄存器来缩放您的重载寄存器值。SysTick 校准值寄存器是一个只读寄存器,在 TENMS 字段(位 0 到 23)中包含 10ms 周期内的脉冲数。该寄存器还有一个 SKEW 位 (30),用于指示由于时钟频率的微小变化,TENMS 部分中的 10ms 校准不完全是 10ms。第 31 位用于指示是否提供参考时钟。
...
不幸的是,我没有找到任何关于 SysTick->LOAD 和 SysTick->CALIB 是如何连接的。也就是说:如果我想限制或加速 systicks,我是否需要操纵 LOAD 或 CALIB 值?我需要将哪些值放入这些寄存器中?
搜索互联网并没有带来任何更好的提示。也许我在错误的地方搜索。这些问题有更详细的参考吗?或者甚至是一些很好的例子?