SysTick 简介
SysTick—系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。
因为 SysTick 是属于 CM3 内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,使得软件在 CM3 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
SysTick 寄存器介绍
SysTick—系统定时器有 4 个寄存器,简要介绍如下。在使用 SysTick 产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
寄存器名称 | 寄存器描述 |
---|---|
CTRL | SysTick控制及状态寄存器 |
LOAD | SysTick重装载值寄存器 |
VAL | SysTick当前数值寄存器 |
CALIB | SysTick校准数值寄存器 |
SysTick控制及状态寄存器
SysTick重装载值寄存器
SysTick当前数值寄存器
SysTick校准数值寄存器
系统定时器的校准数值寄存器在定时实验中不需要用到。有关各个位的描述这里引用手册里面的英文版本,比较晦涩难懂。
SysTick 定时时间计算
T = reload * (1/clk)
Clk = 72M时, T = (72) * (1/72M) = 1us
Clk = 72M时, T = (72000) * (1/72M) = 1ms
SysTick 定时实验
利用 SysTick 产生 1ms/us 的时基,LED 以自己设定的值(ms/us) 的频率闪烁。
硬件材料
SysTick 属于单片机内部的外设,不需要额外的硬件电路,剩下的只需一个 LED 灯即可。可以使用开发板上自带的LED灯,我这里用的是正点原子的战舰,stm32f103无论何家的都能使用。
软件设计
SysTick 配置函数在固件库里面core_cm3.h 中,可以找到整个函数,无需修改。
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// 判断 tick 的值是否大于 2^24,如果大于,则不符合大于
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
//初始化reload寄存器的值
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
//配置中断优先级,配置为15,默认为最低优先级
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
//初始化 counter的值位0
SysTick->VAL = 0;
//配置 systick 的时钟为 72M
//使能中断
//使能systick
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
systick.c
#include "systick.h"
#include "misc.h"
#if 0
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// 判断 tick 的值是否大于 2^24,如果大于,则不符合大于
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
//初始化reload寄存器的值
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
//配置中断优先级,配置为15,默认为最低优先级
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
//初始化 counter的值位0
SysTick->VAL = 0;
//配置 systick 的时钟为 72M
//使能中断
//使能systick
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
#endif
/*实现微秒级的延时*/
void sysTick_Delay_us(uint32_t us)
{
uint32_t i;
SysTick_Config(72);//这是根据系统时钟频率
for(i = 0; i < us; i++){
while( !(SysTick->CTRL) & 1<<16);//1和1&还是1,当这个位为1的时候表示计数完毕,跳出循环
}
}
/*实现毫秒级的延时*/
void sysTick_Delay_ms(uint32_t ms)
{
uint32_t i;
SysTick_Config(72000);//72,ms就是要*1000
for(i = 0; i < ms; i++){
while( !(SysTick->CTRL) & 1<<16);//1和1&还是1,当这个位为1的时候表示计数完毕,跳出循环
}
}
main.c
#include "systick.h"
#include "led.h"
int main()
{
LED_Init();
while(1){
LED0 = 0;
sysTick_Delay_us(50000);
LED0 = 1;
sysTick_Delay_us(50000);
}
}
!!!!!!切记!!!!!!
一定要在你自己编写文件的.h文件中加上
#include "stm32f10x.h"
我这边是systick.h
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include "stm32f10x.h"
#include "core_cm3.h"
void sysTick_Delay_us(uint32_t us);
void sysTick_Delay_ms(uint32_t ms);
#endif /* __SYSTICK_H */
不然会报如下错误