SysTick是系统滴答定时器,可以说是操作系统的的“心跳”,它被绑在NVIC中,用于产生SysTick异常(异常号:15)。一旦产生SysTick异常,就会产生滴答中断,这个滴答中断对操作系统尤其重要。例如:操作系统可以为多个任务分配不同数目的时间片,确保没有一个任务霸占系统,或者将每个定时器周期的某个时间范围赐于特定的任务等。操作系统提供的各种定时功能都与这个滴答定时器有关,因此需要一个定时器产生周期性的中断,而且最好让用户程序不能随意访问它的寄存器。以维持操作系统“心跳”的节律。
而STM32内核包含了一个简单的定时器——SysTick,所有CM3芯片都带有这个定时器,该定时器的时钟源可以是内部时钟,也可以是外部时钟,在STM32中的SysTick以HCLK(AHB时钟)或HCLK/8作为运行时钟。
SysTick是系统滴答定时器,可以说是操作系统的的“心跳”,它被绑在NVIC中,用于产生SysTick异常(异常号:15)。一旦产生SysTick异常,就会产生滴答中断,这个滴答中断对操作系统尤其重要。例如:操作系统可以为多个任务分配不同数目的时间片,确保没有一个任务霸占系统,或者将每个定时器周期的某个时间范围赐于特定的任务等。操作系统提供的各种定时功能都与这个滴答定时器有关,因此需要一个定时器产生周期性的中断,而且最好让用户程序不能随意访问它的寄存器。以维持操作系统“心跳”的节律。
而STM32内核包含了一个简单的定时器——SysTick,所有CM3芯片都带有这个定时器,该定时器的时钟源可以是内部时钟,也可以是外部时钟,在STM32中的SysTick以HCLK(AHB时钟)或HCLK/8作为运行时钟。
2.SysTick工作分析
/* * 函数名 :main * 描述 :主函数 * 输入 : * 输出 : */ int main(void) { /*LED 端口初始化 */ init_led_gpio(); //system_init(); /*配置systick 为10us中断一次*/ SysTick_Init(); for(;;) { turn_led(LED1,ON); Delay_us(50000); turn_led(LED1,OFF); turn_led(LED2,ON); Delay_us(50000); turn_led(LED2,OFF); turn_led(LED3,ON); Delay_us(50000); turn_led(LED3,OFF); } }
#include "SysTick.h" #include "stm32f10x_it.h" #include "core_cm3.h" #include "system_stm32f10x.h" static __IO u32 TimingDelay; /* * 函数名 :SysTick_Init * 描述 :启动系统滴答定时器 SYSTICK * 输入 : * 输出 : * 调用 :外部调用 */ void SysTick_Init(void) { /* systemFrequency /1000 1ms中断 * systemFrequency /100000 10us中断 * systemFrequency /1000000 1us中断 */ //if (SysTick_Config(SystemFrenquency /100000)) ST3.0.0库版本 if (SysTick_Config(SystemCoreClock /100000)) // ST3.5.0库版本 { /* Capture error */ while(1); } //关闭滴答定时器 SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk; } /* * 函数名:Delay_us * 描述 :us 延时程序,10us 为一个单位 * 输入 : * 输入 : * 调用 : Delay_us(1) 则实现的延时为1*10us = 10us */ void Delay_us(__IO u32 nTime) { TimingDelay = nTime; //使能滴答定时器1 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; while(TimingDelay !=0); } /* * 函数名:TimingDelay_Decerment * 描述 : 获取节拍程序 * 输入 : * 输入 : * 调用 : 在SysTick中断函数 SysTick_Handler()调用 */ void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } }
/* * 函数名:Delay_us * 描述 :us 延时程序,10us 为一个单位 * 输入 : * 输入 : * 调用 : Delay_us(1) 则实现的延时为1*10us = 10us */ void Delay_us(__IO u32 nTime) { TimingDelay = nTime; //使能滴答定时器1 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; while(TimingDelay !=0); }
一旦我们调用了Delay_us()函数,SysTick定时器就被开启,按照设定好的定时周期递减技术,当Systick的计数寄存器的值减为0时,就进入中断函数,当中断函数执行完毕之后重新计时,如此循环,除非它被关闭。