昨天在設置 STM32F103 的系統時鐘的時候,按照官方文檔的方法進行設置,雖然系統時鐘有效,可是本來設定爲1s後執行的任務卻延遲了九秒左右。百思不得其解,能夠肯定硬件是沒有問題的。函數
如下是系統時鐘的設置代碼:ui
void clock_init(){ if (SysTick_Config(SystemCoreClock/CLOCK_SECOND)){ while (1); } }
SysTick_Config() 是系統時鐘的設置函數,代碼以下:code
/** * @brief Initialize and start the SysTick counter and its interrupt. * * @param ticks number of ticks between two interrupts * @return 1 = failed, 0 = successful * * Initialise the system tick timer and its interrupt and start the * system tick timer / counter in free running mode to generate * periodical interrupts. */ 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 */ }
參數 ticks 是兩個中斷之間所須要的CPU ticks。我所使用的板子是STM32F103,CPU頻率爲72MHz。能夠經過宏 SystemCoreClock 進行訪問。上面宏 CLOCK_SECOND 設置爲1000。也就是說,經過上面的配置,系統每1ms進行中斷函數一次,精度爲1ms。
如下是中斷處理函數代碼:文檔
void SysTick_Handler(void) { current_clock++; if(etimer_pending() && etimer_next_expiration_time() <= current_clock) { etimer_request_poll(); } if (--second_countdown == 0) { current_seconds++; second_countdown = CLOCK_SECOND; } }
主要的做用是 current_clock 計數的遞增和檢查定時器有沒有過時。可是任務卻沒有像預期同樣在設定的時間後運行,而是延遲了近9秒。已經能夠肯定板子的CPU頻率確實爲72MHz,可是實際上板子的頻率卻爲8M。it
解決方法:
STM32F103內部是8M的震盪,經過倍頻後能夠達到72M。我所使用的固件庫是3.5的版本,經過查看文件system_stm32f103x.c文件,能夠發現下面宏定義:io
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000 #endif
其中STM32F10X_MD_VL之類的宏須要用戶本身定義,而這裏設置了SYSCLK_FREQ_72MHz爲72000000。也就是說固件庫在默認硬件已經接了8M晶振時,103的板子能夠跑到72M。配置
#ifdef SYSCLK_FREQ_HSE static void SetSysClockToHSE(void); #elif defined SYSCLK_FREQ_24MHz static void SetSysClockTo24(void); #elif defined SYSCLK_FREQ_36MHz static void SetSysClockTo36(void); #elif defined SYSCLK_FREQ_48MHz static void SetSysClockTo48(void); #elif defined SYSCLK_FREQ_56MHz static void SetSysClockTo56(void); #elif defined SYSCLK_FREQ_72MHz static void SetSysClockTo72(void); #endif
上面是聲明時鐘設置的代碼,能夠看到這裏出現了SetSysClockTo72 函數,把系統時鐘設置爲72M。而這個函數會被函數 SystemInit() 調用。
因此如今問題已經明確了,你的程序是初始化的時候須要調用 SystemInit() 函數進行系統時鐘的初始化。試了一下,問題完美解決。硬件
總結:
系統時鐘沒有初始化,須要在用戶程序中手動調用,這個大坑。request