1、系统滴答定时器的概述

滴答定时器又称 SysTick,有两个时钟源,一个为内部时钟,一个为外部时钟。滴答定时器是一个 24 位倒计
数的定时器,从预装载值一直到 0,重装载寄存器的值会自动装载到计数寄存器中。 只要不把它使能位清除,那
么它就永远不停,即使在芯片在睡眠模式下也能工作。

2、滴答定时器的内部框图

iOS 息屏后 定时器 不准_数据寄存器

系统滴答定时器的是一个倒计数计数器,作用是:通过计数来定时。常用于:①操作系统的心跳时钟。②裸机代码中的简单定时。

STM32F407ZGT6的系统滴答定时器的计数频率为21MHZ或者为168MHZ。系统滴答定时器控制器有一个“自动重装载寄存器”,该寄存器是24位有效。

举例:假如系统滴答定时器的计数频率设置为21MHZ,定时1ms,需要计数21000,则将该值写入“自动重装载寄存器”。然后系统滴答定时器还有一个“当前值寄存器”,“当前值寄存器”加载“自动重装载寄存器”中的值,在每个时钟节拍下,“当前值寄存器”的置递减,递减到0,则定时时间到。

3、相关寄存器

详细资料在《Cortex M3 与 M4 权威指南》第 315 页

3.1、控制及状态寄存器(SysTick_CTRL

iOS 息屏后 定时器 不准_iOS 息屏后 定时器 不准_02

iOS 息屏后 定时器 不准_寄存器_03

举例:将滴答定时器的计数频率设置为21MHZ,禁止产生滴答中断,使能滴答定时器,如何配置?

SysTick->CTRL &=~(1<<2);

SysTick->CTRL &=~(1<<1);

SysTick->CTRL |= (1<<0);

3.2、自动重装载数据寄存器(SysTick_LOAD)

iOS 息屏后 定时器 不准_加载_04

只有低 24 位有效,数值有效范围为 0-(2^24-1)。 当 SysTick 定时器倒计数到 0 时,该寄存器的值就会把计
数初始值重新加载到计数器中工作。

举例1:将滴答定时器的计数频率设置为21MHZ,禁止产生滴答中断,使能滴答定时器,定时时间为1us,如何配置?

答1:

SysTick->CTRL &=~(1<<2);

SysTick->CTRL &=~(1<<1);

SysTick->LOAD = 0;        //清零

SysTick->LOAD = 21;       //计21次为1us

SysTick->CTRL |= (1<<0);

举例2:将滴答定时器的计数频率设置为21MHZ,禁止产生滴答中断,使能滴答定时器,最大定时时间是多少?

重装载数值寄存器的最大值是16777215,则最大定时时间是:(1/21000000)*16777215 = 0.798915秒。

3.3、当前值寄存器(SysTick_VAL)

iOS 息屏后 定时器 不准_加载_05

这个寄存器同样只有低 24 位有效, SysTick 定时器倒计数寄存器。读取时返回当前倒计数的值,对这个寄存
器进行写操作,则使之清零,并对到零标志位清零。
3.4. 设置延迟时间
由上面寄存器可知,定时器计数的周期为 SysTick-LOAD 寄存器的值和选择的时钟源有关。例如:选择时钟频
率为 24MHz 的时钟,即周期为 1/24000000s,所以假如要实现定时 1s,则需要设置装载值为 24000000(1s=
(1/24000000) *24000000)。同理可得 1ms 需要设置装载值为 21000, 1us 需要设置装载值为 21。
 

4、软件设计

寄存器

#include "stm32f4xx.h"
void delay_ms(int ms)
{
	SysTick->CTRL &=~(1<<2);//选择时钟源为21MHZ
	SysTick->CTRL &=~(1<<1);//禁止滴答中断
	SysTick->LOAD = 21000*ms; //设置重装载寄存器的值
	SysTick->CTRL |= (1<<0);//使能滴答定时器
	while(!(SysTick->CTRL&(1<<16)));//阻塞判断定时时间是否到达,判断SysTick->CTRL的位
}
int main(void)
{
	LED_Init();
	while(1)
	{
		GPIOF->ODR |= (1<<6);//GPIOF_ODR的位6置1则输出高电平
		Delay_ms(500);//延时500ms
		GPIOF->ODR &= ~(1<<6);//GPIOF_ODR的位6清零则输出低电平
		Delay_ms(500);//延时500ms
	}
}
void delay_s(int s)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //选择时钟
SysTick->VAL =0;
SysTick->LOAD =s*24000000; //设置预装载值
SysTick->CTRL =1; //使能滴答定时器
while(!(SysTick->CTRL &(1<<16))); //等待计数完成
SysTick->CTRL =0; //失能滴答定时器
}
void delay_ms(int ms)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
SysTick->VAL =0;
SysTick->LOAD =ms*24000;
SysTick->CTRL =1;
while(!(SysTick->CTRL &(1<<16)));
SysTick->CTRL =0;
}
void delay_us(int us)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
SysTick->VAL =0;
SysTick->LOAD =us*24;
SysTick->CTRL =1;
while(!(SysTick->CTRL &(1<<16)));
SysTick->CTRL =0;
}
int main(void)
{
	LED_Init();
	while(1)
	{
		GPIO_SetBits(GPIOF,GPIO_Pin_9);
		delay_s(2);
		GPIO_ResetBits(GPIOF,GPIO_Pin_9);
		delay_s(2);
	}
}