昨天在设置 STM32F103 的系统时钟的时候,按照官方文档的方法进行设置,虽然系统时钟有效,但是原本设定为1s后执行的任务却延迟了九秒左右。百思不得其解,可以确定硬件是没有问题的。
以下是系统时钟的设置代码:
void clock_init(){
if (SysTick_Config(SystemCoreClock/CLOCK_SECOND)){
while (1);
}
}
SysTick_Config() 是系统时钟的设置函数,代码如下:
/**
* @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。
解决方法:
STM32F103内部是8M的震荡,通过倍频后可以达到72M。我所使用的固件库是3.5的版本,通过查看文件system_stm32f103x.c文件,可以发现下面宏定义:
#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() 函数进行系统时钟的初始化。试了一下,问题完美解决。
总结:
系统时钟没有初始化,需要在用户程序中手动调用,这个大坑。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。