打印
[资料分享]

STM32F103 systick定时器精确延时及仿真验证

[复制链接]
1842|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 fengxu0217 于 2019-1-3 13:20 编辑

    SysTick—系统定时器是属于CM3内核中的一个外设,内嵌在NVIC中。系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK,一般我们设置系统时钟SYSCLK等于72M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。
      SysTick—系统定时有4个寄存器,简要介绍如下。在使用SysTick产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
寄存器名称
寄存器描述
CTRL
SysTick控制及状态寄存器
LOAD
SysTick重装载数值寄存器
VAL
SysTick当前数值寄存器
CALIB
SysTick校准数值寄存器



SysTick控制及状态寄存器:[size=13.3333px]CTRL
位段     
名称                  
类型      
复位值     
描述
16
COUNTFLAG
R/W
0
如果在上次读取本寄存器后, SysTick 已经计到
了 0,则该位为 1。
2
CLKSOURCE
R/W
0
时钟源选择位,0=AHB/8,1=处理器时钟AHB
1
TICKINT
R/W
0
1=SysTick倒数计数到 0时产生 SysTick异常请
求,0=数到 0 时无动作。也可以通过读取COUNTFLAG标志位来确定计数器是否递减到0
0
ENABLE
R/W
0
SysTick 定时器的使能位



SysTick 重装载数值寄存器 :LOAD
位段  
名称
类型  
复位值  
描述
23:0
RELOAD
R/W
0
当倒数计数至零时,将被重装载的值



我们只需要熟悉以上两个寄存器即可编写延时nus及nms的延时函数,代码如下:
-------------------------------------------------------------------------------------------
#include "stm32f10x.h"

RCC_ClocksTypeDef  RCC_Clocks;
/*******************************************************************************
** 函数名称:Systick_delay_us
** 功能描述: 利用systick定时器延时nus,不触发中断,调用前需要先调用RCC_GetClocksFreq( &RCC_Clocks);获取系统时钟
** 参数说明: nus: [输入] 延时多少us
** 返回说明: None
** 创建人员: GMM
** 创建日期: 2018-12-27
********************************************************************************/
void Systick_delay_us(u16 nus)
{
   SysTick->LOAD=nus*(RCC_Clocks.HCLK_Frequency/8/1000000);   //定时uns
   SysTick->VAL =0;
   SysTick->CTRL=0X01;
   while((SysTick->CTRL&0x00010000)==0);
}

/*******************************************************************************
** 函数名称:Systick_delay_ms
** 功能描述: 利用systick定时器延时nms,不触发中断,调用前需要先调用RCC_GetClocksFreq( &RCC_Clocks);获取系统时钟
** 参数说明: nms: [输入] 延时多少ms
** 返回说明: None
** 创建人员: GMM
** 创建日期: 2018-12-27
********************************************************************************/

void Systick_delay_ms(u16 nms)
{
   SysTick->LOAD=nms*(RCC_Clocks.HCLK_Frequency/8/1000);   //定时nms
   SysTick->VAL =0;
   SysTick->CTRL=0X01;
   while((SysTick->CTRL&0x00010000)==0);
}

int main(void)          // 0000 0000 01000000=0x0040
{  
   RCC_GetClocksFreq( &RCC_Clocks);  
   while(1)
    {
       Systick_delay_us(1);
       Systick_delay_us(1000);  
       Systick_delay_ms(1);
       Systick_delay_ms(1000);        
    }
}
----------------------------------------------------------------------------------------------------------

    以上为两个us和ms的延时函数,因为在main函数中使用了RCC_GetClocksFreq( &RCC_Clocks);  来获取系统时钟,所以无论系统时钟是72MHz,还是8MHz或者其他任意频率,均可通过上面两个函数获得精确的延时时间。
    另外,没有使能systick的中断,因此,使用方法与for循环实现延时的使用方法方式完全一样。


1.jpg (125.07 KB )

1.jpg

相关帖子

沙发
gavinpeng2| | 2019-1-4 10:30 | 只看该作者
个人风格不一样,我一般用systick做定时器了。
如果是延时我喜欢直接while循环里面套点自增运算NOP()之类的,至于里面套多少内容就直接用逻辑分析仪或者示波器测点灯

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

70

帖子

0

粉丝