打印
[应用相关]

STM32的SYSTICK详解

[复制链接]
3715|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
bitofnoone|  楼主 | 2016-5-25 17:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
什么是SYSTICK:
这是一个24位的系统节拍定时器system tick timer,SysTick,具有自动重载和溢出中断功能,所有基于Cortex_M3处理器的微控制器都可以由这个定时器获得一定的时间间隔。
作用:
在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。要解决这个问题,可以使用实时操作系统(RTOS).
因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。
微控制器的定时器资源一般比较丰富,比如STM32存在8个定时器,为啥还要再提供一个SYSTICK?原因就是所有基于ARM Cortex_M3内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。而使用RTOS的第一项工作往往就是将其移植到开发人员的硬件平台上,由于SYSTICK的存在无疑降低了移植的难度。

  SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。
要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。

时钟的选择:
用户可以在位于Cortex_M3处理器系统控制单元中的系统节拍定时器控制和状态寄存器(SysTick control and status register ,SCSR)选择systick 时钟源。如将SCSR中的CLKSOURCE位置位,SysTick会在CPU频率下运行;而将CLKSOUCE位清除则SysTick会以CPU主频的1/8频率运行。
3.5版本的库函数与以往的有所区别
不存在stm32f10x_systick.c文件,故原来的一些函数也不存在,比如SysTick_SetReload(u32 reload);SysTick_ITConfig(FunctionalState NewState);等

在3.5版本的库函数中与systick相关的函数只有两个
第一个,SysTick_Config(uint32_t ticks),在core_cm3.h头文件中进行定义的。
第二个,void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),在misc.c文件中定义的。

SysTick_Config(uint32_t ticks),在core_cm3.h
主要的作用:
1、初始化systick
2、打开systick
3、打开systick的中断并设置优先级
4、返回一个0代表成功或1代表失败
注意:
Uint32_t ticks  即为重装值,
这个函数默认使用的时钟源是AHB,即不分频。
要想分频,调用void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),
但是要注意函数调用的次序,先SysTick_Config(uint32_t ticks),
后SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)

沙发
bitofnoone|  楼主 | 2016-5-25 17:08 | 只看该作者
函数说明:
/**
* [url=home.php?mod=space&uid=247401]@brief[/url]  Initialize and start the SysTick counter and its interrupt.
*
* @param   ticks   number of ticks between two interrupts
* [url=home.php?mod=space&uid=266161]@return[/url]  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.
*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            
  /* Reload value impossible */重装载值必须小于0XFF FFFF,为什么,这是一个24位的递减计数器。

  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
     /* set reload register */设置重装载值,SysTick_LOAD_RELOAD_Msk定义见后面
  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 */
}
#endif
与systick相关的寄存器定义
/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
  memory mapped structure for SysTick
  @{
*/
typedef struct
{
  __IO uint32_t CTRL; /*!< Offset: 0x00  SysTick Control and Status Register */
  __IO uint32_t LOAD; /*!< Offset: 0x04  SysTick Reload Value Register       */
  __IO uint32_t VAL; /*!< Offset: 0x08  SysTick Current Value Register      */
  __I  uint32_t CALIB; /*!< Offset: 0x0C  SysTick Calibration Register        */
} SysTick_Type;

与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 */时钟源选择位,0=外部时钟;1=内核时钟

#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 Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos            31      /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk            (1ul << SysTick_CALIB_NOREF_Pos)              
/*!< SysTick CALIB: NOREF Mask */

#define SysTick_CALIB_SKEW_Pos             30       /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk             (1ul << SysTick_CALIB_SKEW_Pos)               
/*!< SysTick CALIB: SKEW Mask */

#define SysTick_CALIB_TENMS_Pos             0       /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick CALIB: TENMS Mask */
/*@}*/ /* end of group CMSIS_CM3_SysTick */

使用特权

评论回复
板凳
bitofnoone|  楼主 | 2016-5-25 17:09 | 只看该作者
与systick相关的寄存器的说明





void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
作用:
选择systick的时钟源,AHB时钟或AHB的8分频
默认使用的是AHB时钟,即72MHz

函数说明:
/**
  * @brief  Configures the SysTick clock source.
  * @param  SysTick_CLKSource: specifies the SysTick clock source.
  *   This parameter can be one of the following values:
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
  * @retval None
  */
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}


Systick时钟源的定义:
/** @defgroup SysTick_clock_source
  * @{
  */

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)//将控制状态寄存器的第二位置0,即用外部时钟源
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)//将控制状态寄存器的第二位置1,即用内核时钟
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))


