目录
12.1 STM32 SysTick基础知识
12.1.1 什么是SysTick
12.1.2 SysTick的作用和优势
12.1.3 SysTick寄存器及其功能介绍
12.2 STM32 SysTick标准延时函数设计
12.2.1 标准固件库中对SysTick的设置
12.2.2 标准延时函数的设计
12.1 STM32 SysTick基础知识
12.1.1 什么是SysTick
SysTick是一个ARM Cortex-M架构中的系统定时器,用于提供基础的操作系统时钟服务。它使用一个24位的计数器来测量时间间隔,并在计数器达到零时生成中断。
SysTick可以配置为不同的时钟源和计数器值,以满足各种应用需求。它通常与其他外部时钟源结合使用,以提供精确的周期性中断服务和实现各种定时和延迟功能。
在嵌入式系统和实时操作系统中,SysTick被广泛用于任务调度、时间管理、节拍控制等方面。它也常用于测试和调试,例如在代码执行过程中插入断点或记录时间戳。
总的来说,SysTick是ARM Cortex-M架构中一个非常实用的系统定时器,具有高度灵活性和可配置性,适用于各种应用场景。
12.1.2 SysTick的作用和优势
SysTick使用基于硬件的计数器来实现周期性的中断,可用于实现系统的延时、定时、多任务调度等功能。
具体来说,SysTick的主要作用包括以下几个方面:
实现系统延时:通过配置SysTick的计数器和中断,可以实现精确的微秒级别延时。这在许多嵌入式系统应用中非常重要,例如控制电机速度、等待传感器响应等。
实现系统定时:通过SysTick中断触发周期性事件,可以实现周期性任务的调度。这对于需要定期执行某些操作的应用非常有用,例如LED闪烁、传感器采集等。
实现多任务调度:通过SysTick中断触发任务切换,可以实现简单的多任务系统。这对于需要同时运行多个任务的应用非常有用,例如控制飞行器深度、高度和姿态等。
除了上述作用之外,SysTick还具有以下优势:
硬件支持:SysTick是处理器内置的硬件模块,无需外部器件支持,具有较高的可靠性和稳定性。
高精度:SysTick计数器精度较高,通常为微秒级别,可满足大多数应用的需要。
灵活配置:SysTick可以配置为不同的时钟源和计数器值,以满足各种应用需求。这使得它非常适合不同嵌入式系统和实时操作系统中的使用场景。
节省功耗:SysTick可以在空闲状态下进入低功耗模式,以节省能源并延长电池寿命。这对于需要追求低功耗的嵌入式系统应用非常有帮助。
综上所述,SysTick是一种非常有用的系统定时器,具有高度的可靠性、灵活性和精度,并能够满足不同应用场景的需求,因此在嵌入式系统和实时操作系统中被广泛使用。
12.1.3 SysTick寄存器及其功能介绍
SysTick—系统定时器有 4 个寄存器,简要介绍如下。在使用 SysTick 产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
12.1.3.1 SysTick控制寄存器
用于启动或停止SysTick计时器以及设置SysTick计时器的工作模式和时钟源等参数。
12.1.3.2 SysTick重装载值寄存器
用于设置SysTick计时器的初始值。
12.1.3.3 SysTick当前值寄存器
用于记录当前SysTick计时器的值,可用于计算剩余时间或者判断SysTick是否已经溢出。
12.1.3.4 SysTick校准值寄存器
用于记录SysTick的时钟频率,可以用来实现不同系统时钟下的精确延时。
12.2 STM32 SysTick标准延时函数设计
12.2.1 标准固件库中对SysTick的设置
12.2.1.1 SysTick配置函数(core_cm3.h)
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
//判断预设值,不能大于2^24,重装载寄存器24位最多2…^24
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
//设置重装载寄存器的初值
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
//设置中断优先级
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
//设置当前数值寄存器,清除上次数据
SysTick->VAL = 0;
//设置系统定时器的时钟源为AHBCLK=72MHz
//使能系统定时器中断
//使能定时器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
//使能成功返回0
return (0);
}
SysTick_Gnfig();在使用时直接调用即可使用,调用时设置好形参预设值。之后系统就会根据预设值到数计到0后产生中断,然后重装载数据寄存器将数据重新装裁到计数器中使其再次循环计数。
注:函数中对中断洗级进行了设置,这个优先级实际上是内核的优先级,所以没有像外说那样的抢占食先级和子优先级的说法,不过在进行优先级比较时依然披照外设那样进行比较。
12.2.1.2 SysTick优先级配置函数
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
/*为指定的中断设置优先级
*中断信号可以为正以指定外部(设备特定)中断
*也可以为负以指定内部(核心)中断
if(IRQn < 0) {
//设置Cortex-M3系统优先级
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); }
else {
//设置外设中断的优先级
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);}
}
IRQn:中断号。
Priority:优先级,在SysTick配置库函数中使用的变量。
12.2.2 标准延时函数的设计
12.2.2.1 实验要求
设计一个毫秒级和微秒级延时函数,实现LED灯的规律闪烁
12.2.2.2 设计思路
SysTtick配置函数SysTick_Config();可以有接调用.如果正确调用,则说明 SySTck各寄存器已经配置完成了,此时系统开始倒计时,我们只需要等待系统计时完成,然后判断标志位COUNTFLAG即可。
》使用SysTick_Config();初始SysTtick的寄存器,并设定重装载寄存器的值。
》设定for循环,判断标志位,用判断系统是否延时完成。
》延时完成,关闭SysTick使能,关闭延时。
12.2.2.3 软件设计
bsp_systick.h
#ifndef _BSP_SYSTICK_H
#define _BSP_SYSTICK_H
#include "stm32f10x.h"
#include "core_cm3.h"
void SysTick_Delay_us(uint32_t us);
void SysTick_Delay_ms(uint32_t ms);
#endif /*_BSP_SYSTICK_H */
bsp_systick.c
#include "bsp_systick.h"
//微秒级
void SysTick_Delay_us(uint32_t us)
{
//计时变量
uint32_t i;
//系统时钟为72M,设置72正好是1us
SysTick_Config(72);
for(i = 0; i < us; i++)
{
//计时到0以后,CRTL寄存器第16位将被置1
//判断STK_CTRL第16位是否为1,为1则跳出循环
while(!(SysTick->CTRL & (1<<16)));
}
//延时完成,关掉定时器使能
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
//豪秒级
void SysTick_Delay_ms(uint32_t ms)
{
//计时变量
uint32_t i;
//系统时钟为72M,设置72000正好是1ms
SysTick_Config(72000);
for(i = 0; i < ms; i++)
{
//计时到0以后,CRTL寄存器第16位将被置1
//判断STK_CTRL第16位是否为1,为1则跳出循环
while(!(SysTick->CTRL & (1<<16)));
}
//延时完成,关掉定时器使能
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
main.c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_systick.h"
int main(void)
{
LED_GPIO_Config();
while(1)
{
LED1_ON;
SysTick_Delay_ms(1000);
LED1_OFF;
SysTick_Delay_ms(1000);
}
}
12.2.2.4 下载验证
LED灯亮灭各一秒。
谢谢阅读!