STM32 系统定时器(SysTick)

Posted 一只小阿大:)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32 系统定时器(SysTick)相关的知识,希望对你有一定的参考价值。

SysTick定义

在这里插入图片描述
SysTick : 24位系统定时器,只能递减,存在于内核嵌套在NVIC中。所有的Cortex-M中都有这个系统定时器。

重装载值reload 递减,当递减到0会触发中断并且会有 置位countflag标志,VAL表示当前值。
然后reload继续从预设值开始递减,周而复始。

在这里插入图片描述
还有一个校准数值寄存器,不常用,想知道的可以看下其他文章会讲。

SysTick定时时间的计算

  1. T : 一个计数循环的时间,跟reload和 CLK有关
  2. CLK : 72M 或者9 M, 由CTRL寄存器配置
  3. reload : 24位,用户自己配置

T = reload * (1/ CLK)
CLK= 72M, 1us = (72 )* (1/ 72 000 000)
CLK= 72M, 1ms = (72 000 )* (1/ 72 000 000)
时间单位换算: 1s = 1000ms = 1000 000 us = 1000 000 000 ns

SysTick结构体

typedef struct
{
__IO uint32_t CTRL; //控制及状态寄存器
__IO uint32_t LOAD; //重装载寄存器
__IO uint32_t VAL; //重装载寄存器
__I uint32_t CALIB; //校准寄存器
} SysTick_Type;

SysTick固件库函数

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); //判断reload的值是否大于最大值 2^24
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; //配置reload寄存器的初值

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); //配置中断优先级 1<<4 -1 =16-1=15

SysTick->VAL = 0; //配置count的值
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | //配置system时钟为 72M
SysTick_CTRL_TICKINT_Msk | //使能中断
SysTick_CTRL_ENABLE_Msk; //使能systick
return (0);
}
在这里插入图片描述
在这里插入图片描述

SysTick中断优先级

在这里插入图片描述
数字越小中断优先级越高

1.system tick 属于内核的外设,它的中断优先级 与片上外设的中断优先级相比谁高?
依据是什么?

答:systick 中断优先级配置的是scb->shprx寄存器
外设中断优先级配置的是nvic-> iprx寄存器
有优先级分组
在这里插入图片描述
3.STM32的外设(内核还是片上)都是使用4个二进制来表示中断优先级

4.中断优先级的分组对内核和外设同样适用,只需要将中断优先级的四个位按外设优先级来分组即可,人为的进行分出抢占优先级和子优先级。例举:

1<<4 -1=16 -1= 15 (1 1 1 1 )
前面两位表示抢占优先级 后面两位表示子优先级
3 3 (抢占优先级3 ,子优先级3)

1<<4 = 1 0000 = 16

编写ms,us延时函数

systick和delay区别

delay一直占用cpu,而systick一般都采用中断方式,(不会有人在程序里一直查询标志位的),不占用cpu。除非任务很简单。否则实际项目不会使用循环的延时。不过因为stm32上面有更强大的外设定时器的。定时的范围也比systick要大。还可以级联,所以一般不用systick,只把systick用于操作系统的时钟节拍。

案例

SysTick.h

#include "stm32f10x.h"
void ms_delay(uint32_t ms);
void us_delay(uint32_t us);

SysTick.c

#include "stm32f10x.h"
#include "SysTick.h"
/*
		ϵͳ¶¨Ê±Æ÷Ìص㣺
		Ö»Äܵݼõ£¬Èç¹û¶¨ÒåµÄÊÇ72000
		ÄǾʹÓ72000¿ªÊ¼µÝ¼õµ½0£¬ÎªÒ»¸öÖÜÆÚ
		ËùÒÔÖ»ÐèÒªÅжÏÊÇ·ñ¼õµ½1
		
		ÈçºÎÅжϣ¿
		¿´COUNTFLAG¼Ä´æÆ÷£¬Ò²¾ÍÊÇSysTick->CTRL
		
*/
void ms_delay(uint32_t ms)
{
		uint32_t i;
		SysTick_Config(72000);//Ñ­»·Ò»´Î1ms 
	
		for(i=0;i<ms;i++)//Ҫѭ»·¶àÉÙms
		{
				while( !((SysTick->CTRL)&(1<<16)) );//ÅжÏSysTickÊÇ·ñµ½0£¬µ½0¸ÃλΪ1   
																					//!(1&1)Ìø³öÑ­»·
																					//Ϊʲô×óÒÆ16λÄØ£¬ÒòΪCTRLÊÇ16λµÄ?
																				  //¿´¿ØÖƼ°×´Ì¬¼Ä´æÆ÷µÄͼдÁË¡£
		}
				SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
		
}

void us_delay(uint32_t us)
{
		uint32_t i;
		SysTick_Config(72);//Ñ­»·Ò»´Î1us
	
		for(i=0;i<us;i++)//Ҫѭ»·¶àÉÙus
		{
				while( !((SysTick->CTRL)&(1<<16)) );
		}
				SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
		
}

led.h

#include "stm32f10x.h"
void Led_init(void);

led.c

#include "stm32f10x.h"
#include "led.h"

void Led_init(void)
{
	GPIO_InitTypeDef Led_init;
	
	//1.ʹÄÜAPB2µÄʱÖÓGPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	//2.½á¹¹ÌåÅäÖÃ
	Led_init.GPIO_Mode 	= GPIO_Mode_Out_PP;
	Led_init.GPIO_Pin	  = GPIO_Pin_13;
	Led_init.GPIO_Speed = GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOC, &Led_init);
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"
#include "usart.h"
#include "stdio.h"
#include "tim.h"
#include "motor.h"
#include "SysTick.h"

void delay(uint16_t time)
{
	uint16_t i =0;
	while(time--){
		i=12000;
		while(i--);
	}
}

int main()
{
	Led_init();
	GPIO_SetBits(GPIOA, GPIO_Pin_3);

//ʹÓÃϵͳ¶¨Ê±Æ÷SysTick´úÌædelay;
		while(1)
		{
				GPIO_ResetBits(GPIOC, GPIO_Pin_13);
				ms_delay(1000);
				GPIO_SetBits(GPIOC, GPIO_Pin_13);
				ms_delay(1000);
		}

}

以上是关于STM32 系统定时器(SysTick)的主要内容,如果未能解决你的问题,请参考以下文章

STM32F103ZET6系统定时器SysTick

stm32的systick原理与应用

STM32 的系统滴答定时器( Systick) 彻底研究解读

《零死角玩转STM32》-18-SysTick系统滴答定时器

STM32学习及应用笔记一:SysTick定时器学习及应用

stm32用SysTick延时