systick定时器是 24位 的,永不停息 的, 递减计数器。 (2^24 =16M ,永不停息是指:只要不清除 systick 控制及状态寄存器中的 使能位 ,systick定时器永不停息,睡眠模式下也工作.)
运行机制: SysTick设定处置并使能后,每经过一个系统时钟周期,计数值就减1.计数到0时,SysTick计数器自动重装初值并继续计数,同时内部的COUNTFLAG标志会置位,若中断使能就会触发中断。
系统时钟周期:外部晶振为8MHz,9倍频,系统时钟为72MHz,SysTick的最高频率为9MHz(最大为HCLK/8)。 SysTick时钟设置为最大值9MHz(9 000 000), 把SysTick计数值设置为9000,就能够产生1ms的时间基值,即SysTick产生1ms的计数。 把SysTick计数值设置为9,就能够产生1us的时间基值,即SysTick产生1ms的计数. 选择外部时钟时:滴答定时器时钟为9M (意味着 一个us ,值减少9) 要延时1us, 往val装9就可以了
下表中的四个寄存器管理了SysTick的运行。
这个寄存器是用来装载我们需计数的次数的寄存器。(它给VAL寄存器装作数值)
每一个时钟周期,VAL的值自减1。 当VAL值为0时,会重新加载LOAD中的值,并且产生COUNTFLAG标志。(COUNTFLA标志在CTRL寄存器)
下表解释的十分详细。 第0位 是定时器使能位。 第1位 是中断使能位,用于决定自减为0后是否执行中断。 第2位 是时钟源选择位 ,可以选择内部时钟或外部时钟作为时钟源。 第16位是计数标志位 ,SysTick自减到0时,该位置1。读取该位后,该位自动清零。 注意点: COUNTFLAG为计数完毕标志,读取后会自动清零。 TICKINT产生SysTick异常请求意思是产生中断。
用来校准计数器的,不常用。
先失能,关闭中断,再装载值,最后再开启。(固件库的直接调用配置函数SysTick_Config()即可)
3.5固件库版本中库函数与中文手册的有所差异。 配置代码
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); SysTick_Config(72);void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) static __INLINE uint32_t SysTick_Config(uint32_t ticks)
功能:选择时钟源 操作:改变SysTick 控制和状态寄存器- CTRL 中 第2位段(0,1,2 即第三个位置)的值 入口参数:1 SysTick_CLKSource_HCLK 内部时钟 HCLK 72M 2 SysTick_CLKSource_HCLK_Div8 外部时钟 HCLK/8 9M 返回值:无
`void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) { /* Check the parameters */ assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); if (SysTick_CLKSource == SysTick_CLKSource_HCLK) { SysTick->CTRL |= SysTick_CLKSource_HCLK; } else { SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; } } //SysTick_CLKSource_HCLK_Div8,SysTick_CLKSource_HCLK 的宏定义如下 //#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) //#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)功能:1、初始化systick 2、打开systick 3、打开systick的中断并设置优先级 操作:略 入口参数:Uint32_t ticks 即为重装值, 返回值:返回一个0代表成功或1代表失败
//此函数在core_cm3.h定义 //如果参数ticks是 72 的话,1us计数完毕,即1us置COUNTFLAG为1一次。 //如果参数ticks是 72000 的话,1ms计数完毕,即1ms置COUNTFLAG为1一次。 static __INLINE uint32_t SysTick_Config(uint32_t ticks)//static 表示只能在此头文件中实验 { //判断tick的值是否大于 2^24 ,如果大于,则不符合规则 if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ //配置 reload 寄存器的初始值 SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ //配置中断优先值,1<<4-1 = 15 v 配置为15,默认为最低的优先级 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ //配置 counter 计数器的值 SysTick->VAL = 0; /* Load the SysTick Counter Value */ //配置systick时钟为72M //使能中断 //使能systick SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0); /* Function successful */ }通常实现延迟函数的方法为:
void delay_ms(int x ) { int i; while(x--) for(i=0;i<x;i++); }x - - 对应于N毫秒的循环值。 缺陷:1占用cpu,浪费cpu资源.2中断会打断即时,易出错。
该代码还是占用了cpu资源。。。待续
//bsp_systick.h文件 #ifndef BSP_SYSTICK_H #define BSP_SYSTICK_H #include "stm32f10x.h"//stm32f10x.h定义了 core_cm3.h 中的IRQn_Type #include "core_cm3.h"//systick在内核,stm32f10x.h是外设的库,core_cm3.h是定义内核中的外设 void SysTick_Delay_us(uint32_t us); void SysTick_Delay_ms(uint32_t ms); #endif //bsp_systick.c文件 #include "bsp_systick.h" void SysTick_Delay_us(uint32_t us) { uint32_t i; SysTick_Config(72); for(i=0;i<us;i++) while(!(SysTick->CTRL&(1<<16)) ); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; } void SysTick_Delay_ms(uint32_t ms) { uint32_t i; SysTick_Config(72000); for(i=0;i<ms;i++) while(!(SysTick->CTRL&(1<<16)) ); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; }