SysTick—系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。为操作系统服务。
放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
系统定时器是一个 24bit 的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。
SysTick—系统定时器有 4 个寄存器。使用 SysTick 产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
统定时器的校准数值寄存器在定时实验中不需要用到。有关各个位的描述这里引用手册里面的英文版本,比较晦涩难懂,暂时不知道这个寄存器用来干什么。
t:一个计数循环的时间,跟reload和CLK有关 CLK:72M或者9M,由CTRL寄存器配置 RELOAD:24位,用户自己配置
t = reload*( 1/clk ) Clk = 72M时,t = (72) *(1/ 72 M )= 1US Clk = 72M时,t = (72000) *(1/ 72 M )= 1MS 时间单位换算: 1s = 1000ms = 1000 000 us = 1000 000 000ns
在固件库文件:core_cm3.h中定义 这里注意,配置结构体,其实就相当于配置寄存器。
这个是库函数中的东西,早core_cm3.h中,我们可以直接拿来用。
//函数前面的是防止对寄存器进行优化 static __INLINE uint32_t SysTick_Config(uint32_t ticks) { // 判断 tick 的值是否大于 2^24,如果大于,则不符合规则 if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); // 初始化reload寄存器的值 SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; // 配置中断优先级,配置为15,默认为最低的优先级 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); // 初始化counter的值为0 SysTick->VAL = 0; // 配置 systick 的时钟为 72M // 使能中断 // 使能systick SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; return (0); }可以实现灯的精确闪烁: main.c:
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h> #include "bsp_led.h" #include "bsp_systick.h" void Delay( uint32_t count ) { for(; count!=0; count--); } int main(void) { // 来到这里的时候,系统的时钟已经被配置成72M。 LED_GPIO_Config(); while(1) { //GPIO_SetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN); LED_G(OFF); //Delay(0xFFFFF); SysTick_Delay_ms(500); //GPIO_ResetBits(LED_G_GPIO_PORT, LED_G_GPIO_PIN); LED_G(ON); //Delay(0xFFFFF); SysTick_Delay_ms(500); } }