systick定时器 延时计时

可以直接看定时器二代
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;                  /*!
	uint32_t fac_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
};

你可能感兴趣的:(嵌入式,单片机,c语言,嵌入式)