作者 | strongerHuang
微信公众号 | 嵌入式专栏
STM32CubeMX中Cortex系统定时器(System Timer)选择1分频和8分频,为啥生成代码一样?
<center><img src="http://mcu.eetrend.com/files/2021-12/wen_zhang_/100555955-229791-1.png&…; alt=“STM32的SysTick时钟源来自哪里?"></center>
因为STM32CubeMX会启动SysTick作为延时(HAL_Delay)函数的时基,而SysTick作为Cortex内核的一部分,就会用到Cortex系统定时器。
那么,问题就来了SysTick时钟源来自哪里?
<strong><font color="#004a85">1、数据手册和STM32CubeMX时钟树</font> </strong>
数据手册时钟树:
<center><img src="http://mcu.eetrend.com/files/2021-12/wen_zhang_/100555955-229792-2.png&…; alt=“STM32的SysTick时钟源来自哪里?"></center>
STM32CubeMX时钟树:
<center><img src="http://mcu.eetrend.com/files/2021-12/wen_zhang_/100555955-229793-3.png&…; alt=“STM32的SysTick时钟源来自哪里?"></center>
你会发现:数据手册中的只有『/8』分频,而STM32CubeMX除了『/8』分频,还有『/1』分频。
<strong><font color="#004a85">2、SysTick时钟初始化代码</font> </strong>
不管是使用标准外设库,还是HAL库,你初始化SysTick,都会调用内核中的SysTick_Config函数。
标准库常用初始化:
<pre style="overflow-x:auto; background-color:#e9e9e9;">SysTick_Config(SystemCoreClock / 1000);</pre>
HAL库初始化同样也是调用底层的初始化函数:
<pre style="overflow-x:auto; background-color:#e9e9e9;">uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}</pre>
初始化调用这段代码之后,SysTick将会实现1ms中断一次。
这段代码实现1ms中断一次相信大家都能理解,但是这里SysTick初始化和上面说的时钟『/8』有关系吗?
<strong><font color="#004a85">3、SysTick时钟源是来自哪里?</font> </strong>
这个问题只要认真看参考手册都能找到答案。
RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。
通过对SysTick控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。(--来自参考手册)
也就是说SysTick时钟源可以来自两个地方:
<ul>
<li>
<p><strong>AHB时钟8分频</strong></p>
</li>
<li>
<p><strong>HCLK(内核)时钟</strong></p>
</li>
</ul>
通过SysTick控制与状态寄存器的设置进行选择时钟源。
具体就是通过CLKSOURCE(时钟源)这一Bit位来选择:
<center><img src="http://mcu.eetrend.com/files/2021-12/wen_zhang_/100555955-229794-4.png&…; alt=“STM32的SysTick时钟源来自哪里?"></center>
再次看SysTick_Config函数源码:
<pre style="overflow-x:auto; background-color:#e9e9e9;">__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
(在core_cm3.h,或者core_cm4.h等内核源码中)</pre>
你会发现,其实源码已经默认使用HCLK(内核)时钟。
而SysTick_Config函数属于内核(如core_cm3.h)已经写好源码,一般我们不去修改。
所以,到这里,你会明白:SysTick时钟源其实就是用的HCLK(内核)时钟。
<strong><font color="#004a85">4、最后</font> </strong>
开篇的问题:STM32CubeMX中Cortex系统定时器(System Timer)选择1分频和8分频,为啥生成代码一样?
<center><img src="http://mcu.eetrend.com/files/2021-12/wen_zhang_/100555955-229795-5.png&…; alt=“STM32的SysTick时钟源来自哪里?"></center>
难道,STM32CubeMX配置Cortex系统定时器时钟是有Bug吗?
来源:<a href="https://mp.weixin.qq.com/s/d7gyEA79RIdaIGU4B3poZg">嵌入式专栏</a>
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。