STM32下SysTick的一个容易发生的错误,时钟频率设置
今天同事測試我之前寫的一個小程序,發生了奇怪的錯誤,先是Uart通訊接收操作,出現了接收數據不全的問題:2個字節的應答幀,在實際運行中只能收到1個字節,導致程序死循環。檢查后發現,是接收部分代碼留的延時太短,造成了芯片誤以為通訊已結束,但實際應答幀尚未傳輸完畢。(此處接收代碼的工作模式是:當Uart接收到1個字節后,即開始一個定長的延時,該延時長度與通訊波特率相關,當正常通訊還在繼續時,則應在延時結束前收到下一個字節數據,如延時結束仍未收到下一個字節數據,說明當前一幀數據已完成,可開始對已接收數據進行處理)
發現了問題后,進行相應的針對性操作,對延時長度進行了增加,即解決了此問題。但仍然覺得疑惑,因此段程序是已經通過測試的,運行正常,不應突然出現這種奇怪的錯誤,因此懷疑芯片自身的延時程序存在問題。
而后此程序繼續出現的錯誤證實了之前的懷疑:新出現的錯誤是顯示部分程序的延時明顯不夠,因此可以斷定是延時部分出了問題。此程序的延時功能由滴答定時器的1ms延時函數來實現,對該函數進行排查,果然發現了問題根源。
stm32的滴答定時器設置主要有以下寄存器:
其中SysTick->CTRL寄存器包含了對滴答定時器的時鐘頻率來源設置和分頻設置。前述小程序中,采用的是STM32F107芯片,外部時鐘,工作頻率為72MHz,在此程序中,為了讓滴答定時器的工作壓力稍減,使用了8分頻的時鐘設置,計數(72000000/8000)=9000,時長為1ms。代碼如下:
?
void SystemTick_Configuration(void)
{
RCC_ClocksTypeDef RCC_Clocks;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
RCC_GetClocksFreq(&RCC_Clocks);
// SystTick configuration: an interrupt every 1 ms
if(SysTick_Config(RCC_Clocks.SYSCLK_Frequency / 8000))
{
while(1) FEED_WWDG;
}
}
此程序在我的電腦編譯下是正常工作的,但在同事電腦編譯下出了問題,滴答定時器的延時明顯縮短,原因在于core_cm3.h文件。此文件位置在C:\Keil\ARM\CMSIS\Include文件夾下,此文件中的SysTick_Config函數包含以下操作:
?
?
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
SysTick->VAL = 0; /* 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 (0); /* Function successful */
}
此處對滴答定時器的時鐘來源進行了操作,使其恢復了最高頻率(72MHz),不分頻:
?
在我的電腦上,因為對core_cm3.h文件做了以下修改,屏蔽了其對滴答定時器時鐘的操作,所以可以正常運行:
SysTick->CTRL |= //SysTick_CTRL_CLKSOURCE_Msk |但在同事的電腦上沒有做此操作,從而導致了1ms延時實際只有0.125ms,于是出現了前述的種種錯誤。
?
解決辦法:
1、使用滴答定時器時,不再考慮減輕芯片負擔,直接采用原始頻率,可以保證不會出現此問題。
2、修改文件調用指向,不調用工程外的相關頭文件,防止出現移植時,不同電腦間,工程外文件的不同導致的錯誤。
總結
以上是生活随笔為你收集整理的STM32下SysTick的一个容易发生的错误,时钟频率设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32外设驱动---SysTick精
- 下一篇: IAR stm32中函数硬是要加上声明才