赞
踩
STM32F4系统定时器SYSTick是属于内核CM4的一个外设,内嵌在NVIC中。所有基于CM4的单片机都具有这个系统定时器,使得软件能够在CM4单片机中可以很容易的移植。
系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK。当重装载数值寄存器的值递减到0时,系统定时器就产生一个中断,以此循环往复。
SYSTick系统定时器有四个寄存器。在使用SYSTick产生定时时,一般只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
CTRL SYSTick控制及状态寄存器
LOAD SYSTick重装载数值寄存器
VAL SYSTick当前数值寄存器
CALIB SYSTick校准数值寄存器
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);
- }
- }
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--;
- }
- }
中断服务程序中修改的供其它程序检测的变量需要加volatile(即__IO)。
volatile(即__IO) 告诉编译器变量是随时可能发生变化的,每次使用它的时候必须从变量的地址中读取,因而编译器生成的可执行码会重新变量的地址读取数据。而如果没有使用__IO,编译器优化做法是,由于编译器发现两次从i中读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中,而不是重新从i里面读。
确定系统时钟配置的系统频率SYSCLK或HSECLK。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。