SysTick定时器
- 一、参考资料
- 二、时钟源选择与定时时间计算
- 1、时钟源选择
- 2、定时时间计算
- 三、SysTick_Handler中断服务函数
一、参考资料
嘀嗒定时器:时钟源、寄存器
二、时钟源选择与定时时间计算
结合正点原子的代码进行说明:
1、时钟源选择
从上图可以发现:Cortex系统时钟(嘀嗒定时器)是经过SYSCLK8分频之后得到的;
SYSCLK最高为72MHz,来源为HSI、PLL、HSE;
原子的代码,默认使用的是来自于PLL,且为最高72MHz;
在system_stm32f10x.c中可以看到:三种时钟源的选择方法。
在stm32f10x.h中可以看到:HSE默认大小为8MHz,如果要修改晶振大小需要注意。
2、定时时间计算
以原子默认时钟源配置为例,SYSCLK为72MHz。
众所周知,原子的delay.c的延迟函数使用的为systick定时器,并且在要先调用delay_init函数
可以看到SysTick_CLKSourceConfig函数无非就是配置其CTRL寄存器,来控制使用哪个时钟源,这里我不在贴寄存器的配置了,可以去看上边的参考链接。
原子选择的是PLL,倍频到72MHz,然后再进行8分频(无论选择哪个时钟源都要进行8分频),72MHz/8=9MHz,也就是说systick此时的频率是9MHz;
再继续看,延迟函数:
这个函数如果nus=1,则装入的值为fac_us,也就表示这个函数能延迟1us。为什么呢?
根据systick的工作原理可以知道,当装入寄存器的值一直减少,当变为0的时候,表示延迟结束。
也就说能够延迟的时间为:装载值*减少一个数所需要的时间
装载值可以发现:当nus=1时,fac_us=SystemCoreClock/8000000。SystemCoreClock为72M,则fac_us=9。即装载值为9。
减少一个数所需要的时间:即为systick的频率,也就是9MHz,转换为时间为1/9MHz。
延迟时间:9*1/9MHz=1us (Hz对应s,KHz对应ms,MHz对应us)
为什么要除以8M?就是为了使得当一个fac_us时,装入的数,刚好为1us。
举个例子:假设SYSCLK选择为8MHz,则systick频率为1MHz;fac_us为8M/8M=1,则延迟时间为1*1/1MHz=1us。
延迟原理不在赘述,无非就是do while死循环,一直读取CTRL寄存器,判断标志位是否置为1。
三、SysTick_Handler中断服务函数
systick为定时器,那么其中断服务函数在哪里?
在stm32f10x_it.c中
那么再问一句,该中断服务函数是每减少装载值的一个数就触发一次,还是装载值减少到0才会触发呢?
我进行了软件模拟仿真,证明是
装载值减少为0才会触发该中断服务函数,也就是说等延迟结束的时候会触发
。