SysTick定时器和delay延迟函数

发布者:chi32最新更新时间:2018-07-17 来源: eefocus关键字:SysTick  定时器  delay  延迟函数 手机看文章 扫描二维码
随时随地手机看文章

一,什么是Systick定时器


  Systick定时器也叫滴答定时器,是内核级别的24位倒计数简单定时器,常用做延迟和系统心跳时钟(如:UCOS) 

  优点:节省MCU资源,不需要浪费一个定时器,只要不清除Systick使能位,就不会停止,即使在睡眠模式下也能工作 

  捆绑在NVIC中断优先级管理,能产生Systick异常(中断),可设置中断优先级


二,Systick相关寄存器


  CTRL: Systick控制和状态寄存器 

  LOAD: Systick重装载寄存器 

  VAL: Systick当前值寄存器 

  CALIB: Systick校准值寄存器 

  定时器工作方式: 

  每经过一个Systick时钟周期,VAL寄存器值-1,当VAL=0,LOAD寄存器中的重装载值赋值给VAL寄存器作为初值….


 1,CTRL-控制和状态寄存器


  这里写图片描述 

  CLKCOURCE-时钟源 

   0:外部时钟源HCLK(AHB总线时钟)/8 72M/8 = 9M 

   1:内核时钟(HCLK) 72M 

  配置函数:


    SysTick_CLKSourceConfig();

1

 2,LOAD-Systick重装载寄存器


  这里写图片描述


 3,VAL-Systick当前值寄存器


  这里写图片描述 

  每经过一个Systick时钟周期,VAL寄存器值-1 

  读取寄存器:返回当前VAL值 

  写寄存器:清零VAL值,还会使CTRL中COUNTFLAG位清零


 4,CALIB-Systick校准值寄存器


  这里写图片描述


三,SysTick函数


 固件库SysTick相关函数


SysTick_CLKSourceConfig()          //Systick选择时钟源(FWLIB-misc.c文件中)

SysTick_Config(uint32_t ticks)     //初始化Systick(CORE-core_cm3.h文件中)

1

2

 Systick中断服务函数:


void SysTick_Handler(void);

1

1,SysTick_CLKSourceConfig()分析:


在FWLIB-misc.c中找到SysTick_CLKSourceConfig()函数源码:

/**

  * @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;          //内部时钟72M

  }

  else

  {

    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;     //外部时钟 72/8=9M

  }

}


 功能:配置SysTick->CTRL寄存器


 在core_cm3.h中找到SysTick结构体定义:


#define SysTick_BASE  (SCS_BASE +  0x0010)    /* SysTick Base Address */


#define SysTick   ((SysTick_Type *) SysTick_BASE) /* SysTick configuration struct */


/** @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_CLKSourceConfig参数的两种情况:


/** @defgroup SysTick_clock_source

  * @{

  */


#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)

#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)

#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \

                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))


两种时钟源 : 

  SysTick_CLKSource_HCLK_Div8 外部时钟 72/8=9M 

  SysTick_CLKSource_HCLK 内部时钟 HCLK=72M


2,SysTick_Config(uint32_t ticks)分析


core_cm3.h中找到SysTick_Config函数源码:


/**

 * @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);       //ticks参数有效性检查


  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; //设置重装载值

                                                    //-1:装载时消耗掉一个Systick时钟周期


  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); //配置NVIC


  SysTick->VAL   = 0;    //初始化VAL=0,使能Systick后立刻进入重装载

  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |      //选择时钟源

                   SysTick_CTRL_TICKINT_Msk   |      //开启Systick中断

                   SysTick_CTRL_ENABLE_Msk;          //使能Systick定时器

  return (0);      /* Function successful */

}


#endif


作用:使能Systick定时器,开启SysTick中断,配置中断时间间隔 

参数ticks:设置多少个Systick时钟周期产生一次中断


四,SysTick实现延时函数


1,延时函数初始化


static u8  fac_us=0;           //延时微秒的频率

static u16 fac_ms=0;           //延时毫秒的频率


void delay_init()

