在微控制器中确定系统时间的典型方法

时间:2014-10-03 20:59:22

标签: embedded arm microcontroller rtos cortex-m

我经常开始一个裸机微控制器项目,并最终使用随机定时器单元实现系统时间测量。

我现在正在使用ARM Cortex-M设备(尽管很短),并且通常使用SysTick(“系统节拍”)中断来创建1ms分辨率计时器。它最近发现了一篇帖子,建议将两个可编程中断定时器(在Kinetis KL25Z器件上)链接起来,以便创建一个无中断的32位毫秒定时器,但牺牲了两个PIT中断,这些中断可能会在以后派上用场。< / p>

所以我想知道是否有一些(某种)规范的方法来确定微控制器上的系统时间 - 最好是Kinetis KL2xZ设备,因为我目前使用这些设备,但不一定如此。

2 个答案:

答案 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中有两个用于定时器计数器的寄存器

  1. 32位秒计数器
  2. 16位预分频器寄存器,每32.768 kHz时钟周期递增一次

  3. 参考手册说

    在写入秒寄存器之前,始终写入预分频器寄存器, 因为秒寄存器在预分频器的第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(显然)