使用特权

评论回复
地板
bitofnoone|  楼主 | 2016-5-25 17:09 | 只看该作者
Systick定时时间的设定:

重装载值=systick 时钟频率(Hz)X想要的定时时间(S)
如:时钟频率为:AHB的8分频;AHB=72MHz那么systick的时钟频率为72/8MHz=9MHz;要定时1秒,则
重装载值=9000000X1=9000000;
定时10毫秒
重状态值=9000000X0.01=90000
Systick的中断处理函数,
在startup_stm32f10x_hd.s启动文件中有定义。
DCD     SysTick_Handler            ; SysTick Handler
根据需要直接编写中断处理函数即可:
Void SysTick_Handler (void)
{ ;}
注意:
如果在工程中,加入了stm32f10x_it.c,而又在主函数中编写中断函数,则会报错。
因为在stm32f10x_it.c文件中,也有这个中断函数的声明,只是内容是空的。
/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
}


使用特权

评论回复
5
bitofnoone|  楼主 | 2016-5-25 17:10 | 只看该作者
中断优先级的修改
在调用SysTick_Config(uint32_t ticks)之后,调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)。这个函数在core_cm3.h头文件中。
具体内容如下:
/**
* @brief  Set the priority for an interrupt
*
* @param  IRQn      The number of the interrupt for set priority
* @param  priority  The priority to set
*
* Set the priority for the specified interrupt. The interrupt
* number can be positive to specify an external (device specific)
* interrupt, or negative to specify an internal (core) interrupt.
*
* Note: The priority cannot be set for every core interrupt.
*/




static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if(IRQn < 0) {
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
  else {
    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
}

下面以一个实例来说明:
利用systick来实现以1秒的时间间隔,闪亮一个LED指示灯,指示灯接在GPIOA.8,低电平点亮。
#include "stm32f10x.h"
//函数声明
void GPIO_Configuration(void);//设置GPIOA.8端口
u32 t;//定义一个全局变量
int main(void)
{
// SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
       SysTick_Config(9000000);
       SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
       GPIO_Configuration();
       while(1);      
}

//GPIOA.8设置函数
void GPIO_Configuration(void)
{
GPIO_InitTypeDef  GPIO_InitStruct;//定义一个端口初始化结构体
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开GPIOA口时钟
       GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出
       GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置输出频率50M
       GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;//指定第8脚
       GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIOA.8      
       GPIO_SetBits( GPIOA,  GPIO_Pin_8);//置高GPIOA.8,关闭LED
}
//systick中断函数
void SysTick_Handler(void)
{
t++;
       if(t>=1)
       {
              if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1)
              {GPIO_ResetBits( GPIOA, GPIO_Pin_8);}      
       }
       if(t>=2)
       {
              if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==0)
                     {GPIO_SetBits( GPIOA, GPIO_Pin_8);}
                     t=0;
       }
}


使用特权

评论回复
6
bitofnoone|  楼主 | 2016-5-25 17:11 | 只看该作者
模拟后的结果
1、8分频后结果





2、直接调用SysTick_Config(9000000);即不分频的结果,间隔为1/8=0.125s


总结:
1、要使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可,
   自动完成了,重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。
2、要修改时钟源调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)。
3、要修改中断优先级调用
     void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
应用说明:
1、因systick是一个24位的定时器,故重装值最大值为2的24次方=16 777 215,
   要注意不要超出这个值。
2、systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。
3、每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。
4、采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。

使用特权

评论回复
7
迪卡| | 2016-5-25 20:19 | 只看该作者
systick是cortex_m3的标配,不是外设

使用特权

评论回复
8
643757107| | 2016-5-25 20:38 | 只看该作者

SysTick时钟,俗称“嘀嗒定时器”,这家伙能按固定的时间产生一次中断,通常是多长时间产生一次中断呢?官方给出的一个时间是1ms

那么,它是怎么准确的产生1ms的呢.. 先来看看这家伙在时钟树的哪里吧


是它,是它,就是它,红色框里的东东,可以看到,它是由HCLK/8得到的,也就是:72MHz/8=9MHz

我们还能在STM32手册上找到这么一句话:系统嘀嗒校准值固定位9000,当系统嘀嗒时钟设为9MHz,产生1ms时间基准.

让我们来看看9000是怎么来的,这里要看下SysTick寄存器的配置了


当然,这个图截得真他妈丑..不过来是可以看到SysTick共有4个寄存器.下面的图盗自别人的博客的, = =  但是链接没法给出,说是禁止URL 真蛋疼