{

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择时钟源-外部时钟-HCLK/8

    fac_us=SystemCoreClock/8000000; // 72/8 延时1微秒9个时钟周期

    fac_ms=(u16)fac_us*1000;   // 延时1毫秒9000个Cystic时钟周期

}


2,微秒延时函数


/**

 * nus : 延时多少微秒

 **/

void delay_us(u32 nus)

{

    u32 temp;

    //nus*fac_us值最大不能超过SysTick->LOAD(24位)-1

    SysTick->LOAD=nus*fac_us;    // 设置重载值:n(us)*延时1us需要多少个SysTick时钟周期

    SysTick->VAL=0x00;                       // VAL初始化为0

    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; // 使能SysTick定时器

    do

    {

        temp=SysTick->CTRL;

    }while((temp&0x01)&&!(temp&(1<<16)));    // 等待计数时间到达(位16)

    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; // 关闭使能

    SysTick->VAL =0X00;                      // 重置VAL

}


3,毫秒延时函数


/**

 * nms : 延时多少毫秒

 **/

void delay_ms(u16 nms)

{

    u32 temp;

    SysTick->LOAD=(u32)nms*fac_ms;

    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  定时器  delay  延迟函数 引用地址:SysTick定时器和delay延迟函数

上一篇:STM32之Systick定时器解析
下一篇:stm32f103 FreeRTOS 滴答时钟配置

推荐阅读最新更新时间:2024-03-16 16:09

浅谈AVR中定时器几种工作模式
AVR有三个定时计数器,其中定时计数器0和定时计数器2是8位的,定时计数器1是16位。 在学习AVR定时计数器时,刚开始被一大堆的寄存器搞的有点晕了,后来认真的把Datasheet中的有关寄存器先看了一遍,再重新看定时计数器的内容才理清了。这里做个总结吧,加深自己的印象。 定时计数器0和定时计数器2基本上是相同的。以定时计数器0来总结它的几种工作模式的不同。 普通模式:不做介绍,和51里面是一模一样的。 CTC模式:当寄存器TCNT0与OCR0相等时(即匹配),OC0按照COM0[1:0]的值相应的改变(置位,清零或取反)。同时TCNT0清零,TCNT0从0x00重新开始计数,当计数结果和下一个OCR0寄存器中值相等时又
[单片机]
浅谈AVR中<font color='red'>定时器</font>几种工作模式
STM32一个定时器同时捕获4路PWM波
问题的提出: 最近需要用航模遥控器控制遥控车,32单片机做主控,需要用到4个通道即需要捕获4路PWM波。如果用四个定时器来捕获四路PWM波,就太浪费资源了。由于STM32单片机的定时器资源有限,故设想用一个定时器的4个通道同时捕获四路PWM波。 设计思路: 由于接收机输出的PWM波高电平最多就2ms,故可以让4个通道轮流使用定时器捕获PWM波 程序如下: include PWMin.h void TIM2_2PWMin_Init(u16 arr,u16 psc) { RCC- APB1ENR|=1 0; RCC- APB2ENR|=1 2; GPIOA- CRL&=0XFFFF0000; GPIOA- CRL|=0X0000
[单片机]
STM8单片机ADC采样功能通过定时器触发
  在使用STM8单片机的ADC功能时,读取ADC数据时一般有两种方式,一种是通常不断地读取采样标志位,来判断ADC采样是否结束,一种是通过中断的方式来通知系统采样是否结束。   有时候采样ADC数据的时候,需要按照一定的时间间隔,定点的去采样数据。一般使用的方式就是通过定时器定时,然后在定时中断函数中再去读取ADC采样的数据。但是这种方式采样的时间是不固定的,比如进入定时器中断后,ADC采样刚结束,就可以直接使用当前采样到的数据。但是如果运气不好的话,进入定时中断后,ADC采样刚开始,那么此时就需要等到ADC采样结束后,才能使用数据。这样就好导致每次读取ADC数据时还会有随机的一段等到ADC数据的延时。   通常查阅ST
[单片机]
STM8单片机ADC采样功能通过<font color='red'>定时器</font>触发
XMEGA128学习笔记11-定时器TC
特点有: 1、16位定时/计数 2、双缓冲定时器周期设置 3、高达4位比较或者捕获通道 4、波形产生 单脉冲/双脉冲/频率发生器 5、输入捕获 带噪声消除/频率捕获/脉宽捕获 6、32位输入捕获方向控制 7、定时器溢出/错误中断或者事件 8、每通道有一个比较匹配或者捕获中断/事件 9、支持DMA 10、高阻高精度扩展 Hi-Res 11、高级波形扩展AWeX 今天我们就使用定时器进行简单的LED灯闪烁,CVAVR设置如下: 编译后下载,就能看到LED0间隔1s闪烁。
[单片机]
XMEGA128学习笔记11-<font color='red'>定时器</font>TC
51单片机定时器实验
一.实验要求 由8031内部定时器1,按方式1工作,即作为16位定时器使用每0.05秒钟T1溢出中断一次。P1口的P1.0-P1.7分别接八个发光二极管。要求编写程序模拟一时序控制装置。开机后第一秒钟L1,L3亮,第二秒钟L2,L4亮,第三秒钟L5,L7亮,第四秒钟L6,L8亮,第五秒L1,L3,L5,L7亮,第六秒钟L2,L4,L6,L8亮,第七秒钟八个二极管全亮,第八秒钟全灭,以后又从头开始,L1,L3亮,然后L2,L4亮......一直循环下去。 二.实验目的 1.学习8031内部计数器的使用和编程方法。 2. 进一步掌握中断处理程序的编程方法。 三.实验电路及连线 P1.0--P1.7 接 L1--
[单片机]
51单片机<font color='red'>定时器</font>实验
不用定时器和汇编语言,只用C语言实现精确无误的延时
对于51定时器,却是有点少,有时候不经意间就被用完了,而实现定时又TM神坑了!一般的解决方案有直接上汇编,一条语句的执行时间就是一个机器周期,所以多写几个就实现了完美的定时功能。可是可是……..又有多少学51的会汇编呢?呵呵哒 所以来分享一个神好用的方法,C语言的while和nop结合使用实现精确延时 上调试代码: #include #include #define TIME 164//此处是需要不断调节的改变时间的数值 //164是少4个机器周期,165是多了2个机器周期 /* ∵晶振=12MHz ∴一条指令用时=1/(12/12)=10^(-6)s=1us */ //想办法补偿,而不是减少 void del
[单片机]
不用<font color='red'>定时器</font>和汇编语言,只用C语言实现精确无误的延时
stm32f103定时器中断
stm32为我们提供了8个定时器,分为:通用是定时器(TIM2~TIM5),高级定时器(TIM1和TIM8),基本定时器(TIM6和TIM7)。 至于三者之间的区别可以参考以下博客:https://blog.csdn.net/dukai392/article/details/72058041 本次我们主要讨论的是通用定时器的基本知识以及更新中断的配置过程。 通用定时器框图如下: 由于stm32的定时器十分复杂,功能特多而本次我们只讨论他的计数跟新功能(定时)。 时钟的选择: 由框图中红色部分可知定时器的时钟来源有三个:内部时钟(CK_INT),外部时钟(TIMx_ETR),其他定时器的时钟(ITR0-ITR
[单片机]
stm32f103<font color='red'>定时器</font>中断
LPTIM低功耗定时器有哪些独特功能?
1写在前面 在早些年,可能较少听见LPTIM这个名词。随着低功耗产品需求越来越严格,MCU厂商就推出了针对低功耗应用的LPTIM定时器。 定时器是我们常见的一种外设,之所以这么常见,原因在于定时器的用途非常广泛。 在STM32所有MCU中都配有定时器,那么你有关注、对比过各系列,各型号MCU中定时器的差异吗? 2哪些STM32配有LPTIM定时器 在STM32中,相对较新推出的MCU部分型号配有LPTIM定时器。 比如:STM32F7、H7高性能MCU,STM32L0、 L4低功耗MCU,以及最新推出的G0系列中配有这种LPTIM定时器。 具体哪些MCU配有LPTIM,大家可以下载对应的数据手册查看。
[单片机]
LPTIM低功耗<font color='red'>定时器</font>有哪些独特功能?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved