0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一文详解SysTick寄存器和SysTick编程

安芯教育科技 来源:灵动MM32 MCU 作者:Nuoeriris 2022-05-13 12:08 次阅读

OS能够支持多任务,能够以周期性地完成上下文的切换,以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。上下文周期性切换需要一个定时器能够打断程序执行,SysTick定时器就可以提供必要的时钟节拍,为OS的任务调度提供一个有节奏的“心跳”。

SysTick定时器即系统滴答定时器,也称“心跳定时器”,它是一个24 位的倒计数定时器,计到0 时,将从重装载寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。

SysTick定时器被捆绑在NVIC中,用于产生SysTick异常(异常号:15),SysTick中断的优先级也可以设置。

它会根据节拍来工作,把整个时间段分成很多小小的时间片,而每个任务每次只能运行一个时间片的时间长度,超时就退出给别的任务运行,这样可以确保任何一个任务都不会霸占操作系统提供的各种定时功能,都与这个滴答定时器有关。

当启用时,定时器从重载值递减计数到零,在下一个时钟周期将重装载SYST\_RVR 中的值,然后在后续时钟周期递减。将零值写入 SYST\_RVR 会在下一次回调时禁用计数器。当计数器变为零时,COUNTFLAG 状态位设置为 1。读取 SYST\_CSR 将 COUNTFLAG 位清除为 0。写入 SYST\_CVR 将清除寄存器和 COUNTFLAG 状态位为 0,写入不会触发 SysTick 异常逻辑,读取该寄存器会在访问时返回其值。

1. SysTick寄存器

SysTick定时器主要由4个寄存器组成:

46c01c4c-d1b2-11ec-bce3-dac502259ad0.png

在CMSIS中系统控制寄存器结构体:


	