注意看上面的CTRL寄存器的CLKSOURCE位(时钟源位),它有两个选择,一个是内核时钟源FLCK(72MHz),一个是外部时钟源HCLK,这里应该是

分频以后的了,所以应该是HCLK/8(9MHz);注意这里,这里选不同的值,重装寄存器里的值也是不同的.到下面配置的时候再说说.

好,那么我们来解释下9000的固定校准值是怎么来的:

我们知道,我们设定一个计数, 那么每次计数器减到 0 ,时间经过了:系统时钟周期  *计数器初值. 我们使用 72M 作为系统时钟, 那么每次计数器减 1 所用的时间是 1/72M, 计数器的初值如果是 72000 ,那么每次计数器减到 0 ,时间经过 (1/72M)*72000= 0.001 , (简单理解:用 72M 的时钟频率,即 1s 计数 72M=72000000 次,那 1ms 计数 72000 次,所以计数值为 72000 ) ,那么它的固定校准值是怎么来的呢..其实我也不知道的,可能和8分频有关系吧.. = = 实在不知道..官方系统库中也找不到关于它的设置 - - 可能是我蠢..

让我们来看看这些寄存器的配置:

系统库core_cm3.h中

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 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 */代码上说得很明白了~简单的抓一个来解释下吧.. 就抓CTRL吧.. 从上面的寄存器图上可以看到,它只需要配置4个位,即:16、2、1、0位,其它的保留不变不用鸟

#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */

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

ul是unsigned long 型, 这两行代码的意思是1左移2位,也就是将2这位置1,这里就是选择了内核时钟源FCLK(72MHz),所以我们要把计数初值设置为72000,这样才能

产生1ms的基准时钟哦~ 当然,如果这里将1改为0,那么就要将计数初值设为9000了~ 哟西~~


使用特权

评论回复
9
643757107| | 2016-5-25 20:52 | 只看该作者

SysTick_Config(SystemFrequency / 10)   函数的形参就是systick重装定时器的值。

systck计数频率为每秒72000000次,所以7200000次就是1/10秒,也就是100ms。

SysTick是1个24bit递减计数器,通过对SysTick控制与状态寄存器的设置,可选择HCLK时钟(72M)或HCLK的8分频(9M,缺省是这个)作为SysTick的时钟源。
SysTick的重装寄存器决定了定时器频率。


若SysTick的时钟源是72M,   SystemFrequency = 72000000Hz
所以 SysTick_Config(SystemFrequency / 1000); 就是1ms时基。
//     1/1000 s=1ms


STM32中sysTick的设置(转)

我不得不说意法半导体确实有点风骚!甚至有点变态。我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维。手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说。今天我们说的是systick定时器。

systick定时器和我上面说的情况一样,在手册中根本没有介绍。我费了九牛二虎之力才在一个犄角格拉里找到systick定时器的英文版的说明。在Cotex-M3有介绍,为什么要找STM32的介绍,是因为功能设置上还有点区别。首先看一下systick定时器的作用,下面是Cotex-M3里的一段话:
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。
该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。(知道我为什么找ST关于systick的说明了吧)。
下面介绍STM32中的systick,Systick 部分内容属于NVIC控制部分,一共有4个寄存器,名称和地址分别是:

STK_CSR,        0xE000E010  --  控制寄存器
STK_LOAD,     0xE000E014  --  重载寄存器
STK_VAL,        0xE000E018  --  当前值寄存器
STK_CALRB,   0xE000E01C  --   校准值寄存器
首先看STK_CSR控制寄存器:寄存器内有4个位t具有意义

   



第0位:ENABLE,Systick 使能位  (0:关闭Systick功能;1:开启Systick功能)
第1位:TICKINT,Systick 中断使能位    (0:关闭Systick中断;1:开启Systick中断)
第2位:CLKSOURCE,Systick时钟源选择  (0:使用HCLK/8 作为Systick时钟;1:使用HCLK作为Systick时钟)
第3位:COUNTFLAG,Systick计数比较标志,如果在上次读取本寄存器后,SysTick 已经数到了0,则该位为1。如果读取该位,该位将自动清零

STK_LOAD  重载寄存器:




Systick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD  重载寄存器是个24位的寄存器最大计数0xFFFFFF。

  

STK_VAL当前值寄存器:




也是个24位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在SysTick 控制及状态寄存器中的COUNTFLAG 标志。
STK_CALRB  校准值寄存器:




