知道网站是wp程序做的如何仿站,wordpress 转小程序,苏州实力做网站公司,网站建设作业#xfeff;#xfeff;
这几年一直使用STM32的MCU#xff0c;对ARM内核的SysTick计时器也经常使用#xff0c;但几乎没有仔细了解过。最近正好要在移植一个新的操作系统时接触到了这块#xff0c;据比较深入的了解了一下。
1、SysTick究竟是什么#xff1f;
关于SysT…
这几年一直使用STM32的MCU对ARM内核的SysTick计时器也经常使用但几乎没有仔细了解过。最近正好要在移植一个新的操作系统时接触到了这块据比较深入的了解了一下。
1、SysTick究竟是什么
关于SysTick在STM32的资料中并没有详细的介绍这可能由于SysTick是ARM内核的东西。在《STM32F10xxx参考手册》、《STM32F4xx参考手册》以及《STM32F7xx参考手册》中介绍时钟的时候仅仅是在使用树上简单的画出了HCLK时钟经过8分频后送到了Cortex系统时钟。对这个时钟的描述也非常的简单。在《STM32F10xxx参考手册》中仅仅说“RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。”同样在《STM32F4xx参考手册》和《STM32F7xx参考手册》中也只是说“RCC 向 Cortex 系统定时器 (SysTick) 馈送 8 分频的 AHB 时钟 (HCLK)。”
另外STM32在中断部分对SysTick也有一句话的描述。如在《STM32F10xxx参考手册》中的“9.1.1 系统嘀嗒(SysTick)校准值寄存器”中提到“系统嘀嗒校准值固定为9000当系统嘀嗒时钟设定为9MHz(HCLK/8的最大值)产生1ms时间基准。”而在《STM32F4xx参考手册》的“10.1.2SysTick 校准值寄存器”一节和《STM32F7xx参考手册》“10.1.1SysTick 校准值寄存器”一节中也都有“SysTick 校准值设置为 18750。当 SysTick 时钟设置为 18.75 MHzHCLK/8HCLK 设为150 MHz会产生 1 ms 时间基准。”
仅看这些让我们觉得SysTick似乎都是定好的但事实上并非如此因为在库函数中有相关寄存器的操作函数。为了搞清楚这一点我们必须查看Cortex-M3和M4的手册。在《Cortex-M3权威指南》的“第8章 NVIC与中断控制”中有比较详细的描述。首先很明确SysTick 就是一个定时器其次SysTick定时器被捆绑在NVIC中用于产生SYSTICK异常主要适用于操作系统的“心跳”节律。关于SysTick的时钟来源最终还是由芯片厂商决定。
SysTick定时器能产生中断并且是一个单独的异常类型并且在向量表中有它的一席之地。并有四个寄存器来控制SysTick在《Cortex-M3权威指南》中对他们的描述如下
1、STK_CSR控制寄存器寄存器内有4个位具有意义 2、STK_LOAD 重载寄存器
Systick 是一个递减的定时器当定时器递减至0 时重载寄存器中的值就 会被重装载继续开始递减。STK_LOAD 重载寄存器是个24 位的寄存器最大计数0xFFFFFF。 3、STK_VAL当前值寄存器 也是个24 位的寄存器读取时返回当前倒计数的值写它则使之清零同时还会清除在SysTick 控制及状态寄存器中的COUNTFLAG 标志。 4、STK_CALRB 校准值寄存器 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 delayAdjustments12; //函数名ms延时函数
//描 述参数1即为1ms1000即为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-CTRL0x00; //关闭计数器 SysTick-VAL 0X00; //清空计数器
} //函数名us延时函数
//描 述参数1即为1us1000即为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-CTRL0x00; //关闭计数器 SysTick-VAL 0X00; //清空计数器
} //函数名延时递减计数函数
//描 述由systick的中断函数调用实现延时数值的递减计数
void TimingDelay_Decrement(void)
{ if (TimingDelay ! 0x00) { TimingDelay--; }
} //函数名延时调整形式的delaynus函数
//描 述参数1即为1us1000即为1ms根据时钟频率的不同时间不同
void delay_nus(uint16_t n)
{ uint16_t j; while(n--) { jdelayAdjustments;//根据不同时钟频率的指令周期调整数值 while(j--); }
} //函数名延时调整形式的delaynms函数
//描 述参数1即为1ms1000即为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库说明》