历史上的今天
返回首页

历史上的今天

今天是:2024年12月03日(星期二)

正在发生

2021年12月03日 | STM32 SysTick定时器和delay延迟函数

2021-12-03 来源:eefocus

一,什么是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();


 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文件中)


 Systick中断服务函数:

void SysTick_Handler(void);


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;

}

推荐阅读

史海拾趣

Altitude Technology公司的发展小趣事

随着产品的不断升级和市场的不断扩大,Altitude Technology开始将目光投向海外市场。公司制定了详细的市场拓展计划,通过参加国际电子展会、建立海外销售渠道等方式,积极推广自己的产品。经过一番努力,Altitude Technology的产品逐渐在国际市场上获得了认可,公司的知名度也得到了提升。

Device Engineering Incorporated公司的发展小趣事

在电子行业快速发展的背景下,DEI公司意识到只有不断创新才能保持竞争力。因此,公司加大了对研发的投入,积极引进新技术和人才。通过不断的努力,DEI公司成功推出了一系列具有自主知识产权的创新产品,涵盖了多个领域。这些产品不仅提升了公司的竞争力,也为公司赢得了更多的市场份额。

Bud Industries公司的发展小趣事

在发展过程中,DEI公司也遇到了不少挑战。如市场竞争日益激烈、技术更新换代加快等。然而,DEI公司始终保持着冷静和清醒的头脑,积极应对各种挑战。他们通过加强内部管理、优化产品结构、拓展新的业务领域等方式,不断提高自身的适应能力和竞争力。这些努力使得DEI公司在电子行业中始终保持领先地位,实现了持续稳定的发展。

ALLEN BRADLEY公司的发展小趣事

在发展过程中,DEI公司也遇到了不少挑战。如市场竞争日益激烈、技术更新换代加快等。然而,DEI公司始终保持着冷静和清醒的头脑,积极应对各种挑战。他们通过加强内部管理、优化产品结构、拓展新的业务领域等方式,不断提高自身的适应能力和竞争力。这些努力使得DEI公司在电子行业中始终保持领先地位,实现了持续稳定的发展。

科通(COMTEK)公司的发展小趣事

随着公司业务的不断拓展,科通技术开始与国际知名品牌展开合作。通过与Xilinx、Intel、SanDisk等全球领先的芯片原厂建立紧密的合作关系,科通技术获得了这些品牌的产品线授权,并为其在中国市场的拓展提供了有力的支持。这些合作不仅提升了科通技术的品牌影响力,也为其带来了更多的市场机会。

ABCO公司的发展小趣事

ABCO公司深知产品质量是企业生存的根本。因此,公司建立了一套严格的质量管理体系,从原材料采购到产品生产、检测、出厂等各个环节都进行严格把控。同时,公司还注重持续改进,不断优化生产流程,提高生产效率,确保产品质量始终保持在行业前列。

问答坊 | AI 解惑

CPU与DSP的区别

从表面上来看,DSP与标准微处理器有许多共同的地方:一个以ALU为核心的处理器、地址和数据总线、RAM、ROM以及I/O端口,从广义上讲,DSP、微处理器和微控制器(单片机)等都属于处理器,可以说DSP是一种CPU。但DSP和一般的CPU又不同: 首先是体系结 ...…

查看全部问答>

关于18B20多点测温的研究

一个18B20测量温度想必大家都学过了,不知道大家有没有做过多个串在一起的18B20的测温?在网上找这样的程序很难找到,找到了也是不完整的或者收费才能下的,因此我花了两个星期才实验成功。现在上传,希望能对各位有所帮助。由于手头上只有2个18B20 ...…

查看全部问答>

多路输出开关电源的设计及应用原则

对现代电子系统,即便是最简单的由单片机和单一I/O 接口电路所组成的电子系统来讲,其电源电压一般也要由+5V,±15V或±12V等多路组成,而对较复杂的电子系统来讲,实际用到的电源电压就更多了。 目前主要由下述诸多电压组合而成:+3.3V,+5V, ...…

查看全部问答>

如何用短信猫接收状态报告???

在网上找了很久,发现都不可用,我是移动的猫, 在执行SIM卡的STK菜单发送短信后,希望能接收到移动的状态报告。 at+cnmi=1,1,0,1,1 at+cnmi=2,1,0,1,1 这两个都不行吗,在发完短信后,用它们去检测设备是否接收到状态报告,可什么也没接到? ...…

查看全部问答>

请问如何混沌序列被量化为二进制序列的那个量化函数的定义是什么?要详细的,讲的尽量清楚些,谢谢高手专家了!!!

请问如何混沌序列被量化为二进制序列的那个量化函数的定义是什么?要详细的,讲的尽量清楚些,谢谢高手专家了!!!…

查看全部问答>

可用U盘看节目的DVD机原理

其实是借用DVD机的功能,将U盘插在DVD机的USB接口上,通过DVD机读入U盘上节目,从电视上看U盘上的内容。 1,原理?  2,有没有现成的成品改装老的DVD\\VCD?  3,可否扩展用硬盘看节目?…

查看全部问答>

求职: 请问有没有人需要高级WINCE工程师--限深圳地区!

求职: 请问有没有人需要高级WINCE工程师--限深圳地区! 谢了!…

查看全部问答>

如何把PWM输出的3.3V转化成5V?

由于驱动模块需要5V才能够驱动,如何把PWM输出的3.3V转化成5V?…

查看全部问答>

为什么在FatFs文件系统下写文件会出现这个问题?

我把FatFs 移植到LPC1114上以后,给一个文件写内容:比如给SD卡里面的“ration.txt”文件写512个字母d,结果是在“ration.txt”里面出现了如下现象! (注意:文件头从下面字母g前面的一个空格开始)     g  T ddddd ...…

查看全部问答>

不明白出D题的所谓砖家是否被砖拍了

本帖最后由 paulhyde 于 2014-9-15 03:58 编辑 3.6V 不说 还100ma 还不说 还15M 明摆着用拼学校老师的实力吗  …

查看全部问答>