<p>基于特定的开发板上的时钟策略:<p><img src="https://6.eewimg.cn/news/uploadfile/2021/1104/059935.png" alt=""/><p>倍频/分频系数需要在使能 PLL 之前进行配置,所以需要在 Open PLL 之前将所有系统的时钟分频器系数以及PLL的倍频系数配置好。整个时钟的配置流程如下所示:<p><br/><p>(1) 开启HSE,等待HSE稳定 <p>(2) 设置APB2、APB1、AHB分频系数 <p>(3) 设置PLL的时钟来源和PLL的倍频系数 <p>(4) 开启PLL,等待PLL稳定 <p><br/><p>(5) 设置SYSCLK源为 PLL 的输出,读取时钟切换状态,确保PLLCLK被选为系统时钟<p><br/><p>(1) OSC_IN/OSC_OUT 上外接 8M 晶振。要使用外接晶振,上电后(默认使用 8M 的HSI),首先需要使能 HSE,位于RCC_CR寄存器的 bit16,即:<p><br/><p> /* Enable HSE */ <p> RCC->CR |= ((uint32_t)RCC_CR_HSEON);<p>接着需要等待外部时钟 HSE 稳定(轮询 RCC_CR寄存器的 bit17):<p><br/><p> /* Wait till HSE is ready and if Time out is reached exit */<p> do<p> {<p> HSEStatus = RCC->CR & RCC_CR_HSERDY;<p> StartUpCounter++; <p> } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));<p>(2) 接着配置 AHB 时钟为 SYSCLK ,即 AHB 分频系数为1,不分频,SYSCLK直接供给SDIO, FSMC, AHB BUS, FCLK并直接作用于APB1/APB2的输入端:<p><br/><p> /* HCLK = SYSCLK */<p> RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;<p>配置高速APB2 分频系数为1,即 SYSCLK ->AHB->APB2:<p><br/><p> /* PCLK2 = HCLK */<p> RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;<p>由于APB1的时钟最大频率为 36MHz,当前希望输入的SYSCLK为72MHz(最大频率),故需要配置低速 APB1 分频系数为2,即两分频:<p><br/><p> /* PCLK1 = HCLK */<p> RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;<p>(3) 继续,配置 PLL 时钟源,以及 PLL 的倍频系数:<p><br/><p>首先将需要配置的 bit 先清零:<p><br/><p> RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));<p>接着<p><br/><p>A. 选择HSE 时钟为 PLL 的输入 ,RCC_CFGR 的 bit16. <p><br/><p>B. 对HSE输入晶振频率不分频,直接供给 PLL 作为输入<p><br/><p>C. 由于外部晶振时钟为 8M,得到 72MHz 最大时钟频率,故设置 PLL 倍频系数为 9:<p><br/><p> RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);<p>至此,分频/倍频系数基本设置完毕(未设置的部分采取系统 Reset 后的默认值)<p><br/><p>(4) 开启 PLL 并等待稳定<p><br/><p> /* Enable PLL */<p> RCC->CR |= RCC_CR_PLLON;<p> <p> /* Wait till PLL is ready */<p> while((RCC->CR & RCC_CR_PLLRDY) == 0)<p> {<p> }<p>(5) 切换系统时钟源为 PLL 的输出:<p><br/><p> /* Select PLL as system clock source */<p> RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));<p> RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; <p>轮询等待生效:<p><br/><p> /* Wait till PLL is used as system clock source */<p> while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)<p> {<p> }<p><br/><p>至此时钟配置完毕,本次配置是基于板载外接 8MHz 晶振进行的配置,若是板载其他的频率的晶振,只需改变 PLL 的倍频系数即可,此刻,系统运行在最大支持频率 72MHz 下。<p><br/><p>完整的代码如下:<p><br/><p>static void SetSysClockTo72(void)<p>{<p> __IO uint32_t StartUpCounter = 0, HSEStatus = 0;<p> <p> /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ <p> /* Enable HSE */ <p> RCC->CR |= ((uint32_t)RCC_CR_HSEON);<p> <p> /* Wait till HSE is ready and if Time out is reached exit */<p> do<p> {<p> HSEStatus = RCC->CR & RCC_CR_HSERDY;<p> StartUpCounter++; <p> } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));<p> <p> if ((RCC->CR & RCC_CR_HSERDY) != RESET)<p> {<p> HSEStatus = (uint32_t)0x01;<p> }<p> else<p> {<p> HSEStatus = (uint32_t)0x00;<p> } <p> <p> if (HSEStatus == (uint32_t)0x01)<p> {<p> /* Enable Prefetch Buffer */<p> FLASH->ACR |= FLASH_ACR_PRFTBE;<p> <p> /* Flash 2 wait state */<p> FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);<p> FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; <p> <p> <p> /* HCLK = SYSCLK */<p> RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;<p> <p> /* PCLK2 = HCLK */<p> RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;<p> <p> /* PCLK1 = HCLK */<p> RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;<p> <p> <p> /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */<p> RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |<p> RCC_CFGR_PLLMULL));<p> RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);<p> <p> /* Enable PLL */<p> RCC->CR |= RCC_CR_PLLON;<p> <p> /* Wait till PLL is ready */<p> while((RCC->CR & RCC_CR_PLLRDY) == 0)<p> {<p> }<p> <p> /* Select PLL as system clock source */<p> RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));<p> RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; <p> <p> /* Wait till PLL is used as system clock source */<p> while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)<p> {<p> }<p> }<p> else<p> { /* If HSE fails to start-up, the application will have wrong clock <p> configuration. User can add here some code to deal with this error */<p> }<p>} <p>STM32三种启动模式:<p>STM32三种启动模式对应的存储介质均是芯片内置的,它们是:<p>1)用户闪存 = 芯片内置的Flash。<br/>2)SRAM = 芯片内置的RAM区,就是内存啦。<br/>3)系统存储器 = 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序。这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区。<p><br/><p>在每个STM32的芯片上都有两个管脚BOOT0和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序,见下表:<p><br/>BOOT1=x BOOT0=0 从用户闪存启动,这是正常的工作模式。<br/>BOOT1=0 BOOT0=1 从系统存储器启动,这种模式启动的程序功能由厂家设置。<br/>BOOT1=1 BOOT0=1 从内置SRAM启动,这种模式可以用于调试。<p>----------------------------------------------------------------------------------------------------------------------------- <p>现有的参考设计都是在STM32的启动选择引脚BOOT0和BOOT1上使用了跳帽,用以人工选择STM32的启动方式,但是在实际应用中这种设计就显得冗余,所以这里顺带研究了一下STM32的启动方式。<p><br/><p>所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存。用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式。<p> <br/>1. Main Flash memory<p>是STM32内置的Flash,一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。<p> <br/>2. System memory<p>从系统存储器启动,这种模式启动的程序功能是由厂家设置的。一般来说,这种启动方式用的比较少。<p><br/><p>系统存储器是芯片内部一块特定的区域,STM32在出厂时,由ST在这个区域内部预置了一段BootLoader,也就是我们常说的ISP程序,这是一块ROM,出厂后无法修改。<p><br/><p>一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤:<p>Step1:将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader<p>Step2:最后在BootLoader的帮助下,通过串口下载程序到Flash中<p>Step3:程序下载完成后,又有需要将BOOT0设置为GND,手动复位,这样,STM32才可以从Flash中启动<p><br/><p>可以看到,利用串口下载程序还是比较的麻烦,需要跳帽跳来跳去的,非常的不注重用户体验。<p><br/><p>3. Embedded Memory<p>内置SRAM,既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。<p><br/><p>假如我只修改了代码中一个小小的地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/191460.html