SysTick讲解
前言
SysTick—系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。为操作系统服务。
放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
系统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。
1.SysTick 寄存器介绍
SysTick—系统定时器有 4 个寄存器。使用 SysTick 产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
1.1 CTRL SysTick 控制及状态寄存器
1.2 LOAD SysTick 重装载数值寄存器
1.3 SysTick 当前数值寄存器
1.4 SysTick 校准数值寄存器
统定时器的校准数值寄存器在定时实验中不需要用到。有关各个位的描述这里引用手册里面的英文版本,比较晦涩难懂,暂时不知道这个寄存器用来干什么。
2.SysTick 定时时间计算
t:一个计数循环的时间,跟reload和CLK有关
CLK:72M或者9M,由CTRL寄存器配置
RELOAD:24位,用户自己配置
t = reload*( 1/clk )
Clk = 72M时,t = (72) *(1/ 72 M )= 1US
Clk = 72M时,t = (72000) *(1/ 72 M )= 1MS
时间单位换算:
1s = 1000ms = 1000 000 us = 1000 000 000ns
3.SysTick 寄存器结构体
在固件库文件:core_cm3.h中定义
这里注意,配置结构体,其实就相当于配置寄存器。
4.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);
}
5.函数设计
5.1 微秒延时函数
void SysTick_Delay_us(uint32_t us)
{
uint32_t i;
SysTick_Config(72);
for(i=0; i<us; i++)
{
while( !((SysTick->CTRL) & (1<<16)) );
}
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
5.1 毫秒延时函数
void SysTick_Delay_ms(uint32_t ms)
{
uint32_t i;
SysTick_Config(72000);
for(i=0; i<ms; i++)
{
while( !((SysTick->CTRL) & (1<<16)) );
}
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
后记
可以实现灯的精确闪烁:
main.c:
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>
#include "bsp_led.h"
#include "bsp_systick.h"
void Delay( uint32_t count )
{
for(; count!=0; count--);
}
int main(void)
{
// 来到这里的时候,系统的时钟已经被配置成72M。
LED_GPIO_Config();
while(1)
{
//GPIO_SetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);
LED_G(OFF);
//Delay(0xFFFFF);
SysTick_Delay_ms(500);
//GPIO_ResetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN);
LED_G(ON);
//Delay(0xFFFFF);
SysTick_Delay_ms(500);
}
}