STM32 系統時鐘(SysTick)設置雷區

昨天在設置 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

相關文章
相關標籤/搜索