当前位置:   article > 正文

STM32系统定时器

stm32系统定时器

一、系统定时器

1. 简介

        SysTick 叫做系统滴答时钟、系统定时器,属于 Cortex-M4 内核中的一个外设(外围设备),并且是24bit向下递减的计数器。

《STM32中文参考手册》P108

RCC 向 Cortex 系统定时器 (SysTick) 馈送 8 分频的 AHB 时钟 (HCLK)。SysTick 可使用此时钟作为时钟源,也可使用 HCLK 作为时钟源。

https://note.youdao.com/yws/public/resource/b994246549f84052c3cad3ea416ccf64/xmlnote/53190316F07F4BF89AC603CD0635DEF2/639B7924744B442093CEE0D1112D7B7A/59212

具体可在 SysTick 控制和状态寄存器中配置。

注意:

  • 定时器的位数越多,定时时间更长。
  • 通过计数值间接计算定时时间,不能像操作系统直接调用函数实现延时或定时功能。

计数值,就是要进行多少个计数。

2.工作原理

https://note.youdao.com/yws/public/resource/b994246549f84052c3cad3ea416ccf64/xmlnote/53190316F07F4BF89AC603CD0635DEF2/1AE1DD465D634468BACB32279F081AEA/41888

3.频率的概念

https://note.youdao.com/yws/public/resource/b994246549f84052c3cad3ea416ccf64/xmlnote/53190316F07F4BF89AC603CD0635DEF2/2F6907161ED1476E994BDD51CB4E6268/38840

物质在1s内完成周期性变化的次数叫做频率,常用f表示。为了纪念德国物理学家赫兹的贡献,人们把频率的单位命名为赫兹,简称“赫”,符号为HZ。

周期与频率的关系:f=1/T。(其中f为频率,T为周期)。

周期,物体作往复运动或物理量作周而复始的变化时,重复一次所经历的时间。物体或物理量(如交变电流、电压等)完成一次振动(或振荡)所经历的时间。

二、库函数

参考文档:《Cortex M3与M4权威指南.pdf》第314页

1.系统定时器配置

/** \brief System Tick Configuration

The function initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts.

\param [in] ticks Number of ticks between two interrupts.

\return         0 Function succeeded.

\return         1 Function failed.

\note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b> must contain a vendor-specific implementation of this function.

*/

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)

示例:

//系统定时器触发1KHz的中断,中断周期时间T= 1/f = 1000ms/1000=1ms

//系统定时器连接到PLL输出的168MHz时钟,就是1秒内产生脉冲的个数为168000000。

//只要系统定时器进行168000000次计数,就是1秒时间的到达

//只要系统定时器进行168000次计数,就是1ms时间的到达

//只要系统定时器进行168次计数,就是1us时间的到达 SysTick_Config(SystemCoreClock/1000);

SysTick_Config(168000);

注:若发现定时不准确,检查PLL配置是否正确。

三、最大定时时间

1.确定最大的计数值2^24 -1,若计算到0,则进行2^24次计数。

1000ms                 Tmax

--------         =         --------

168000000            2^24

Tmax = 2^24 *1000ms/168000000 = 99.86ms。

2.测试结果

初始化系统定时器,1S 内核触发 1000 次中断,说白了定时 1ms,能够成功

SysTick_Config(SystemCoreClock/1000);

初始化系统定时器,1S 内核触发 10 次中断,说白了定时 100ms,现象失败

SysTick_Config(SystemCoreClock/10);

初始化系统定时器,1S 内核触发 11 次中断,说白了定时 90.90ms,能够成功

SysTick_Config(SystemCoreClock/11);

总结:填写中断频率值不能小于11,否则定时时间不准确。

SysTick_Config(SystemCoreClock/11);

四、延时函数

1.系统定时器的用途

  • 没有操作系统:只用于延时
  • 有操作系统(ucos2 ucos3 freertos....):为操作系统提供精准的定时中断(1ms~50ms)

2.官方示例

参考文档:《Cortex M3与M4权威指南.pdf》第314页

In many cases you might not want to use the SysTick_Config function because you might want to use the reference clock or you might not want to enable the SysTick interrupt. In these cases you need to program the SysTick registers directly,and the following sequence is recommended:

