2、STM32中的SysTick
作为一用于系统级的24位递减计时器,在STM32中又是处理的呢?ST在手册里介绍的比较简单,但在库函数中却有比较清楚的定义。不论是标准库还是HAL库都有较为清楚的定义,如在标准库中就定义SysTick寄存器结构体机器操作函数,在misc.C文件中的SysTick_CLKSourceConfig函数,它是一个时钟源配置函数,其定义如下:
/*@功能:配置SysTick时钟源
*@输入参数: SysTick_CLKSource: 指定 SysTick 时钟源.
* 该参数可以是以下其中一个值:
* @ SysTick_CLKSource_HCLK_Div8: AHB 时钟 8 分频作为SysTick时钟源
* @ SysTick_CLKSource_HCLK: AHB 时钟作为 SysTick 时钟源. */
void SysTick_CLKSourceConfig(uint32_t Sy sTick_CLKSource)
{
assert_param(IS_SYSTICK_CLK_SOURCE(SysTi ck_CLKSource));
if(SysTick_CLKSource== SysTick_CLKSource_HCLK)
{
SysTick->CTRL|= SysTi ck_CLKSource_HCLK;
}
else
{
SysTick->CTRL&= SysTick_CLKSource_HCLK_Div8;
}
}
由此可见,在STM32中时钟可以设置为HCLK或者HCLK的8分频,根据使用的需求而定。默认不配置的话时钟就是HCLK的8分频。同样在HAL苦衷的定义也是如此。
在core_cm3.h文件中有寄存器定义:
typedefstruct
{
__IOuint32_t CTRL;
__IOuint32_t LOAD;
__IOuint32_t VAL;
__Iuint32_t CALIB;
}SysTick_Type;
还定义了一个SysTick_Config 函数
#if (!defined(__Vendor_Sy sTickConfig )) ||(__Vendor_SysTickConfig == 0)
/**
* @功能 初始化并开启 Sy sTick 计数器及其中断
*@输入参数 ticks 两次中断间的 ticks 数值
*@返回值 1 = 失败, 0=成功
* 初始化系统滴答定时器及其中断并开启系统滴答定时器在自由运行模式下以产生周期中断*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if(ticks >SysTick_LOAD_RELOAD_Msk) return(1);/* 重装值超过了 24 位,是不可能的。返回失败值 0 */
SysTick->LOAD =(ticks & SysTick_LOAD_RELOAD_Msk) - 1;/* 设置重装载寄存器 */
NVIC_SetPriority(SysTick_IRQn,( 1<<__NVIC_PRIO_BITS) - 1); /*设置优先级for Cortex-M0系统中断*/
SysTick->VAL = 0; /*装载计数器值(当前计数值清 0) */
SysTick->CTRL =SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk| SysTick_CTRL_ENABLE_Msk;/* 使能 Sy sTick 中断请求和 Sy stick 定时*/
return(0); /*成功,返回 0 */
}
#endif
经过以上分析,我们我们需要,可以很方便的在自己的软件中操作SysTick来实现一些功能。
3、STM32中SysTick应用举例
既然SysTick我们已经清楚了他的原理及操作,也明白了STM32库中如何来操作它,那么我们能用他来做什么呢?首先我们可以在STM32中使用嵌入式操作系统的时候使用它来,并更具实际应用来设置。其实在不考虑操作系统是我们还可以使用SysTick来实现延时计时器。
一个实现的例子如下:
//定义延时计数的变量
__IO uint32_t TimingDelay;
const uint16_t delayAdjustments=12;
//函数名:ms延时函数
//描 述:参数1即为1ms,1000即为1s;只有几us的误差;
void Delayms(__IO uint32_t nTime)
{
while(SysTick_Config(SystemCoreClock/1000));
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;// 关闭滴答定时器
TimingDelay = nTime;
SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk;// 使能滴答定时器
while(TimingDelay != 0);
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//函数名:us延时函数
//描 述:参数1即为1us,1000即为1ms;只有几us的误差;
void Delayus(__IO uint32_t nTime)
{
while(SysTick_Config(SystemCoreClock/1000000));
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;// 关闭滴答定时器
TimingDelay = nTime;
SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk;// 使能滴答定时器
while(TimingDelay != 0);
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//函数名:延时递减计数函数
//描 述:由systick的中断函数调用,实现延时数值的递减计数
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
//函数名:延时调整形式的delaynus函数
//描 述:参数1即为1us,1000即为1ms,根据时钟频率的不同时间不同
void delay_nus(uint16_t n)
{
uint16_t j;
while(n--)
{
j=delayAdjustments;//根据不同时钟频率的指令周期调整数值
while(j--);
}
}
//函数名:延时调整形式的delaynms函数
//描 述:参数1即为1ms,1000即为1s,根据时钟频率的不同时间不同
void delay_nms(uint16_t n)
{
while(n--)
{
delay_nus(1000);
}
}
4、参考文献
我们参考了一些经典的手册以及网络论坛上的一些讨论,无法一一列出,暂列出部分参考文献:
(1)、《Cortex-M3权威指南》
(2)、《STM32F10x参考手册》
(3)、《STM32F4参考手册》
(4)、《STM32F7参考手册》
(5)、《STM32F10x库函数说明》
(6)、《STM32F1 HAL库说明》
(7)、《STM32F4 HAL库说明》
(8)、《STM32F7 Hal库说明》