stm32-7SysTicks

stm32-7SysTicks


1.系统定时器的相关配置

首先跟踪一部分代码,下面为初始化滴答定时器的函数

    /* 配置SysTick为10ms中断一次*/
    SysTick_Init();

跟踪到bsp_SysTicks.c文件中对他的定义

/**
  * @brief  配置滴答定时器
  * @param  
  * @retval 
  * @attention:配置中断的时间间隔,配置成功后关闭定时器
  */
void SysTick_Init(void)
{
    /* 配置中断时间间隔
     * SystemFrequency / 1000    1ms中断一次
     * SystemFrequency / 100000  10us中断一次
     * SystemFrequency / 1000000 1us中断一次
     */
//  if (SysTick_Config(SystemFrequency / 100000))   // ST3.0.0库版本
    if (SysTick_Config(SystemCoreClock / 100000))   // ST3.5.0库版本
    { 
        /* Capture error */ 
        while (1);
    }
        // 关闭嘀嗒定时器  
    SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}

其中,函数SysTick_Config(SystemCoreClock / 100000) 配置中断时间间隔,配置失败返回1,跟踪到 core_cm3.h中:

/* #####################    SysTick function  ######################## */

#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0)

/**
 * @brief  Initialize and start the SysTick counter and its interrupt.
 *
 * @param   ticks   number of ticks between two interrupts
 * @return  1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 * ticks个时钟周期中断一次,中断时间=ticks*时钟周期
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{   //检查输入的参数是否正确,ticks的值<=fffffff
    if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
    //将ticks-1的值装入RELOAD,从ticks-1减到0是ticks
    SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
    //配置系统滴答定时器中断SysTick中断的优先级
    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
    //配置相关寄存器STK_CTRL:时钟源、异常请求、使能
    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 */
}

#endif
/* ###################    Reset function  ############################# */

这个内核中的函数中使用了位指示宏位屏蔽宏,先上代码,这是 core_cm3.h 中关于 SysTick 寄存器的一些定义

/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos         16                                             /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk         (1ul << SysTick_CTRL_COUNTFLAG_Pos)            /*!< SysTick CTRL: COUNTFLAG Mask */

#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */

#define SysTick_CTRL_TICKINT_Pos            1                                             /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)              /*!< SysTick CTRL: TICKINT Mask */

#define SysTick_CTRL_ENABLE_Pos             0                                             /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)               /*!< SysTick CTRL: ENABLE Mask */

/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */

/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos             0                                             /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick VAL: CURRENT Mask */

其中的寄存器位指示宏:SysTick_xxx_Pos ,宏展开后即为xxx 在相应寄存器中的位置,如控制 SysTick 时钟源的 SysTick_CTRL_CLKSOURCE_Pos ,宏展开为 2,这个寄存器位正是在寄存器 STK_CTRL 中的 Bit2。

而寄存器位屏蔽宏:SysTick_xxx_Msk,宏展开是xxx 的位全部置 1 后,左移 SysTick_xxx_Pos 位。如控制 SysTick 时钟源的SysTick_CTRL_CLKSOURCE_Msk,宏展开为 (1ul << SysTick_CTRL_CLKSOURCE_Pos) ,把无符号长整型数值(ul) 1 左移 2 位,得到了一个只有 Bit2:CLKSOURCE 位被置 1,其它位为 0 的数值,这样的数值配合位操作&(按位与)、| (按位或)可以很方便地修改寄存器的某些位。假如控制 CLKSOURCE 需要四个寄存器位,这个宏就应该被改为(0xf ul << SysTick_CTRL_CLKSOURCE_Pos) ,这样就会得到一个关于 CLKSOURCE 的四位被置 1 的值,这些宏的参数就是这样被确定的。

2.利用滴答定时器实现精确延时

关于使用滴答定时器时间精确延时函数:

/**
  * @brief      us延时程序,10us为一个单位»
  * @param  
  * @arg nTime: Delay_us( counts ) 延时为 counts * 10us
  * @retval     TimingDelay是全局变量
  */
void Delay_us(__IO u32 nTime)
{ 
    TimingDelay = nTime;    
    //使用滴答定时器
    SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;
    //直到TimingDelay减到0,延时结束
    while(TimingDelay != 0);
}

中断需要调用的TimingDelay自减函数

/**
  * @brief  获取节拍程序 
  * @param  
  * @retval 
  * @attention  在 SysTick 中断函数 SysTick_Handler()调用
  */
void TimingDelay_Decrement(void)
{
    if (TimingDelay != 0x00)
    { 
        TimingDelay--;
    }
}

中断函数SysTick_Handler(),在stm32f10x_it.h中由用户填写,每中断一次调用一次TimingDelay_Decrement();使TimingDelay自减一次,直到TimingDelay == 0

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
    TimingDelay_Decrement();    
}

注意

在一个文件里调用另外一个文件里的函数需要在该文件中用extern声明,不然会报错


End

你可能感兴趣的:(stm32)