这个寄存器好像目前的水平我还用不到,大体意思明白点,把英文说明放这吧:
位31 NOREF :1=没有外部参考时钟(STCLK 不可用)0=外部参考时钟可用
位30 SKEW:1=校准值不是准确的1ms 0=校准值是准确的1ms
位[23:0] :Calibration value
Indicates the calibration value when the SysTick counter runs on HCLK max/8 as external clock. The value is product dependent, please refer to the Product Reference Manual, SysTick Calibration Value section. When HCLK is programmed at the maximum frequency, the SysTick period is 1ms. If calibration information is not known, calculate the calibration value required from the frequency of the processor clock or external clock.
SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。
下面我们就应用SysTick定时器来裸奔,把它作为一个定时器来用,还是老一套,在寄存器头文件中添加定义寄存器:
//*****************************************************************
//*                               SystemTick-Register                                   
//*******************************************************************
#define SYSTICK_TENMS    (*((volatile unsigned long *)0xE000E01C))
#define SYSTICK_CURRENT  (*((volatile unsigned long *)0xE000E018))
#define SYSTICK_RELOAD   (*((volatile unsigned long *)0xE000E014))
#define SYSTICK_CSR       (*((volatile unsigned long *)0xE000E010))
  

配置systick寄存器:
void SysTick_Configuration(void)
{
   SYSTICK_CURRENT=0; //当前值寄存器
   SYSTICK_RELOAD=20000; //重装载寄存器,系统时钟20M中断一次1mS
   SYSTICK_CSR|=0x06;// HCLK作为Systick时钟,Systick中断使能位
}
中断处理:
void SysTick_Handler(void) //中断函数
{
extern unsigned long TimingDelay; // 延时时间,注意定义为全局变量
  

SYSTICK_CURRENT=0;
if (TimingDelay != 0x00)
TimingDelay--;
}
利用systick的延时函数:
  

unsigned long TimingDelay;  // 延时时间,注意定义为全局变量
void Delay(unsigned long nTime)  //延时函数
{
SYSTICK_CSR|=0x07;   // 使能SysTick计数器
TimingDelay = nTime; // 读取延时时间
while(TimingDelay != 0); // 判断延时是否结束
SYSTICK_CSR|=0x06;// 关闭SysTick计数器
}
  

int main()
{
  SystemInit0();    //系统(时钟)初始化
stm32_GpioSetup (); //GPIO初始化

  SysTick_Configuration(); //配置systick定时器

while(1)
{
  GPIO_PORTB_ODR|=(1<<5);
Delay(1000); //1S
GPIO_PORTB_ODR&=~(1<<5);
Delay(1000); //1S                                                                                
  }
}
完成!Delay(1000);实现了1S的精确延时,利用Delay(unsigned long nTime);配合systick定时器可以实现任意时间的精确延时,当然通过定时器TIMx也是可以这样做的,我只是用它来说明systick定时器的用法。

使用特权

评论回复
10
皈依| | 2016-5-25 22:06 | 只看该作者
systick官方的讲解也很少,楼主讲解的非常详细!好评~哈哈

使用特权

评论回复
11
gejigeji521| | 2016-5-25 23:33 | 只看该作者
这个是专门用于提供时间时钟的。

使用特权

评论回复
12
robter| | 2016-5-26 08:00 | 只看该作者
很好的资料,学习了

使用特权

评论回复
13
johnrita| | 2016-5-26 10:10 | 只看该作者
学习!

使用特权

评论回复
14
fbn2580| | 2016-5-26 17:19 | 只看该作者
mark,学习了,最近刚开始折腾stm32,要好好看看了

使用特权

评论回复
15
只为梦| | 2016-5-28 13:26 | 只看该作者
非常详细,收藏着,以后研究

使用特权

评论回复
16
penguin008| | 2016-5-29 18:27 | 只看该作者
8楼的图死活刷不出来,是图床不好还是怎么的。。。

使用特权

评论回复
17
tanruiqiang| | 2016-6-3 09:07 | 只看该作者
感谢楼主无私分享

使用特权

评论回复
18
victor1934| | 2016-6-8 22:59 | 只看该作者
先收藏了,慢慢研究,谢谢分享,支持一下

使用特权

评论回复
19
tototm| | 2016-6-10 17:42 | 只看该作者
知道有,也用,一直没有深入进去!谢谢分享!

使用特权

评论回复
20
lovecat2015| | 2016-6-11 21:51 | 只看该作者
这个在学习ucos ii的时候会用的很熟练的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

85

帖子

5

粉丝