一、Systick简介
二、Systick timer
三、相关寄存器介绍
除了上面说的STK_VAL,下面带大家了解相关的寄存器和寄存器位。
1. SysTick_CSR 控制状态寄存器
Bit1: TICKINT
Bit2: CLKSOURCE
Bit16:COUNTFLAG
2. SysTick_LOAD
0-23 24位的重装值,这也是为什么只能计数到2^24
3. SysTick_VAL 当前值寄存器
4. SysTick_CALRB 校准寄存器
由于我们要写精确延时的LED流水灯,所以我们需要使用Systick进行精确延时,理论上它的最小计时单位为AHB的时钟周期,1/72000000秒,72分之一微秒。
我们在昨天流水灯的基础上,新建两个文件,SysTick.c和SysTick.h
具体代码如下
SysTick.h
#ifndef __SYSTICK_H__
#define __SYSTICK_H__
#include "stm32f10x.h"
#define __SYSTICK_H__
#include "stm32f10x.h"
void SysTick_Init(void);
void Delay_us(__IO u32 nTime);
#endif
SysTick.c
#include "SysTick.h"
#include "stm32f10x.h"
#include "stm32f10x.h"
static __IO u32 TimingDelay;
void SysTick_Init(void)
{
if(SysTick_Config(SystemCoreClock/100000))
{
while(1);
}
//关闭滴答定时器
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
{
}
void TimingDelay_Decrement(void)
{
if(TimingDelay != 0x00)
{
TimingDelay--;
}
}
{
}
void Delay_us(__IO u32 nTime)
{
TimingDelay = nTime;
//使能滴答定时器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(TimingDelay != 0);
}
{
}
中断函数,在stm32f10xit.c
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
{
}
修改main.c如下
#include "stm32f10x.h"
#include "led.h"
#include "SysTick.h"
#include "led.h"
#include "SysTick.h"
int main(void)
{
}
这里面只有两个函数,SysTick_Init()和Delay_us(),一个是配置SysTick定时器,一个是进行精确延时
中断函数也只是运行了一个自定义函数,看看不难理解
SysTick_Config(SystemCoreClock/100000);
SystemCoreClock是系统时钟的宏,SystemCoreClock = 72000000
我们的计时总时间 T = tick * (1/f),tick为SysTick_Config()的输入参数
1/f为SysTick timer使用的时钟源的时钟周期,f为该时钟源的时钟频率。
上面的语句中:tick = SystemCoreClock/100000=720,表示720个时钟周期中断一次,1/f是时钟周期的时间,1/f = 1/72us,所以T = 720*(1/72) = 10us
SysTick_CTRL_ENABLE_Msk,这是一个宏,用来指示寄存器的特定位置或进行位屏蔽用的,那么他是如何定义的呢?

其中的寄存器位指示宏:SysTick_xxx_Pos,
寄存器的位屏蔽宏:SysTick_xxx_Msk,宏展开是xxx的位全部置1后,左移SysTick_xxx_Pos位,1ul使之无符号长整型,上图中SysTick_CTRL_CLKSOURCE_Msk,宏展开为1ul<<SysTick_CTRL_CLKSOURCE_Pos,即1左移2位,得到的只有Bit2:CLKSOURCE位被置1,而其它位为0,这样搭配& | 能够很方便的修改寄存器的某些位,这样就程序就不难理解了.就说这么多吧,已经讲得很多了,不懂得自己想想,琢磨一下就通了。