看完了自带的视频,感觉有的说的不是很明白,所以自己查了资料,参考了很多大神的经验总结,与大家分享一下。
SysTick共有4个寄存器。
file:///C:/Users/ADMINI~1/AppData/Local/Temp/enhtmlclip/11.png
file:///C:/Users/ADMINI~1/AppData/Local/Temp/enhtmlclip/20140523202736453.png
file:///C:/Users/ADMINI~1/AppData/Local/Temp/enhtmlclip/20140523202758406.png
file:///C:/Users/ADMINI~1/AppData/Local/Temp/enhtmlclip/20140523202815062.png
注释:
1.可以通过CTRL的第2位的时钟源寄存器来控制是外部时钟源还是内部是内部时钟源。如将SCSR中的CLKSOURCE位置位,SysTick会在CPU频率下运行(72MHZ);而将CLKSOUCE位清除则SysTick会以CPU主频的1/8频率运行(9MHZ)。
2.SysTick 是一个24 位的定时器,即一次最多可以计数 2^24个时钟脉冲,这个脉冲计数值被保存到SysTick->VAL 当前计数值寄存器中,它只能向下计数,每接收到一个时钟脉冲SysTick->VAL 的值就向下减 1,直至0,然后由硬件自动把重载寄存器SysTick->LOAD 中的值到SysTick->VAL重新计数,并且当SysTick->VAL值计数到0时,触发异常,调用void SysTick_Handler(void)函数,可以在此中断服务函数中处理定时中断事件了,一般是对设定值进行递减计数操作。只要不把它在SysTick控制及状态寄存器SysTick->CTRL中的第0位使能位清除,就永不停息。
在core_cm3.h中有一个SysTick_Config函数如下所示:
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
/*reload寄存器为24位,最大值为2^24*/
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
重装载值必须小于0XFFFFFF,这是24位的递减计数器 ,不能大于最大计数值 .(0xFFFFFF的二进制是24个1)
/*初始化reload寄存器的值*/
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
在宏定义中:
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)
其中
#define SysTick_LOAD_RELOAD_Pos 0
ul代表无符号长整型数据,所以SysTick_LOAD_RELOAD_Msk的值为0XFFFFFF左移动0位,还是0XFFFFFF。
所以初装载值SysTick->LOAD=ticks-1
这句话是设置装载值,如果选用的是72M/8=9M的时钟,那么每次计数器-1需要用时1/9000000,如果我们设置装载值是9000,那么计数器一直减到0用时为 1/9000000*9000=1/1000=0.001s=1ms
/*配置systick的中断优先级*/
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
中断优先级的分组对内核和外设同样适用。当比较的时候,只需要把内核外设的中断优先级的四个位按照外设的中断优先级来分组来解析即可,即人为的分出抢占优先级和子优先级。
/*计数器值清0*/
SysTick->VAL = 0;
/*配置systick的时钟为AHB的时钟*/
/*使能systick的中断*/
/*使能systick*/
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
分别操纵了CRTL寄存器的2、1、0位,使其置位或者复位
return (0);
}
void SysTick_ms(uint32_t ms)
{
uint32_t i;
SysTick_Config(72000); 选择的使系统内部时钟,时钟没有分频,所以时钟的频率为位72M,那么计数器每次减1所用的时间是1/72000000。计数器初值如果是72000,那么每次计数器减到0,所需要的时间为(1/720000000)*72000=0.001s。所以设置初值72000时间为1ms。
for(i=0;i<ms;i++)
{
while(!((SysTick->CTRL)&(1<<16))); CTRL寄存器的第16位置1后,跳出循环。
}
/*失能systick*/
SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; 计数完成后关闭计数器
} |