这里针对的是无操作系统的情况下的使用。之前一直想利用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 u8g2移植笔记
下一篇:基于STM32指纹识别模块(TFS-M64)的学习
推荐阅读最新更新时间:2024-11-05 06:05
设计资源 培训 开发板 精华推荐
- 用于 LCD 显示器的 6-LED 白光 LED 驱动器
- 使用 NXP Semiconductors 的 MCF5232CVM150 的参考设计
- LTC3735EG 演示板,IMVP4 电源(钢崖模块),Vin = 5V 至 24V,Vout = 0.6V-1.75V@32A
- EVAL-ADF4252EB1,ADF4252小数n分频PLL频率合成器评估板
- LM224DR2G 双四路滤波器运算放大器的典型应用
- STM8-DS1302万年历
- TEA1892TS GreenChip SR控制器已添加板载以实现反激
- 使用 RTC2-0505SRW 隔离式 DC/DC 转换器的典型应用,根据 EN55022 B 类进行 EMC 滤波
- LTC2908CTS8-B1、3.3V 和 2.5V 双电源监视器的典型应用电路,未来可能扩展至多达六个电源
- 使用 LTC2367IDE-18、18 位、500ksps、伪差分单极 SAR ADC 的典型应用