1. 硬件平台
本例程使用的是 stm32f302rdt6 芯片,其时钟配置方法在其它st单片机中也类似。
2. 实验目的
使用外部 32mhz 晶振配置系统时钟为 72mhz。
3. 配置原理
根据stm32f302rd芯片的参考手册,可以查看该芯片的时钟树结构,这里我们配置系统时钟 sysclk 为72mhz,所以这里只需要修改 prediv 的分频值为4分频,其它 pll 倍频等配置和使用8mhz外部晶振时配置相同。
(1)打开工程里的 system_stm32f30x.c 文件,找到 setsysclock() 函数,进行时钟配置修改。这里我们只需要将外部时钟四分频后得到8mhz的时钟,所示我们只需要添加 rcc->cfgr2 |= (uint32_t)rcc_cfgr2_prediv1_div4;来实现时钟的分频。
static void setsysclock(void)
{
__io uint32_t startupcounter = 0, hsestatus = 0;
/******************************************************************************/
/* pll (clocked by hse) used as system clock source */
/******************************************************************************/
/* sysclk, hclk, pclk2 and pclk1 configuration -----------*/
/* enable hse */
rcc->cr |= ((uint32_t)rcc_cr_hseon);
/* wait till hse is ready and if time out is reached exit */
do
{
hsestatus = rcc->cr & rcc_cr_hserdy;
startupcounter ;
} while((hsestatus == 0) && (startupcounter != hse_startup_timeout));
if ((rcc->cr & rcc_cr_hserdy) != reset)
{
hsestatus = (uint32_t)0x01;
}
else
{
hsestatus = (uint32_t)0x00;
}
if (hsestatus == (uint32_t)0x01)
{
/* enable prefetch buffer and set flash latency */
flash->acr = flash_acr_prftbe | (uint32_t)flash_acr_latency_1;
/* hclk = sysclk / 1 */
rcc->cfgr |= (uint32_t)rcc_cfgr_hpre_div1;
/* pclk2 = hclk / 1 */
rcc->cfgr |= (uint32_t)rcc_cfgr_ppre2_div1;
/* pclk1 = hclk / 2 */
rcc->cfgr |= (uint32_t)rcc_cfgr_ppre1_div2;
/* pll configuration */
rcc->cfgr &= (uint32_t)((uint32_t)~(rcc_cfgr_pllsrc | rcc_cfgr_pllxtpre | rcc_cfgr_pllmull));
rcc->cfgr |= (uint32_t)(rcc_cfgr_pllsrc_prediv1 | rcc_cfgr_pllxtpre_prediv1 | rcc_cfgr_pllmull9);
/*!< prediv1 input clock divided by 4 */
rcc->cfgr2 |= (uint32_t)rcc_cfgr2_prediv1_div4; // add. by zhixiaoxing
/* enable pll */
rcc->cr |= rcc_cr_pllon;
/* wait till pll is ready */
while((rcc->cr & rcc_cr_pllrdy) == 0)
{
}
/* select pll as system clock source */
rcc->cfgr &= (uint32_t)((uint32_t)~(rcc_cfgr_sw));
rcc->cfgr |= (uint32_t)rcc_cfgr_sw_pll;
/* wait till pll is used as system clock source */
while ((rcc->cfgr & (uint32_t)rcc_cfgr_sws) != (uint32_t)rcc_cfgr_sws_pll)
{
}
}
else
{ /* if hse fails to start-up, the application will have wrong clock
configuration. user can add here some code to deal with this error */
}
}
(2)全局搜索 hse_value 空定义,在 stm32f30x.h 文件中,这里我们将外部晶振时钟修改为 32000000 hz
#if !defined (hse_value)
#define hse_value ((uint32_t)32000000) /*!< value of the external oscillator in hz */
#endif /* hse_value */
5. 查看总线时钟
在对stm32时钟进行配置后,为了进一步验证配置的正确性,我们可以使用仿真来查看系统各总线的时钟频率。首先在主函数中添加如下代码:
int main(void)
{
rcc_clockstypedef get_rcc_clock;
rcc_getclocksfreq(&get_rcc_clock); // 获取系统时钟配置
}
通过仿真可以查看各总线时钟的配置频率,如下图所示:
note:注意一定要修改宏 #define hse_value ((uint32_t)32000000) /!< value of the external oscillator in hz /的值,因为时钟使用该宏定义进行计算。
5. 慎入此坑
在时钟配置时,需要注意的一些问题:
(1)在时钟树任何一个倍频的环节都不能超频,即使后面分频系数较大,还是会导致时钟配置失败;
(2)在配置外部晶振四分频时,发现了一个诡异的问题,cfgr2寄存器一定要在cfgr寄存器之后,否则会导致cgfr2寄存器的值与配置的不符,至今不明其诡异之处?
/* pll configuration */
rcc->cfgr &= (uint32_t)((uint32_t)~(rcc_cfgr_pllsrc | rcc_cfgr_pllxtpre | rcc_cfgr_pllmull));
rcc->cfgr |= (uint32_t)(rcc_cfgr_pllsrc_prediv1 | rcc_cfgr_pllxtpre_prediv1 | rcc_cfgr_pllmull9);
/*!< prediv1 input clock divided by 4 */
rcc->cfgr2 |= (uint32_t)rcc_cfgr2_prediv1_div4; // add. by zhixiaoxing
『本文转载自网络,u球体育app下载的版权归原作者所有,如有侵权请联系删除』