【STM32】SysTick定时器

一、SysTick定时器

SysTick定时器是存在于Cortex-M3上的一个外设,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值,在下一个时钟沿重新加载(回绕到)LOAD 寄存器中的值,只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。

STM32F1xx官方资料:《STM32F10xxx Cortex-M3编程手册》

二、SysTick定时器的作用

(1)专用于产生RTOS的系统滴答时钟
(2)可用于裸机程序中短时间精确延时函数
(3)可用作普通定时中断功能

三、SysTick定时器的相关寄存器

SysTick控制和状态寄存器(STK_CTRL)
在这里插入图片描述

CTRL寄存器各位描述
位bit名称描述
16COUNFLAG当定时器倒计数到0时,该为由硬件自动置1
2CLKSOURCE时钟源选择 0 : AHB / 8 , 1 :AHB
1TICKINTSysTick 异常请求使能 0:不产生中断, 1:产生中断
0ENABLE计数器使能 0:禁用 ,1:使能

SysTick自动重装载值寄存器(STK_LOAD)
在这里插入图片描述
LOAD寄存器存放的是计数器的初始值,是一个恒定不变的值
RELOAD 值的范围是 0x00000001-0x00FFFFFF

SysTick当前值值寄存器(STK_VAL)
在这里插入图片描述
CORRENT首先存放的是LOAD寄存器中值,每来一个时钟,CORRENT存放的值减1
当减到0时,在下一个时钟到来重新从LOAD寄存器取值。

四、SysTick定时器相关库函数

SYSTICK寄存器在标准库中的封装
(1)SysTick_CLKSourceConfig

/**
  * @brief  Configures the SysTick clock source.
  * @param  SysTick_CLKSource: specifies the SysTick clock source.
  *   This parameter can be one of the following values:
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
  * @retval None
  */
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}

(2)SysTick_Config

 * @brief  Initialize and start the SysTick counter and its interrupt.
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

SysTick_Config函数配置的状况是:默认使用AHB时钟,会产生中断,中断优先级为低,并且最末尾启动了定时器。
如果要使用时钟AHB/8则应该先调用SysTick_Config函数后调SysTick_CLKSourceConfig函数

SYSTICK定时器的2种工作模式
(1)中断方式
(2)查询方式

SYSTICK定时器的定时计算
(1)公式:重装载值 = systick时钟频率(Hz) * 想要的定时时间(S)
(2)举个栗子(1ms) CNT = 72000000Hz * 0.001S = 72000

五、 SysTick定时器中断 SysTick_Handler()

功能:SYSTICK中断实现LED每隔500ms闪烁一次
在main函数中
(1)设置好时钟打开相应的GPIO时钟模块
(2)将相应GPIO配置为推挽输出
(3)NVIC的配置
(4)SysTick时钟源和ticks值(LOAD值)
(5)在stm32f10x_it.c相应的ISR中取反LED电平

#include "stm32f10x.h"

// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void SYSTICK_Configuration(void);

int main(void)
{
	RCC_Configuration();		//时钟配置
	GPIO_Configuration();		//GPIO配置
	NVIC_Configuration();		//NVIC配置
	SYSTICK_Configuration();
	while (1);
}

void RCC_Configuration(void)
{
	// 因为在起始文件中执行main函数之前,调用了SystemInit函数,将主频设置到72Mhz	
	/* Enable Key Button GPIO Port, GPIO_LED and AFIO clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//打开GPIOB的时钟
}

void GPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET);		//初始化PB8为0

}

void NVIC_Configuration(void)
{
//  NVIC_InitTypeDef NVIC_InitStructure;
  
#ifdef  VECT_TAB_RAM  
  /* Set the Vector Table base location at 0x20000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);   //分配中断向量表
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif
}

void SYSTICK_Configuration(void)
{
	// AHB主频为72MHz,定时时间500ms = 72000000 * 0.5 = 36000000(重新装载值)
	// 2^24 = 16777216 < 36000000
	SysTick_Config(36000000 / 8);   	
	
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);		//将SysTick时钟源设为AHB/8
}
void SysTick_Handler(void)
{
	// 在中断程序中让LED取反
	GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)!GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_8));
	// 清挂起中断
	
}

六、SysTick定短时间精确延时函数 delay()

#include "stm32f10x.h"

// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);

#define DELAY	1000

int main(void)
{
	RCC_Configuration();	 //系统时钟配置   
  	GPIO_Configuration();    //配置GPIO
	while (1)
	{
		GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);		// 亮
		delay_ms(DELAY);
		GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET);	// 灭
		delay_ms(DELAY);	
	}
}

void RCC_Configuration(void)
{
  /* Enable Key Button GPIO Port, GPIO_LED and AFIO clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
}

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  // PB8 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);		// 默认输出1让LED亮
}

// 用systick计数器来帮我们实现us级别的精确延时
// 这个函数要成立有2个条件:1、主频必须是72MHz
// 2、us要小于 1864135
void delay_us(unsigned int us)
{
	unsigned int tmp = 0;

	// 思路是先把systick的时钟源设置好,然后给一个正确的ticks
	// 然后使能systick,while循环等待countflag置位则时间到
	SysTick->LOAD = us * 9; 	// 72MHz主频,9MHz systick时钟  9 * (1 / 8)
	SysTick->VAL = 0;
	SysTick->CTRL = 0x01;		// 时钟源是AHB/8,禁止中断,使能systick
	
	do
	{
		tmp = SysTick->CTRL;	
	}while (!(tmp & (1<<16)));

	// 跳出do while循环说明时间到了,关闭定时器即可
	SysTick->VAL = 0;
	SysTick->CTRL = 0x00;
}

// ms不能大于 1864
void delay_ms(unsigned int ms)
{
 	unsigned int tmp = 0;
 	
	// 思路是先把systick的时钟源设置好,然后给一个正确的ticks
	// 然后使能systick,while循环等待countflag置位则时间到
	SysTick->LOAD = ms * 9000; 	// 72MHz主频,9MHz systick时钟
	SysTick->VAL = 0;
	SysTick->CTRL = 0x01;		// 时钟源是AHB/8,禁止中断,使能systick

	do
	{
		tmp = SysTick->CTRL;	
	}while (!(tmp & (1<<16)));

	// 跳出do while循环说明时间到了,关闭定时器即可
	SysTick->VAL = 0;
	SysTick->CTRL = 0x00;
}
  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tyx-☆、、、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值