SetSysClockTo72(void) 解析
本帖最后由 yanjiesh 于 2013-12-3 10:46 编辑/**
* @briefSets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @paramNone
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON); // RCC_CR_HSEON 定义为 0x00010000, 即CR寄存器的第十六位设为1.R寄存器的第十六位设为1.
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY; // RCC_CR_HSERDY 定义为 ((uint32_t)0x00020000),即CR 寄存器的第十七位为1,表示External high-speed clock ready flag.
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); //HSE_STARTUP_TIMEOUT 定义为 ((uint16_t)0x0500) /*!< Time out for HSE start up */
if ((RCC->CR & RCC_CR_HSERDY) != RESET) //typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;换句话 成功了就执行以下内容
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01) //成功时,,,
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE; // #defineFLASH_ACR_PRFTBE ((uint8_t)0x10) /*!< Prefetch Buffer Enable */
/* ● 等待时间:可以随时更改的用于读取操作的等待状态的数量。
● 预取缓冲区(2个64位):在每一次复位以后被自动打开,由于每个缓冲区的大小(64位)与闪存的带宽相同,因此只通过需一次读闪存的操作即可更新整个缓冲区的内容。由于预取缓冲区的存在,CPU可以工作在更高的主频。CPU每次取指最多为32位的字,取一条指令时,下一条指令已经在缓冲区中等待。
● 半周期:用于功耗优化。
*/
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); //#defineFLASH_ACR_LATENCY ((uint8_t)0x03) /*!< LATENCY bits (Latency) */
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; //#defineFLASH_ACR_LATENCY_2 ((uint8_t)0x02) /*!< Bit 1 */
// 请教高手 FLASH->ACR 是一个寄存器吗? 好像手册里没能找到啊?哪位能告知下 谢谢。
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //#defineRCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!< SYSCLK not divided */
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; //#defineRCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!< HCLK not divided */
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; //#defineRCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!< HCLK divided by 2 */以上三个分频设置均在RCC_CFGR寄存器中。位置分别是:bit7:4的AHB分频;Bit13:11 的APB2 和 Bit 10:8 的 APB1。
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
/* #defineRCC_CFGR2_PREDIV2 ((uint32_t)0x000000F0) !< PREDIV2 bits 反相与后即0x0000 不分频 */
/*#defineRCC_CFGR2_PLL2MUL ((uint32_t)0x00000F00) !< PLL2MUL bits反相与后为0x0000,保留。*/
/* #defineRCC_CFGR2_PREDIV1 ((uint32_t)0x0000000F) !< PREDIV1 bits反相与后即0x0000 不分频。*/
/* #defineRCC_CFGR2_PREDIV1SRC ((uint32_t)0x00010000) bit16=1,反相与后表明HSE作为PREDIV1的时钟源 !< PREDIV1 entry clock source */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
/*#defineRCC_CFGR2_PREDIV2_DIV5 ((uint32_t)0x00000040) PREDIV2: 0x0100, 即5分频。< PREDIV2 input clock divided by 5 */
/*#defineRCC_CFGR2_PLL2MUL8 ((uint32_t)0x00000600) PLL2MUL:0x0110,即 PLL2 8倍频。!< PLL2 input clock * 8 */
/* #defineRCC_CFGR2_PREDIV1SRC_PLL2 ((uint32_t)0x00010000) bit16=1 表明PLL2 是 PREDIV1的输入时钟源。!< PLL2 selected as PREDIV1 entry clock source */
/*#defineRCC_CFGR2_PREDIV1_DIV5 ((uint32_t)0x00000004) PREDIV1:0x0100,即5分频。!< PREDIV1 input clock divided by 5 */
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/*PLL2和PLL3由HSE通过一个可配置的分频器提供时钟。必须在使能每个PLL之前完成PLL的配置(选择时钟源、预分频系数和倍频系数等),同时应该在它们的输入时钟稳定(就绪位)后才能使能。一旦使能了PLL,这些参数将不能再被改变。
当改变主PLL的输入时钟源时,必须在选中了新的时钟源(通过时钟配置寄存器(RCC_CFGR) 的PLLSRC位)之后才能关闭原来的时钟源。
如果使能了时钟中断寄存器(RCC_CIR),可以在PLL就绪时产生一个中断。
*/
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON; // #defineRCC_CR_PLL2ON ((uint32_t)0x04000000) /*!< PLL2 enable */
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* #defineRCC_CFGR_PLLXTPRE ((uint32_t)0x00020000) !< HSE divider for PLL entry */
/* #defineRCC_CFGR_PLLSRC ((uint32_t)0x00010000) !< PLL entry clock source */
/*#defineRCC_CFGR_PLLMULL ((uint32_t)0x003C0000) 0x0000 0000 0011 1100 0000 0000 0000 0000 !< PLLMUL bits (PLL multiplication factor) */
/* 以上操作即为复位相关设置住*/
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
/* #defineRCC_CFGR_PLLXTPRE_PREDIV1 ((uint32_t)0x00000000) !< PREDIV1 clock not divided for PLL entry */
/* #defineRCC_CFGR_PLLSRC_PREDIV1 ((uint32_t)0x00010000) !< PREDIV1 clock selected as PLL entry clock source */
/* #defineRCC_CFGR_PLLMULL9 ((uint32_t)0x001C0000) 0x0000 0000 0001 1100 0000 0000 0000 0000 PLLMUL: 0x0111 !< PLL input clock * 9 */
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/*PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */
/* Enable PLL */
/*#defineRCC_CR_PLLON ((uint32_t)0x01000000) 0x0000 0001 !< PLL enable */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
/* #defineRCC_CFGR_SW ((uint32_t)0x00000003) !< SW bits (System clock Switch)*/
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); //本句为设置HSI作为系统时钟
/* #defineRCC_CFGR_SW_PLL ((uint32_t)0x00000002) !< PLL selected as system clock */
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //本句设置PLL输出为系统时钟
/* Wait till PLL is used as system clock source */
/* #defineRCC_CFGR_SWS ((uint32_t)0x0000000C) !< SWS bits (System Clock Switch Status) */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) //如果检测到CFGR寄存器的bit3:2位是10--即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 */
}
} 自己补充一下 学了很久 但是一直能深入 阻碍主要是C语言的技能水平 逐步学习后 想与大家交流下 看来 此帖不吸引人 要么高手不愿赐教 要么新手也是看了头晕 呵呵 只当抛砖引玉了 {:lol:}
页:
[1]