可以直接看定时器二代
systick定时器是属于cortex M内核的外设,专门为RTOS的系统时钟节拍设计的。systick是cortex M内核自带的,因此和debug调试接口一样,与单片机型号和厂商无关,只要是cortex M内核的单片机,都拥有这个24位的systick定时器。
systick定时器是一个24位递减计时器,用户至于要掌握CMSIS包中的SysTick_Config 函数进行初始化即可。
/** \brief System Tick Configuration
This function initialises the system tick timer and its interrupt and start the system tick timer.
Counter is in free running mode to generate periodical interrupts.
\param [in] ticks Number of ticks between two interrupts
\return 0 Function succeeded
\return 1 Function failed
*/
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 */
}
SysTick_Config(uint32_t ticks)函数通过参数ticks设置中断间隔,如果要设置1ms的中断间隔,则ticks = 系统时钟/1000. 设置Systick中断服务函数默认优先级最低,可以通过如下函数修改中断优先级。
// //优先级配置 抢占优先级1 子优先级2 越小优先级越高 抢占优先级可打断别的中断
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1,2));
初始化完成后,systick在设置的中断间隔到来时触发中断,进入中断服务函数
/**
* @brief systick中断服务函数
*
* @param
*
* @return
*
* @note
*
* @example
*
* @date 2019/6/10 星期一
*/
void SysTick_Handler(void)
{
}
完整代码 bsp_systick.h
#ifndef __BSP_SYSTICK_H
#define __BSP_SYSTICK_H
#include "stdint.h"
/**
* @brief 一个系统时间结构体
*/
typedef struct
{
void (* init) (void);
uint32_t (* get_time_us) (void);
uint32_t (* get_time_ms) (void);
void (* delay_us)(uint32_t);
void (* delay_ms)(uint32_t);
}systime_t;
/** 声明 systime */
extern systime_t systime;
#endif //__BSP_SYSTICK_H
bsp_systick.c
/*!
* @file bsp_systick.c
*
* @brief systick驱动文件
*
* @author 不咸不要钱
*
* @note 无
*
* @version 无
*
* @date 2019/10/18 星期五
*/
#include "bsp_systick.h"
#define EACH_PER_MS 25 /*!<每隔 25 ms 中断一次 systick 定时器是24位向下计数的定时器 最大装载值16777215 */
/**
* @brief 一个时间结构体
* @note 内部调用
*/
struct time{
uint32_t fac_us; /*!<us分频系数 */
uint32_t fac_ms; /*!<ms分频系数 */
volatile uint32_t millisecond; /*!<当前ms值 */
uint8_t ms_per_tick; /*!<每隔多少ms中断一次 */
}timer;
/*!
* @brief systime 初始化
*
* @param 无
*
* @return 无
*
* @note 默认优先级最低 可以修改
*
* @see systime.init(); //初始化
*
* @date 2019/6/10 星期一
*/
void systime_init(void)
{
timer.fac_us = SystemCoreClock / 1000000;
timer.fac_ms = SystemCoreClock / 1000;
timer.ms_per_tick = EACH_PER_MS;
timer.millisecond = 100;
SysTick_Config((SystemCoreClock / 1000) * timer.ms_per_tick ); //开启systick中断
// //优先级配置 抢占优先级1 子优先级2 越小优先级越高 抢占优先级可打断别的中断
// NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1,0));
}
/*!
* @brief systime 中断服务函数
*
* @param 无
*
* @return 无
*
* @note 无
*
* @see 无
*
* @date 2019/6/10 星期一
*/
void SysTick_Handler(void)
{
timer.millisecond += timer.ms_per_tick;
}
/*!
* @brief 获取当前时间
*
* @param 无
*
* @return 当前ms值
*
* @note 无
*
* @see system.get_time_ms(); //获取当前ms值
*
* @date 2019/6/10 星期一
*/
uint32_t systime_get_current_time_ms(void)
{
register uint32_t val, ms;
do
{
ms = timer.millisecond;
val = SysTick->VAL;
}while(ms != timer.millisecond);
return ms - val/timer.fac_ms;
}
/*!
* @brief 获取当前时间
*
* @param 无
*
* @return 当前us值
*
* @note 无
*
* @see system.get_time_us(); //获取当前ms值
*
* @date 2019/6/10 星期一
*/
uint32_t systime_get_current_time_us(void)
{
register uint32_t val, ms;
do
{
ms = timer.millisecond;
val = SysTick->VAL;
}while(ms != timer.millisecond);
return (uint32_t)((uint32_t)(ms * 1000) - val / timer.fac_us);
}
/*!
* @brief systime 延时函数
*
* @param us :延时时间
*
* @return 无
*
* @note 最大延时不要超过 4292s
*
* @see system.delay_us(1000); //延时1ms
*
* @date 2019/6/10 星期一
*/
void systime_delay_us(uint32_t us)
{
uint32_t now = systime.get_time_us();
uint32_t end_time = now + us - 3;
while( systime.get_time_us() <= end_time)
{
;
}
}
/*!
* @brief 延时函数
*
* @param ms : 延时时间
*
* @return 无
*
* @note 无
*
* @see system.delay_ms(1000); //延时1s
*
* @date 2019/6/10 星期一
*/
void systime_delay_ms(uint32_t ms)
{
while(ms--)
{
systime.delay_us(1000);
}
}
/** 创建一个systck实例 */
systime_t systime =
{
systime_init,
systime_get_current_time_us,
systime_get_current_time_ms,
systime_delay_us,
systime_delay_ms
};