STM32 SysTick秒用

STM32 SysTick妙用

​ 这里针对的是无操作系统的情况下的使用。之前一直想利用systick既实现记录系统运行时间又能够精确实现微秒延时的功能,如果将SysTick的定时器的定时中断时间设置为1us,这在有些情况下会导致死机的问题。这样的话就无法利用systick来实现us延时函数了。
​ 利用SysTick实现1ms定时中断,us延时函数可以利用SysTick的寄存器来运算得到精确的延时函数,具体实现如下:

头文件:

#ifndef __SYSTICK_H
#define __SYSTICK_H

#ifdef __cplusplus
 extern "C" {
#endif
   
/* Includes ------------------------------------------------------------------*/  
#include "stm32f10x.h"  
  
#define millis getCurrentMillis
#define micros getCurrentMicros
#define delay delay_ms
   
void systick_init(void);  
void systick_reset(void);
uint32_t getCurrentMillis(void);
uint32_t getCurrentMicros(void);
void delay_ms(uint32_t ms); 
void delay_us(uint32_t us); 
  
#ifdef __cplusplus
 }
#endif

#endif /*__SYSTICK_H */

源文件:

/* Includes ------------------------------------------------------------------*/
#include "bsp_systick.h"

__IO uint32_t _ms_tick = 0;

/**
  * @brief  initialize systick
  * @param  None
  * @retval None
  */
void systick_init(void) 
{
  _ms_tick = 0;  
  
  /* SystemCoreClock / 1000     1ms中断一次 */
	if(SysTick_Config(SystemCoreClock / 1000))
  {
    /*capture error*/
    while(1);
  }
}

/**
  * @brief  获取系统当前的ms计数值
  * @param  None
  * @retval 系统当前时间ms
  */
uint32_t getCurrentMillis(void)
{
  return _ms_tick;
}

/**
  * @brief  获取系统当前的us计数值
  * @param  delay time
  * @retval 系统当前时间us
  */
uint32_t getCurrentMicros(void)
{
  /* Ensure COUNTFLAG is reset by reading SysTick control and status register */
  //LL_SYSTICK_IsActiveCounterFlag();
  uint32_t m = getCurrentMillis(); 
  const uint32_t tms = SysTick->LOAD + 1;
  __IO uint32_t u = tms - SysTick->VAL;
  if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == (SysTick_CTRL_COUNTFLAG_Msk)) {
    m = getCurrentMillis(); 
    u = tms - SysTick->VAL;
  }
  return (m * 1000 + (u * 1000) / tms);
}

/**
  * @brief  复位系统计数
  * @param  None
  * @retval None
  */
void systick_reset(void) 
{
  _ms_tick = 0;
}

/**
  * @brief  delay (ms)
  * @param  delay time
  * @retval None
  */
void delay_ms(uint32_t ms) 
{ 
	uint32_t target;
	
	target = millis() + ms;
	while(millis() < target);
} 

/**
  * @brief  delay (us)
  * @param  delay us time
  * @retval None
  * @attention 延时的us数不应特别大,否则会导致nbTicks在计算时会溢出。
  */
void delay_us(uint32_t us)
{
  __IO uint32_t currentTicks = SysTick->VAL;
  /* Number of ticks per millisecond */
  const uint32_t tickPerMs = SysTick->LOAD + 1;
  /* Number of ticks to count */
   uint32_t nbTicks = ((us - ((us > 0) ? 1 : 0)) * tickPerMs) / 1000;
  /* Number of elapsed ticks */
  uint32_t elapsedTicks = 0;
  __IO uint32_t oldTicks = currentTicks;
  do {
    currentTicks = SysTick->VAL;
    elapsedTicks += (oldTicks < currentTicks) ? tickPerMs + oldTicks - currentTicks :
                    oldTicks - currentTicks;
    oldTicks = currentTicks;
  } while (nbTicks > elapsedTicks);
}

/**
  * @brief  SYSTICK中断服务函数
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
  _ms_tick++;
}

你可能感兴趣的:(STM32)