参考文档《Cortex-M3权威指南(中文).pdf》

什么是systick?

手册解释:

RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick 控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。

系统滴答定时器是一个非常基本的倒计时定时器,用于在每隔一 定的时间产生一个中断,即使是系统在睡眠模式下也能工作,并且在向量表中有它的一 席之地。。它使得 OS 在各 CM3 器件之间的移植中不必修改系统定时器的代码,移植工作一下子容易多了。 SysTick 定时器也是作为 NVIC 的一部分实现的

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号: 15)。在以前,大多操 作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如, 为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期 的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时 器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问 它的寄存器,以维持操作系统“心跳”的节律。

Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时 器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK, CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过, STCLK的 具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视 芯片的器件手册来决定选择什么作为时钟源。

个人理解:

systick就是一个基于M3、M4内核的一个简单的24bit,倒计时,自动重装载定时器,倒计时结束会产生一个中断。常用于做延时,在实时系统中做心跳时钟,用于任务的切换。

简述:

1、systick定时器,就是系统滴答定时器

2、24位自动重装载倒计时定时器

3、当倒计时到0时,将从RELOAD寄存器中自动重装载初值

4、只要不清除SysTick控制及状态寄存器的使能位,就永不停息,在睡眠模式下也能工作

5、systick倒计时结束,会产生一个中断,且中断优先级可以设置

四个寄存器:

1、SysTick控制和状态寄存器——CTRL

2、SysTick重装载数值寄存器——LOAD

3、SysTick当前值寄存器 ——VAL

4、SysTick校准值寄存器——CALIB

在core_cm3.h中可以看到定义

/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTickmemory 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控制和状态寄存器:-------------------------------------------/

位0:ENABLE=1 //使能滴答定时器

位1:TICKINT=0 //当SysTick倒数到0时候,无动作

TICKINT=1 //当SysTick倒数到0时候,会产生一个SysTick异常请求

位2:CLKSOURCE=0 //选择时钟源为外部时钟源(STCLK)——AHB总线时钟HCLK的1/8

CLKSOURCE=1 //选择时钟源为内核时钟源(FCLK)——AHB总线时钟HCLK=内核时钟

位16:COUNTFLAG:如果倒计时为0,该位自动置1,读取该位,自动清0(如果读取该位时未倒计时到0,则该位为0)

/---------------------------SysTick重装载数值寄存器------------------------------------------/

RELOAD[23:0]

倒数至0时,将会被重装载的值。

/------------------------------------SysTick当前值寄存器-------------------------------------------/

CURRENT[23:0]

会在一个自动重装载周期不断变化,读取该寄存器时,返回当前倒计时的值;写该寄存器时,会使该寄存器清0,同时还会清除SysTick控制及状态寄存器中的COUNTFLAG标志

/------------------------------------校准寄存器-------------------------------------/

待分析。。。

/-------------------------------------------------------------------------------------------------------------------/

库函数的配置:

misc.c中

/*** @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_CLKSourceConfig(uint32_t SysTick_CLKSource);//SysTick时钟源选择

if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;//选择内核时钟源(FCLK)=AHB时钟HCLK
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;//选择AHB总线时钟HCLK的1/8
  }

core_cm3.h或coer_cm4.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.*/
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 */
}#endif

SysTick_Config(uint32_t ticks);//初始化systick时钟为HCLK,并开启中断

ticks:两个中断之间的滴答数

if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);  //设置的值应该小于允许的最大值24bit

SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;//写load自动重载寄存器

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); //设置优先级

SysTick->VAL   = 0;//清除当前值寄存器

SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | //选择时钟//1<<2:CTRL第三位=1
                   SysTick_CTRL_TICKINT_Msk   | //开启中断
                   SysTick_CTRL_ENABLE_Msk; //使能定时器

在stm32f10x_it.c中

void SysTick_Handler(void)
{
}

SysTick_Handler(void);//中断处理函数

应用:

SysTick_Config(uint32_t ticks);//直接就可以配合中断处理函数使用

ticks参数:

例子:

