这个systick看起来简单,但是刚开始理解的时候还是有点烧CPU。
前情提要:
简单来说:ctrl就是开关systick,load就是计时的一个目标值,计时到了这个目标值就自动归0;VAL里面装了现在计时的数字。
我的理解:
CTRL:
啃臭键 ,0位负责systick的开关,1位负责设置计时到期后要不要做其他动作;2位就是选择时钟,值0表示AHB频率8分频,值1表示用AHB时钟。
先上代码再解释:
#include "bsp_systick.h"
uint32_t f_us;
uint32_t f_ms;
void SysTick_Init(){
SysTick->CTRL &=~0x05;//AHB——8分频,并且关闭定时器
f_us = SystemCoreClock / 8000000;
f_ms = f_us * 1000;
}
函数中第一句代码的意思是让CTRL的2~0位变成010;(&=~)清0用;
第二句代码中系统时钟就是72M,除了之后的f_us 就是 9;
为什么设置成9呢?
因为systick时钟在8分配后频率就是9MHz,1秒计数9×10*6次,1s = 10*6us, 1us 计数 9 次。
void SysTick_Delay_us(uint32_t us)
{
uint32_t i;
SysTick->LOAD = us*f_us;
SysTick->VAL = 0;
SysTick->CTRL |=0x01;
do{
i = SysTick->CTRL;
}while(!(i&(1<<16)));
SysTick->CTRL &=~0x01;
}
这里假设传入参数10,load 的值就是 10 * 9 =90;把val清0了,然后打开计时器,
通过一个 do-while 循环,获取 SysTick 控制寄存器的值 CTRL
,并将其存储在变量 i
中。
循环会一直执行,直到 SysTick 控制寄存器的第 16 位(也就是计数器完成位)设置为 1,表示延迟时间已经过去。(我们的目的是计数完成就退出循环,所以当第16置1的时候,加个!就能退出循环了)
关闭计数器。
整个函数的功能简单来说就是 计数目标值90,计数器从0计数,开启计数器,判断计数完成否?,关闭计数器。
void SysTick_Delay_ms(uint32_t ms)
{
uint32_t i;
SysTick->LOAD = ms*f_ms;
SysTick->VAL = 0;
SysTick->CTRL |= 0x01;
do{
i = SysTick->CTRL;
}while(!(i&(1<<16)));
SysTick->CTRL &=~0x01;
}