stm32的外部晶振不起振以及更改外部晶振值的问题

今天有人问我关于外部晶振不起振以及如歌更改32的外部晶振,在此我做一个简单的记录(以stm32f1系列为例,其余类似)。

1.晶振不起振

        此次遇到的问题倒不是出在电路上,实际上还是软件上的问题。画的新板子,换了一块贴片的晶振,与原来的直插式有点区别。首先,打印当前系统时钟频率,调用函数:

RCC_GetClocksFreq(&RCC_Clocks);

printf("SYSCLK_Frequency: %d\r\n",RCC_Clocks.SYSCLK_Frequency);

结果打出来的是:

SYSCLK_Frequency: 8000000

        事实上,正常的f1系列的主频应该为72Mhz,所以应该打印出72000000。由此判断,应该是晶振出现了毛病。于是准备开仿真调试一下,结果尴尬了,居然打印除了72000000?你说啥?这就不懂了,怎么仿真的时候正常,下进去的程序就不行了?仔细回想一下32的启动过程,想到系统初始化的时候在main函数调用之前会进入SystemInit函数,如下(文件为startup_stm32f10x_hd.s启动文件):

stm32的外部晶振不起振以及更改外部晶振值的问题_第1张图片
启动文件源码截图

        从这里入手,经过层层深入,根据宏定义,发现其最终调用了SetSysClockTo72()函数,里面有一个等待HSE(外部高速晶振)起振的超时:

stm32的外部晶振不起振以及更改外部晶振值的问题_第2张图片
SetSysClockTo72()函数

        在仿真的过程中,由于使用单步调试,在进入第996行的while循环中,其实HSE_STARTUP_TIMEOUT已经失去了它的作用(因为鼠标点一下的时间对于单片机来说已经过去很久了,所有这里没用了),这也算是仿真和实际运行的一大区别吧。结合上述的现象,猜一猜或许是给的晶振允许起振的时间不够?打开HSE_STARTUP_TIMEOUT,其实就是一个宏定义,默认是0x0500:

/**

* @brief In the following line adjust the External High Speed oscillator (HSE) Startup

  Timeout value

  */

#define HSE_STARTUP_TIMEOUT  ((uint16_t)0x0500) /*!< Time out for HSE start up */

试着加大,改成0xf000,再次编译,下载,好了,终于成功打印出了72000000。

2.更改外部晶振值

        这个问题相对于上一个问题就简单了,如果保持系统的主频72Mhz不变,那么改变外部晶振之后(如12Mhz),只需要改变两个宏定义就可以了。首先是stm32f10x.h文件中,大概在119行的位置,将HSE_VALUE的值改为你所更换的晶振的值,原来(8Mhz)是8000000,此时(12Mhz)是12000000:

HSE_VALUE宏定义

        其次,在system_stm32f10x.c文件中,依然在SetSysClockTo72()函数里,大概在1056行的位置,将倍频系数RCC_CFGR_PLLMULL9改成RCC_CFGR_PLLMULL6就可以了。默认是9倍的原因是外部晶振8Mhz*9=72Mhz,此时外部晶振为12Mhz,改成RCC_CFGR_PLLMULL6即可达到12Mhz*6=72Mhz的效果:

倍频系数的更改

至此,两个问题解决。

你可能感兴趣的:(stm32的外部晶振不起振以及更改外部晶振值的问题)