if(SysTick_Config(SystemCoreClock/1000))//两个相邻中断时间间隔=1s

SystemCoreClock = 72MHz

ticks=72 000

理解:在系统72M时钟下:1/72M计数一次,也就是说:1S可以计数72M次

那么,计数ticks次,触发一次中断,即系统每计72 000个数触发一次中断

系统计 72 000 000 个数的时间为 1s,

则系统计72 000个数的时间为 1ms。

注意:用滴答时钟做delay延时时,不建议用中断的方式。一直进中断,太占用CPU资源

Systick 做delay:(抄正点原子的)

static u8  ticks_us=0;                          //us延时倍乘数
static u16 ticks_ms=0;                         //ms延时倍乘数void SysTick_init(void)
{SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);  //选择外部时钟  HCLK/8=9Mticks_us=SystemCoreClock/8000000;              //延时1us需要计数的值=9  //1S系统计数9M,则系统计数到9,耗时1usticks_ms=(u16)ticks_us*1000;                       //延时1ms需要计数的值
}void delay_us(u32 nus)
{u32 temp;           SysTick->LOAD=nus*ticks_us;                    //时间加载           SysTick->VAL=0x00;                         //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));     //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器SysTick->VAL =0X00;                           //清空计数器
}//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{                 u32 temp;        SysTick->LOAD=(u32)nms*ticks_ms;             //时间加载(SysTick->LOAD为24bit)SysTick->VAL =0x00;                           //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能滴答定时器,开始倒数do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));      //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器SysTick->VAL =0X00;                          //清空计数器
} 

static u8  ticks_us=0;  //设置最小时间单位的计数值//1us的计数值

static u8  ticks_ms=0;  //设置最小时间单位的计数值//1ms的计数值

void SysTick_init(void)//初始化滴答时钟
{
    //选择外部时钟  HCLK/8=9M
    //延时1us需要计数的值=9  //1S系统计数9M,则系统计数到9,耗时1us
    //延时1ms需要计数的值
}
        temp=SysTick->CTRL;//如果计数到0,读取该寄存器时,CTRL-bit16=0

while((temp&0x01)&&!(temp&(1<<16))) //所以temp的 bit16 和 bit0 都为1

(temp&0x01)=1;(temp&(1<<16))=1;   即:while((1) != (1))   不成立,退出。

/******************************修改之前的systick做delay***********************************/

在内核头文件中,有这么一个函数

/* ##################################    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.*/
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 */
}#endif

直接拿来用就好了

int main(void)
{   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); SysTick_Config(SystemCoreClock/1000);while(1)
{if(SysTickTime >= 1000)//500ms{}
}
}

SystemCoreClock/1000写进load值

ticks=72 000

理解:在系统72M时钟下:1/72M计数一次,也就是说:1S可以计数72M次

72 000次1ms

所以1ms,进一次中断

/*** @brief  This function handles SysTick Handler.* @param  None* @retval None*/
extern uint16_t SysTickTime;
void SysTick_Handler(void)
{SysTickTime++;if(SysTickTime >= 65535){SysTickTime=0;}
}

优化延时函数后流水灯

 while(1){if(SysTickTime>=1000){GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)?GPIO_ResetBits(GPIOC, GPIO_Pin_13),SysTickTime=0: GPIO_SetBits(GPIOC, GPIO_Pin_13),SysTickTime=0;}}