1). Disable the SysTick timer by writing 0 to SysTick->CTRL. This step is optional.It is recommended for reusable code because the SysTick could have been enabled previously.

2). Write the new reload value to SysTick->LOAD.

3). Write to the SysTick Current Value register SysTick->VAL with any value to clear the current value to 0.

4). Write to the SysTick Control and Status register SysTick->CTRL to start the SysTick timer.

参考文档:《Cortex M3与M4权威指南.pdf》第316页

If you want to use the SysTick timer in polling mode, you can use the count flag in the SysTick Control and Status Register (SysTick->CTRL) to determine when the timer reaches zero. For example, you can create a timed delay by setting the SysTick timer to a certain value and waiting until it reaches zero:

SysTick->CTRL = 0; // Disable

SysTick SysTick->LOAD = 0xFF; // Count from 255 to 0 (256 cycles)

SysTick->VAL = 0; // Clear current value as well as count flag SysTick->CTRL = 5; // Enable SysTick timer with processor clock while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set SysTick->CTRL = 0; // Disable SysTick

3.寄存器

https://note.youdao.com/yws/public/resource/b994246549f84052c3cad3ea416ccf64/xmlnote/53190316F07F4BF89AC603CD0635DEF2/0F9E15FFD47B4F32A845EA99CB9C5A26/41880

https://note.youdao.com/yws/public/resource/b994246549f84052c3cad3ea416ccf64/xmlnote/53190316F07F4BF89AC603CD0635DEF2/CC749DDD84974BA3977B2EFD8B33DEC3/41885

https://note.youdao.com/yws/public/resource/b994246549f84052c3cad3ea416ccf64/xmlnote/53190316F07F4BF89AC603CD0635DEF2/A37EA4591C74404D89AD07964228304E/41882

 4.毫秒与微秒级延时函数

void delay_ms(uint32_t ms)

{

        while(ms --)

        {

                SysTick->CTRL = 0; // 关闭系统定时器后才能配置寄存器

                SysTick->LOAD = 21000; // 设置计数值,用于设置定时的时间

                SysTick->VAL = 0; // 清空当前值还有计数标志位

                SysTick->CTRL = 1; // 使能系统定时器工作,且时钟源为系统时钟的8分频(168MHz/8=21MHz)

                while ((SysTick->CTRL & (1<<16))==0); // 等待系统定时器计数完毕

                SysTick->CTRL = 0; // 关闭系统定时器

        }

}

void delay_us(uint32_t n)

{         

        SysTick->CTRL = 0; // 关闭系统定时器

        SysTick->LOAD = n*168-1; // 168000000/1000000 -1,每次延时1us

        SysTick->VAL = 0; //清空val寄存器 还有清空COUNTFLAG标志位

        SysTick->CTRL = 5; // 使能系统定时器工作,而它的时钟源为处理器时钟168MHz         

        while ((SysTick->CTRL & 0x00010000)==0);// 等待系统定时器计数完毕

        SysTick->CTRL = 0; // 关闭系统定时器

}

5.微秒和毫秒延时的优化[拓展]

官方代码没有想到意外关闭的问题

int32_t delay_us(uint32_t nus)

{

        uint32_t temp;

       

        SysTick->CTRL = 0;

        SysTick->LOAD = (nus*21)-1;

        SysTick->VAL = 0;

        SysTick->CTRL = 1;

        while(1)

        {

                temp=SysTick->CTRL;

        

                //检测count flag

                if(temp & 0x00010000)

                        break;

                //检测系统定时器是否意外关闭

                if((temp & 0x1)==0)

                        return -1;

        }

        SysTick->CTRL = 0;

        return 0;

}

int32_t delay_ms(uint32_t nms)

{

        uint32_t t = nms;

        uint32_t temp;

        while(t--)

        {

                SysTick->CTRL = 0;

                SysTick->LOAD = 21000-1;

                SysTick->VAL = 0;

                SysTick->CTRL = 1;

                while(1)

                {         

                        temp=SysTick->CTRL;

                        

                        //检测count flag i

                        f(temp & 0x00010000)

                                break;

                        //检测系统定时器是否意外关闭

                        if((temp & 0x1)==0)

                                return -1;

                }

        }

        SysTick->CTRL = 0;

        

        return 0;

}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/942248
推荐阅读
相关标签
  

闽ICP备14008679号