typedefstruct {__IOuint32_tCTRL;/*!< 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;

Arm官方资料中4个寄存器的命名分别是SYST\_CSR、SYST\_RVR、SYST\_CVR和SYST\_CALIB,但是在CMSIS中进行了简化命名,更加清晰明了。

1.1 SysTick控制和状态寄存器(SYST\_CSR)

46edf02c-d1b2-11ec-bce3-dac502259ad0.png

CSR寄存器用到的位有4个,bit0用于是否开启定时器,置1表示使能SysTick定时器;bit1用于控制是否产生中断,该位置为1为允许产生中断;bit2用于设置定时器的时钟源,设为1,定时器的时钟源为主时钟,反之设为0的话定时器的时钟源为主时钟的四分之一。

MM32F0130系列的SysTick的HCLK来源于AHB总线经过硬件4分频,FCLK直接来源于AHB时钟总线。

4721a58e-d1b2-11ec-bce3-dac502259ad0.png

当 SysTick 定时器从1计到0时,它将把COUNTFLAG位置位;

而下述方法可以清零:

  • 读取 SysTick 控制及状态寄存器(STCSR)

  • 往 SysTick 当前值寄存器(STCVR)中写任何数据

1.2 SysTick重装载寄存器(SYST\_RVR)
473c3caa-d1b2-11ec-bce3-dac502259ad0.png  RVR寄存器用到0~23位,这个值是定时器倒计时的初始值,打开定时器以后,就会从这里设置的值倒计时到0,倒计时到0以后,又会从此值开始倒计时。
1.3 SysTick当前值寄存器(SYST\_CVR)
4759d7ce-d1b2-11ec-bce3-dac502259ad0.png  CVR寄存器也是用到0~23位,这是一个状态寄存器,当定时器开始运作的时候,这个值在不断的变化,从RVR寄存器获取初值以后,倒计时到0。CURRENT:读此寄存器返回系统定时器的当前值,给这个寄存器赋值,将使定时器归0,且清CTRL中的COUNTFLAG位。
1.4 SysTick当前值寄存器(SYST\_CALIB)
47772126-d1b2-11ec-bce3-dac502259ad0.png  如果不知道校准信息,则根据处理器时钟或外部时钟的频率计算所需的校准值。校准值寄存器提供了这样一个解决方案:它使系统即使在不同的CM0产品上运行,也能产生恒定的SysTick中断频率。最简单的作法就是:直接把TENMS的值写入重装载寄存器,这样一来,只要没突破系统极限,就能做到每10ms来一次 SysTick异常。如果需要其它的SysTick异常周期,则可以根据TENMS的值加以比例计算。在系统定时器的四个寄存器中,SYST\_CALIB为校准寄存器,这个是在出厂之前就已经配置好了的,我们不必考虑这个寄存器。

2. SysTick编程

SysTick配置需要遵循一定的流程:
  1. 开始

  2. 禁止SysTick

  3. 设置重装值寄存器

  4. 清除当前值寄存器

  5. 使能SysTick

  6. 完成

SysTick操作相关函数有:

	__STATIC_INLINEuint32_tSysTick_Config(uint32_tticks); voidSysTick_CLKSourceConfig(u32systick_clk_source); voidRCC_SystickDisable(void); voidRCC_SystickEnable(u32sys_tick_period); 下面的代码演示启用 SysTick 的基本程序:

	;使能SysTick定时器,并且使能SysTick异常 LDRR0,=0xE000E010;加载STCSR的地址 MOVR1,#0 STRR1,[R0];先停止SysTick,以防意外产生异常请求 LDR R1, =0x3FF ;让SysTick每1024周期计完一次。因为是从1023数到 ;0,总共数了1024个周期,所以加载值为0x3FF STRR1,[R0,#4];写入重装载的值 STRR1,[R0,#8];往STCVR中写任意的数,以确保清除COUNTFLAG标志 MOVR1,#0x7;选择FCLK作为时钟源,并使能SysTick及其异常请求 STRR1,[R0];写入数值,开启定时器 在CMSIS库中有定义对应的配置函数:

	__STATIC_INLINEuint32_tSysTick_Config(uint32_tticks) { /*Reloadvalueimpossible*/ if((ticks-1UL)>SysTick_LOAD_RELOAD_Msk){ return(1UL); } /*setreloadregister*/ SysTick->LOAD=(uint32_t)(ticks-1UL); /*setPriorityforSystickInterrupt*/ NVIC_SetPriority(SysTick_IRQn,(1UL<< __NVIC_PRIO_BITS) - 1UL);  /* Load the SysTick Counter Value */     SysTick->VAL=0UL; /*EnableSysTickIRQandSysTickTimer*/ SysTick->CTRL=SysTick_CTRL_CLKSOURCE_Msk| SysTick_CTRL_TICKINT_Msk| SysTick_CTRL_ENABLE_Msk; /*Functionsuccessful*/ return(0UL); } SysTick可以通过轮询或者中断方式进行操作,使用轮询的程序可以读取SysTick控制和状态寄存器,检查COUNTFLAG,如果该位置位,则表明SysTick计数已减到0。中断方式延时参考程序:

	static__IOuint32_tTimingDelay; voidDelay(__IOuint32_tnTime) { TimingDelay=nTime; while(TimingDelay!=0); } voidSysTick_Handler(void) { if(TimingDelay!=0x00) { TimingDelay--; } } intmain(void) { //systick时钟为HCLK,中断时间间隔1ms if(SysTick_Config(SystemCoreClock/1000)) { while(1); } while(1) { Delay(200);//200ms } } 轮询方式延时参考程序:

	voiddelay_init() { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div4);//选择外部时钟HCLK/4 //为系统时钟的1/4,实际上也就是在计算1usSysTick的VAL减的数目 fac_us=SystemCoreClock/4000000; //代表每个ms需要的systick时钟数,即每毫秒SysTick的VAL减的数目 fac_ms=(u16)fac_us*1000; } voiddelay_ms(u16nms) { u32temp; SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit) SysTick->VAL=0x00;//清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;//开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16)));   //等待时间到达,看CTRL的第16位(COUNTFLAG)是否为1,看STRL的第0位(ENABLE)是否为1         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;//关闭计数器 SysTick->VAL=0X00;//清空计数器 } voiddelay_us(u32nus) { u32temp; SysTick->LOAD=nus*fac_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;//清空计数器 } SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如时间测量、定时或者闹铃等。

						

						

						
														


原文标题:技术分享 | Cortex-M0中断控制和系统控制(五)

文章出处:【微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    4991

    浏览量

    117414
  • 定时器
    +关注

    关注

    23

    文章

    3124

    浏览量

    111898
  • Systick
    +关注

    关注

    0

    文章

    62

    浏览量

    12938

原文标题:技术分享 | Cortex-M0中断控制和系统控制(五)

文章出处:【微信号:Ithingedu,微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    SysTick使用详解

    处理的微控制都可以由这个定时获得定的时间间隔。2. SysTick相关寄存器状态
    发表于 08-12 06:32

    寄存器编程个用systick定时的延时函数

    今天想自己用寄存器编程个用systick定时的延时函数,写完后做实验发现我要延时1s,但是却延时了8s。这个问题让我纠结了半天。实际上
    发表于 08-19 06:04

    Systick有哪些寄存器

    Systick有哪些寄存器
    发表于 11-24 07:07

    Systick寄存器的相关资料下载

    Systick寄存器可以和51中的定时相类比感觉就是51中定时的加强版实现个小小的Systick
    发表于 01-05 07:08

    SysTick的定义与相关寄存器详解

    、概述:SysTick个简单的递减24位计数如果你不需要再应用程序中嵌入操作系统,SysTick可以作为简单的延时和产生周期性的中断
    发表于 01-05 07:26

    SysTick寄存器介绍

    设置系统时钟SYSCLK 等于72M。当重装载数值寄存器的值递减到0 的时候,系统定时就产生次中断,以此循环往复。SysTick 寄存器
    发表于 01-21 11:37

    如何使用STM32实现systick的精确延时

    SYSTICK寄存器初始化 void SysTick_Configuration(void) { if (SysTick_Config(SystemCoreClock
    发表于 11-21 15:54 5702次阅读

    SysTick定时器介绍,SysTick定时器寄存器

    在 STM32F1 库函数中,并没有提供相应的 SysTick 定时器配置函数,我们要操作 SysTick 定时器就需要了解它的寄存器功能。 其实 SysTick 定时器
    的头像 发表于 02-11 15:37 1.7w次阅读
    <b class='flag-5'>SysTick</b>定时器介绍,<b class='flag-5'>SysTick</b>定时器<b class='flag-5'>寄存器</b>

    STM32F103:精准延时delay——SysTick使用

    处理器的微控制器都可以由这个定时器获得一定的时间间隔。2. SysTick相关寄存器状态寄存器-CTRLSTCLK外部时钟源:AHB总线时钟的 1/8FCLK 内部时钟:AHB总线时钟——STM32F103是72MHz重装载数值
    发表于 12-02 18:36 9次下载
    STM32F103:精准延时delay——<b class='flag-5'>SysTick</b>使用

    STM32_SysTick—系统定时器

    SysTick 的简介和寄存器的详细描述。因为 SysTick 是属于CM3 内核的外设,有关寄存器的定义和部分库函数都在 core_CM3.h 这个头文件中实现。所以学习
    发表于 12-23 19:56 2次下载
    STM32_<b class='flag-5'>SysTick</b>—系统定时器

    [学习笔记]STM32F1 SYSTICK 滴答定时器(寄存器、标准库、HAL库)

    目录0. 博主理解:1. 实验内容及步骤:2. 硬件说明3. 寄存器说明3.1 SysTick的时钟和使能:3.2 SysTick重装载数值寄存器:3.3
    发表于 12-23 20:02 7次下载
    [学习笔记]STM32F1 <b class='flag-5'>SYSTICK</b> 滴答定时器(<b class='flag-5'>寄存器</b>、标准库、HAL库)

    一文详解STM32的嘀嗒时钟(SysTick)

    计数值到0的时候,SysTick重装载寄存器就会自动重新装载初值。只要SysTick控制和状态寄存器(CTRL)中的使能位没有ENABLE清除掉,那么就会永远的执行下去。
    的头像 发表于 01-19 18:11 8904次阅读
    一文<b class='flag-5'>详解</b>STM32的嘀嗒时钟(<b class='flag-5'>SysTick</b>)

    SysTick时钟

    Cortex-M3内核的处理器,内部包含了一个SysTick定时器,SysTick是一个24位的倒计数定时器,当计数到0时,将从ReLoad寄存器中自动重装载定时初值,开始新一轮计数。只要不把它在
    的头像 发表于 03-01 17:40 521次阅读
    <b class='flag-5'>SysTick</b>时钟

    STM32 SysTick配置函数

    之前使用SysTick滴答定时器都是通过查找内核编程手册配置寄存器SysTick滴答定时器工作的。
    的头像 发表于 07-22 10:21 1060次阅读
    STM32 <b class='flag-5'>SysTick</b>配置函数

    个人对STM32 SysTick的总结(寄存器操作)

    一、概述:SysTick是一个简单的递减24位计数器。如果你不需要再应用程序中嵌入操作系统,SysTick可以作为简单的延时和产生周期性的中断。状态控制寄存器的第0位可以使能计数器,当前值寄存
    的头像 发表于 01-06 08:00 281次阅读
    个人对STM32 <b class='flag-5'>SysTick</b>的总结(<b class='flag-5'>寄存器</b>操作)