4、SysTick定时器的理解相关推荐

  1. 填坑-关于SysTick定时器

    目录 01.坑的由来 02.填坑 03.修改代码验证 04.总结 本文主要来填坑,更正之前文章的错误.也进一步加深了我对SysTick定时器的理解,希望对你有帮助. 01.坑的由来 在之前的推文中&l ...

  2. 玩转STM32F0 Value Line Discovery 之 深入理解 SYSTICK定时器

    在上面的点亮LED中用到了 Systick .GPIO,RCC,这次先介绍 SYSTICK定时器. 1.SYSTICK 定时器,又称节拍定时器.顾名思义,就是为操作系统提供一个固定的时钟参考.话不多说 ...

  3. STM32延时函数的四种方法:普通延时(2种)、SysTick 定时器延时(2种)

    STM32延时函数的三种方法:普通延时.SysTick 定时器延时(1.中断方式:2.非中断方式) 单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us( )和毫秒级delay_ ...

  4. 寄存器(R0~R16)以及从SysTick系统时钟理解RTOS移植初始化

    移植系统最重要的细节之一就是配置系统时钟 第一次玩RT-Thread,发现同样的程序逻辑,测试现象不一样,从现象很明显看出来是时钟频率配置不一样. 由于之前玩STM32几乎没有关注过系统时钟的初始化, ...

  5. 嵌入式单片机基础篇(十)之Systick定时器原理及应用

    Systick定时器原理及应用 1.什么是Systick定时器? 回答: (1)ystick定时器,是一个简单的定时器,对于CM3,CM4内核芯片,都有Systick定时器. (2)Systick定时 ...

  6. SysTick 定时器

    11.1关于 SysTick 定时器 SysTick定时器(又名系统滴答定时器)是存在于Cortex-M3的一个定时器,只要是ARM Cotex-M系列内核的MCU都包含这个定时器.使用内核的SysT ...

  7. SysTick定时器的一个简单应用

    SysTick即为系统定时器,又称嘀嗒定时器,是Cortex-M3内核的一个外设,集成在NVIC中.SysTick是一个24bit的向下递减的计数器,每计数一次的时间为1/SYSCLK(SYSCLK一 ...

  8. systick定时器 延时计时

    可以直接看定时器二代 systick定时器是属于cortex M内核的外设,专门为RTOS的系统时钟节拍设计的.systick是cortex M内核自带的,因此和debug调试接口一样,与单片机型号和 ...

  9. stm32 systick定时器

    systick定时器是系统滴答定时器,一个24位的倒计时定时器,计到0时,将从RELOAD寄存器中自动装载定时初值,只要不把它在Systick控制及状态寄存器中的使能位清楚,就永不停息,即使在睡眠状态 ...

最新文章

  1. Java 中字符串的格式化
  2. 手写 单隐藏层神经网络_反向传播(Matlab实现)
  3. 数据挖掘十大算法之—C4.5
  4. 在vue中实现picker样式_基于Vue实现timepicker
  5. 射灯安装方法图解_家居射灯怎么选?第三代宜美SMD射灯给你正解
  6. (68)SPI工作模式有哪些?分为几种极性模式。
  7. php垂直居中代码_纯css实现水平和垂直居中
  8. 有人说“如今聪明的年轻人上班,愚蠢的年轻人创业!”对此大家怎么看?
  9. 第三代计算机的内存使用是什么,lpddr3内存什么意思
  10. php 顺序排序,PHP顺序排序
  11. MacOS如何设置不使用时退出登录用户账号
  12. Python——python3的requests模块的导入
  13. uft怎么做app自动化测试_UFT自动化测试实施-VBS编程简要教程
  14. Origin自动寻峰
  15. np.array()函数
  16. 合作伙伴最怕的是什么_创业须知:什么样的人是好的合作伙伴?
  17. C语言在坐标轴上输出曲线,C语言打印正弦曲线、直线、圆等等
  18. 【计算机网络】Socket详解
  19. monthsbetween 在mysql_months_between()
  20. Word2016自第3页开始添加连续页脚(除掉封面和目录)

热门文章

  1. java 获取xml所有节点_获取XML下的所有节点(父节点及子节点)
  2. 高频故障-双击图标出现属性(打不开程序)
  3. 操作系统-Futex机制
  4. 开源虚拟化平台之KVM
  5. WC2015 k小割(k短路+暴力+搜索)
  6. mysql商品规格设计_关于商品规格(SKU)的设置
  7. Oracle DG broker搭建
  8. LeetCode | #6 ZigZag Conversion
  9. 无法启动此程序因为计算机中丢失d,怎么办?无法启动此程序因为计算机中丢失ms – 手机爱问...
  10. IDEA字体大小设置