SysTick延时
相关代码:
void delay_us(u32 uS) {
SysTick->LOAD=72*uS; //重装计数初值(当主频是72MHz,72次为1微秒)
SysTick->VAL=0x00; //清空定时器的计数器
SysTick->CTRL=0x05; //选择时钟源HCLK,打开定时器
while(!(SysTick->CTRL&0x10000)); //等待计数到0
SysTick->CTRL=0x04; //关闭定时器
//这个中断是由硬件自动触发的,不受软件控制
//因此,即使没有显式地设置打开总中断,SysTick 定时器的中断仍然会生效,因为它是由硬件触发的。
}
void delay_ms(u16 ms){ //mS毫秒级延时程序(参考值即是延时数,最大值65535)
while( ms-- != 0){
delay_us(1000); //调用1000微秒的延时
}
}
void delay_s(u16 s){ //S秒级延时程序(参考值即是延时数,最大值65535)
while( s-- != 0){
delay_ms(1000); //调用1000毫秒的延时
}
}
Systick是Cortex内核当中,中断寄存器的一部分,因此相关的函数以及寄存器介绍在Cortex-M3编程手册内可见,固件编程手册函数仅供参考。
由参考手册可知,SysTick寄存器由四个寄存器组成。我们只需要使用其中的3个寄存器:
STK_CTRL(控制及状态寄存器):
当CLKSOURCE为0时,则选择外部时钟源,即(stm32f103c8t6最小系统板外置晶振为8M,通过PLL倍频到72MHz)72MHz的8分频(AHB/8),在load装载初值时,计数72/8=9次即为1us。
当CLKSOURCE为1时,则选择内核时钟(72M),计数72次即为1us。
重装载数值寄存器(RELOAD):
当前数字寄存器(VAL):(用于中断)
校准数值寄存器(CALIB):
利用中断来实现对滴答定时器的配置:
- 滴答定时器是一个24位的倒计数定时器,当计数到0时,将从RELOAD寄存器中自动装载初值。
- 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
- 设置的定时时间 = RELOAD寄存器值 x 1/72M
- 例如RELOAD = 72000,则定时时间 = 72000 x 1/72M = 1ms
1、设置RELOAD需要通过SysTick_Config来设置:
- SysTick_Config(72000000/1000);
2、当定时时间到了之后,滴答定时器会产生中断
- 使用中断就需要打开总中断的开关,因此需要到core_cm3中找到控制总中断的函数__set_PRIMASK(0);使能总中断需要设置为0。
3、使用中断还需要对中断进行分组
- STM32F103内部有16个内核中断和60个可屏蔽(关闭)中断,具有16个级别的可编程的中断优先级
- 中断的分组需要用到NVIC-内嵌向量中断控制器
- 该控制器将中断一共分为五个组,分为组0-4
在misc中找到该函数:NVIC_PriorityGroupConfig();(NVIC优先级分组配置,一般参数填NVIC_PriorityGroup_2)
4、在进入滴答定时器完成计时后进入中断,我们还需要编写处理中断的中断处理函数。
- 该函数可在STM32的启动文件当中找到:SysTick_Handler(void);
- 当定时的时间到了之后,就会进入到该中断函数内。
滴答定时器的中断没有设置优先级,是因为滴答定时器的中断是在系统内核当中的,在系统内已经设置好了。
在SysTick_Config();函数当中已经通过配置寄存器设置了滴答定时器的中断优先级(1左移4位等于15)。
#include "SysTick.h"
u32 DelayTimer;
void SysTick_Init(void) {
//定时器装载初始值,装载72000即定时1ms,该函数位于core_cm3
SysTick_Config(72000000/1000);
//定时器会产生中断,所以需要打开总中断开关,该函数位于core_cm3
__set_PRIMASK(0);
//凡是使用中断都需要对中断设置分组,SysTick属于内核中断
//设置中断分组需要设置NVIC,一般设置为组2,函数位于misc
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
void SysTickDelayMs(u32 nms) {
DelayTimer = nms;
while(DelayTimer); //执行空语句
}
void SysTick_Handler(void) {
if(DelayTimer) DelayTimer--;
}