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