SysTick——系统定时器(标准库)

STM32F4的SYSTick是一个24位的系统定时器,常用于操作系统的时基,产生中断。配置涉及CTRL、LOAD和VAL寄存器,通过SysTick_Config()库函数设置。中断优先级默认最低,可通过NVIC_SetPriority()调整。文章还介绍了SYSTick中断时间的计算方法和注意事项,如使用volatile修饰中断服务程序中的变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、STM32F4的SYSTick定时器

STM32F4系统定时器SYSTick是属于内核CM4的一个外设,内嵌在NVIC中。所有基于CM4的单片机都具有这个系统定时器,使得软件能够在CM4单片机中可以很容易的移植。

系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。

系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK。当重装载数值寄存器的值递减到0时,系统定时器就产生一个中断,以此循环往复。

2、SYSTick的寄存器

SYSTick系统定时器有四个寄存器。在使用SYSTick产生定时时,一般只需要配置前三个寄存器,最后一个校准寄存器不需要使用。

   CTRL              SYSTick控制及状态寄存器

   LOAD             SYSTick重装载数值寄存器

   VAL                 SYSTick当前数值寄存器

   CALIB             SYSTick校准数值寄存器

3、SYSTick配置库函数

(1)库函数解析

SYSTick是属于内核的外设,有关的寄存器定义和库函数都在内核相关的库文件core_cm4.h中。

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks);

使用固件库编程的时候,我们只需要调用库函数SysTick_Config()即可。

        形参ticks用来设置重装载数值寄存器的值,最大值为2^24 = 16777216。

        返回值  0,设置成功    1,设置失败。

SysTick_Config()库函数主要配置了SYSTick中的三个寄存器:LOAD/VAL/CTRL。其中还调用了NVIC_SetPriority()来配置系统定时器的中断优先级。由于SYSTick属于内核外设,跟普通外设的中断优先级有区别,并没有抢占优先级和子优先级的说法。在STM32F407中,内核外设的中断优先级由内核SCB这个外设的寄存器:SHPPx(x = 1,2,3)来配置。在STM32F407中,只有高四位有效,中断优先级可编程为0~15,只有16个可编程优先级。

        标准库的函数原型:

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    
                                              /* Reload value impossible */

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                        
                                              /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); 
                                             /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                            
                                            /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         
                                           /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     
                                           /* Function successful */
}

在系统定时器中,配置优先级为 (1UL « __NVIC_PRIO_BITS) - 1UL),其中宏 __NVIC_PRIO_BITS 为 4,那计算结果就等于 15,可以看出系统定时器此时设置的优先级在内核外设中是最低的。

  #ifndef __NVIC_PRIO_BITS
    #define __NVIC_PRIO_BITS          4
    #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
  #endif

SYSTick初始化函数由用户自己编写,里面调用了SysTick_Config()这个固件函数,通过设置该函数的形参,就决定了系统定时器经过多少时间就产生一次中断。

void SysTick_Init(void)
{
    if(SysTick_Config(SystemCoreClock/100000))   //10us
    {
        while(1);
    }
} 

(2)SYSTick相关计算

SYSTick中断时间计算

SYSTick定时器的计数器是向下递减计数的,计数一次时间 T = 1/AHBCLK

当重载寄存器中的值VALUE减到0的时候,产生中断。

中断一次的时间 T=VALUE/AHBCLK。

如果AHBCLK设置为168MHz,VALUE值设置为168,则中断时间为1us。

VALUE值设置为1680,则中断时间为10us.

VALUE值设置为168000,则中断时间为1ms。

static __IO uint32_t TimingDelay;

void systick_init(void)
{
	//初始化SYSTick产生一次中断的时间
	while(SysTick_Config(168000)!=0);//1ms产生一次中断
	
}

//计时程序 nTime*1ms
void Time_us(uint32_t nTime)
{ 
	if(TimingDelay == 0)
	{
		TimingDelay = nTime;
		GPIO_ToggleBits(GPIOF,GPIO_Pin_9);
	}

}
//在 SysTick 中断函数 SysTick_Handler()进行计数
void TimingDelay_Decrement(void)
{
	if (TimingDelay != 0x00)
	{ 
		TimingDelay--;
	}
}

3、注意事项

中断服务程序中修改的供其它程序检测的变量需要加volatile(即__IO)。

volatile(即__IO) 告诉编译器变量是随时可能发生变化的,每次使用它的时候必须从变量的地址中读取,因而编译器生成的可执行码会重新变量的地址读取数据。而如果没有使用__IO,编译器优化做法是,由于编译器发现两次从i中读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中,而不是重新从i里面读。

确定系统时钟配置的系统频率SYSCLK或HSECLK。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星顶照

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值