STM32笔记——系统定时器SysTick

本文详细介绍了STM32的SysTick系统时钟配置,包括如何设置重装载寄存器、中断优先级、时钟源和使能定时器。SysTick作为内核外设,其中断优先级不同于普通外设,不涉及抢占和子优先级。文章还讨论了当SysTick与片上外设中断同时使用时的优先级设置,并提供了计算中断时间和实现简单延时的方法。此外,文章提到了利用SysTick的COUNTFLAG位进行软件查询实现延时的编程方式。
摘要由CSDN通过智能技术生成

SysTick

——系统时钟都是属于CM3内核的一个外设,内核在NVIC中。系统定时器的时钟是一个24位向下递减的计数器,计数器每计数一次的时间为1/SYSTICK,一般我们设置系统时钟的等于72M,当重装载数值寄存器计数到0时,系统定时器就会产生一次中断,以此重复循环。

SysTick寄存器汇总

CTRL: SysTick控制及状态寄存器
LOAD: SysTick重装载数值寄存器
VAL: SysTick当前值寄存器
CALIB: SysTick校准数值寄存器

编程的要点:

1.配置重装载寄存器的值

2.清除当前值寄存器的值

3.配置控制及状态寄存器

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ //不可能的装载值,超出范围
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
  
   //设置重装载寄存器
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  
  //设置中断优先级
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */

//设置当前值寄存器
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */

//设置定时器的时钟源为AHBCLK=72MHz
//使能定时器中断
//使能定时器
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
                   
  return (0);                                                  /* Function successful */
}

形参ticks用来设置重装载寄存器的值,最大不能超过重装载寄存器的2的24次方。当重装载的值递减到0时产生中断,然后重装载寄存器的值又重新装载往下递减计数,以此循环往复。随后配置好中断优先级,最后配置系统定时器的时钟等于AHBCLK=72MHz,使能定时器和定时器中断,这样系统定时器的时钟就配置好了。
因为SysTick属于内核的外设,与普通外设的中断优先级有些区别,并没有抢占优先级和子优先级的说法。内核外设的中断优先级由内核SCB这个外设的寄存器SHPRx(x=1~3)来配置。
SPRH1是一个32位的寄存器,但是只能通过字节来访问,每8个字段控制一个内核外设的中断优先级设置。在STM32F103中,只有位7~位3这高四位有效,低四位没有用到,所以内核外设的中断优先级可编程为0到15,只有16个可编程优先级,数值越小,优先级越高。

但是,问题来了,如果同时使用了片上外设和SysTick呢?而且片上外设也刚好需要使用中断,那SysTick的中断优先级跟外设的中断优先级怎么设置?会不会因为SysTick是内核里面的外设,所以它的中断优先级就比内核外的中断优先级高呢?

外设在设置中断优先级的时候,首先要分组,然后还要设置抢占优先级和子优先级,而SysTick这类内核外设在配置的时候,只需要配置一个寄存器即可,取值范围为0~15,既然配置的方式不同那么如何区分两者的优先级,下面举例说明。

比如设置一个中断优先级分组为2,抢占优先级为1,子优先级也为1,SysTick的优先级为固件库默认配置的15.当我们比较内核外设和片上外设的中断优先级时,我们只需抓住NVIC中断优先级分组不仅对片上外设有效,对内核外设也有效这一点,把SysTick的优先级15转化成二进制的数1111,又因为NVIC的优先级分组为2,那么前两位的11(0b)就是3,后面两位的11(0b)也是3,。无论是抢占优先级还是子优先级,都比我们设定的片上外设的优先级低。如果当两个软件的优先级都配置成一样,那么就比较它们在中断向量表中的硬件编号,编号越小,优先级越高。

SysTick中断时间的计算

SysTick定时器的计数器是向下递减计数的,计数一次的时间为TDEC=1/CLKAHB ,当重装载寄存器中的值为VALUELOAD减到0的时候,产生中断,可知中断一次的时间为TINT=VALUELOAD*TDEC=VALUELOAD/CLKAHB,其中CLKAHB=72MHz。如果设置VALUELOAD为72,那中断一次的时间TINT=72/72M=1us。不过1us的中断没啥意义,整个程序的重心都花在进出中断上了,根本没有时间处理其他任务。

SysTick定时时间的计算

当设置好中断时间TINT后,我们可以设置一个变量t,用来记录进入中断的次数,那么变量t乘以中断的时间TINT就可以计算定时的时间了。

一种更加简洁的定时器编程

我们知道,SysTick的counter从reload值往下递减到0的时候,CTRL寄存器的为16:countflag会置1,且读取该位的值可以清0,所以我们可以使用软件查询的方式来实现延时。我敢肯定这样的写法初学者肯定喜欢,因为它直接,更容易了解。

void SysTick_Delay_Us(__IO uint32_t us)
{
	uint32_t i;
	SysTick _Config(SystemCoreClock/1000000);
	
	for(i=0; i<us; i++)
	{  /*	当计数器的值减到0时,CTRL寄存器的位16会置1  */
	  while(!((SysTick->CTRL)&(1<<16)));
	}
	SysTick->CTRL&=~ SysTick_CTRL_ENABLE_Msk; 
}

若有概念上的错误,欢迎在下方评论区改正!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

%Zero%

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

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

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

打赏作者

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

抵扣说明:

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

余额充值