我经常开始一个裸机微控制器项目,并最终使用随机定时器单元实现系统时间测量。
我现在正在使用ARM Cortex-M设备(尽管很短),并且通常使用SysTick
(“系统节拍”)中断来创建1ms分辨率计时器。它最近发现了一篇帖子,建议将两个可编程中断定时器(在Kinetis KL25Z器件上)链接起来,以便创建一个无中断的32位毫秒定时器,但牺牲了两个PIT
中断,这些中断可能会在以后派上用场。< / p>
所以我想知道是否有一些(某种)规范的方法来确定微控制器上的系统时间 - 最好是Kinetis KL2xZ设备,因为我目前使用这些设备,但不一定如此。
答案 0 :(得分:3)
你提出的规范方法就像你所做的一样 - 使用systick。这是Cortex-M架构定义的单个定时器设备;任何其他计时器硬件都在核心和供应商特定的外部。
某些部分(例如STM32F2)包含32位定时器/计数器硬件,因此您不需要链接两个。
最好的方法是通过定义您为所有部件实现的通用计时器API来抽象计时器服务,以便应用程序层对所有部分都相同。例如,在这种情况下,您可以简单地实现标准库clock()
function并定义CLOCKS_PER_SEC
。
如果 使用两个自由运行的级联定时器,则在组合两个计数器值时必须确保高/低字一致性:
#include <time.h>
clock_t clock( void )
{
uint16_t low_word = 0 ;
uint16_t hi_word = 0 ;
do
{
hi_word = readTimerH() ;
lo_word = readTimerL() ;
} while( hi_word != readTimerH() ) ;
return (clock_t)(hi_word << 16 | lo_word) ;
}
答案 1 :(得分:1)
我刚看了KL25子系列参考手册。 在第34章实时时钟(RTC)部分34.3.2时间计数器(可能与文档版本不同)。 我发现在RTC中有两个用于定时器计数器的寄存器
参考手册说
在写入秒寄存器之前,始终写入预分频器寄存器, 因为秒寄存器在预分频器的第14位的下降沿递增 注册强> 这意味着计算系统时间,读取rtc_sec_counter并添加14位prescalar_reg 您甚至可以创建一个宏来为您提供uSec中的系统时间和来自rtc_sec_counter和prescalar_reg或Sec的组合的mSec(显然来自rtc_sec_counter)
对于16位预分频器REG系统时钟为32.768 Khz,我们可以创建宏来获取uSec和mSec的时间
#define PRESCALAR_TICK 32768
#define KHZ 1000
#define MHZ 1000000
/// Here first we extract 14bit value of prescalar_reg and than multiply it with MHZ to get better precision
/// but this value will not go more than 14 Bit
#define GET_SYS_US ((((prescalar_reg & 0x03FFF)*MHZ)/PRESCALAR_TICK))
#define GET_SYS_MS (GET_SYS_US)/KHZ)
if you need time in milliseconds up to 32 bit use below macro
#define GET_SYS_US_32bit ((rtc_sec_counter * 0x3FFF) + GET_SYS_US)
#define GET_SYS_MS_32bit ((rtc_sec_counter * 0x3FFF) + GET_SYS_MS)
但要使用这些信息,您必须初始化您的RTC(显然)