1概述
嘀嗒时钟(SysTick)是一个简单的系统时钟节拍计数器,它属于Cortex-M4内核嵌套向量中断控制器(NVIC)里的一个功能单元。他是一个24位的倒计时定时器(在NVIC中),当systick计数值到0的时候,SysTick重装载寄存器就会自动重新装载初值。只要SysTick控制和状态寄存器(CTRL)中的使能位没有ENABLE清除掉,那么就会永远的执行下去。
SysTick定时器被捆绑在NVIC中,可产生SysTick异常(异常号:15),属于Cortex-M4内核里的一个功能单元。
SysTick常作为系统节拍定时器用于操作系统(如mCOS-Ⅱ、FreeRTOS等)的系统节拍定时,从而推动任务和时间的管理。
SysTick的最大使命,就是作为系统的时基定期地产生异常请求。
在不采用操作系统的情况下,完全可以作为通用定时器、计数器使用的。
下图是SysTick控制控制和状态寄存器描述,(地址:0xe000e010)
SysTick 控制及状态寄存器:
SysTick 寄存器:
SysTick 重装载数值寄存器:地址 0XE000E014
特别注意:计数最大值是)0XFFFFFF,在设置重装在值得时候不能大于这个。
SYSTick当前数值寄存器(VAL),地址:0XE000E018
毕业寄语:
毕业,是一首离别的歌,更是青年成长的里程碑。四年的时光一千多日夜就这样瞬息即过,但它却是你们的瑰丽人生中最浓丽的一抹色彩!如一条条的小溪汇成了一条多彩的河流。你们成了校园里最靓丽的一道风景。
SYSTick校准数值寄存器(VAL),地址:0XE000E018
配置SysTick作为时钟基准,主要通过对SysTick控制与状态寄存器、SysTick重装载数值寄存器和SysTick当前数值寄存器三个寄存器进行初始化。需要配置的内容如下:
① SysTick时钟源选择。
② 异常请求设置。
③ SysTick时钟使能。
④ 初始化SysTick重装数值。
⑤ 清零SysTick当前数值寄存器。
SysTick的库函数
1、SysTick寄存器结构体类型
/** \\brief Structure type to access the System Timer (SysTick).
*/
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
2、SysTick时钟源初始化函数
/**
@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.
*/
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;
}
}
SysTick_CLKSourceConfig函数被定义在misc.c文件中,配置的是SysTick控制与状态寄存器中的位2。
设置为0:选择使用HCLK/8作为时钟源。
设置为1:选择使用HCLK作为时钟源。
在实际使用的过程中参数宏在misc.h文件里面。
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
3、SysTick配置函数
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
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函数被定义在core_cm3.h文件中,它的功能是初始化并开启SysTick计数器及其中断,输入参数ticks是两次中断间的ticks数值。通过次函数可以初始化系统嘀嗒定时器及其中断并开启系统嘀嗒定时器在自由运行模式下以产生周期中断。
SysTick异常服务函数
void SysTick_Handler(void)
SysTick_Handler的服务函数已在启动文件中定义过,并定义了[WEAK]属性,函数内执行的是空循环。
这就要求用户在使用SysTick异常服务时,需要在启动文件之外的其他文件重新定义服务程序,并且其函数名要和启动文件中的函数名保持一致,只有这样才能在编译阶段,将重定义的服务程序函数入口地址替换到SysTick在异常/中断向量表的位置。
01应用实例
使用SysTick产生1s的定时,控制LED灯以2s为周期进行闪烁。
假设HCLK=180MHz。
在system_stm32f4xx.c文件中定义了全局变量uint32_t SystemCoreClock=180000000,并在头文件system_stm32f4xx.c->stm32f4xx.h中声明。
1-配置SysTick
按照1ms进行分片,配置程序如下:
SysTick_Config(SystemCoreClock/1000);
这样,SysTick会每1ms产生一次异常请求。全局变量定义:
volatile uint32_t TimingDelay;
volatile防止变量TimingDelay在使用过程中被优化
2-写延时函数
编写以1ms为计时基准的函数:
void delay_ms(uint32_t nTime)
{
TimingDelay=nTime;
while(TimingDelay!=0);
}
其中,nTime是需要计时的ms数。
3-写中断服务函数
每1ms SysTick都会产生一次异常请求,执行其异常服务程序SysTick_Handler。对SysTick异常服务程序进行编写,每1ms对变量TimingDelay减1次。
void SysTick_Handler(void)
{
if (TimingDelay!=0)
{
TimingDelay--;
}
}
4-应用
int main(void)
{
/*配置SysTick为每1ms异常一次*/
if (SysTick_Config(SystemCoreClock/1000))
{
/*SystemCoreClock/1000超出计数最大值时报错,程序陷入空循环*/
while (1);
}
/*初始化LED灯的GPIO*/
LED_Config ();
while (1)
{
/*反转LED灯状态*/
LED_TOGGLE;
/*延时1s*/
delay_ms (1000);
}
全部0条评论
快来发表一下你的评论吧 !