好用的SYSTICK

好用的Systick

在core_cm3.h和core_cm4.h头文件里边都有Systick滴答定时器的配置函数。

/**
 * @brief  Initialize and start the SysTick counter and its interrupt.
 *
 * @param   ticks   number of ticks between two interrupts
 * @return  1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

该函数的功能是初始化滴答定时器的定时时间,还有使能本身的中断功能,其形式参数tick是自动重装载值。拿STM32F103c8t6举个例子,比如设置该单片机的系统时钟是48MHz(通俗的讲每秒钟时钟线能够波动48000000个脉冲,那么一个脉冲时间就是1/48000000),而入口参数ticks如果为48000的话,那么就是滴答定时器要运行48000个1/48000000秒后才会中断一次,就是中断周期1ms。
只要使用了上面的函数,就能使用滴答定时器来实现任务的调度切换,相比其他定时器,是不是很方便呢?!
讲究时间精确,中断服务函数尽量少程序。这里滴答定时器中断函数里只实现将一个变量加1操作

//uint32_t sysTickUptime=0;
void SysTick_Handler(void)
{
	sysTickUptime++;
}

在做一些设计过程中,可能会遇到一些算法需要时间变量,这时可以写下面的函数获取程序运行的时间。

1.获取当前的工程(程序)运行时间
uint32_t GetSysTime_us(void) 
{
    uint32_t ms, cycle_cnt;//register 
    do {
        ms = sysTickUptime;
        cycle_cnt = SysTick->VAL;
    } while (ms != sysTickUptime);
    return (ms * 1000) + (usTicks * 1000 - cycle_cnt) / usTicks;
}

其中的usTicks可以在系统初始化的时候算出来,函数可以是:

static void cycleCounterInit(void)
{
    RCC_ClocksTypeDef clocks;
    RCC_GetClocksFreq(&clocks);
    usTicks = clocks.SYSCLK_Frequency / 1000000;
}

比如Sysclk为48MHz,那么usTicks等于48,即1us。上面的函数GetSysTime_us无非就是ms加上不足ms的us,最后得到的就是us级别的时间。
解释(usTicks * 1000 - cycle_cnt) / usTicks:usTicks1000是滴答定时器的自动重装载值,usTick1000/usTick就是1ms。而滴答定时器是一个24位的递减计数器,所以要得到不足ms的us时间应该写成(usTicks * 1000 - cycle_cnt) / usTicks。

2.获取时间间隔(或是周期)

有些控制算法需要用到时间变量dt,比如数字滤波算法和PID算法,所以这里介绍下如何获取一个函数或者一段程序的执行周期dt,函数如下:

float Get_DeltaT(uint32_t currentT)
{
	static uint32_t previousT;
	volatile float	deltaT;
	deltaT= (currentT - previousT) * 1e-6;	
	previousT = currentT;
	return deltaT;
}
//调用方式:dt = Get_DeltaT(GetSysTime_us());
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值