单片机
返回首页

STM32 SysTick秒用

2022-08-10 来源:csdn

这里针对的是无操作系统的情况下的使用。之前一直想利用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++;

}


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何构建一个触摸传感器电路

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章