STM32学习日记——时钟初始化


前言

自己学习stm32的一些小笔记
下面这些内容需要 STM32中文参考手册_V10配合使用
资料连接:
https://pan.baidu.com/s/1uY7SjmHKLwy3xbqYulnJPw 提取码 uk62

一、STM32F103ZE时钟初始化

 /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;//对CR寄存器进行操作 8mhz振荡器
  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;//使HSEON, CSSON and PLLON位置0

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;//使HSEBYP 置0

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;//使PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE置零
  ....
 SetSysClock();

首先,这些是stm32时钟初始化的部分语句,这些是直接操作RCC寄存器中的RCC_CR ,RCC_CFGR,RCC_CIR等等寄存器。这些寄存器都是32位的
这些寄存器详细信息可以在stm32中文参考手册中找到,罗列上述用到的寄存器信息(详细信息会写在文章末尾)
在这里插入图片描述
首先看到寄存器是32位,首先打开HSEON开启内部8MHZ振荡器
RCC->CR |= (uint32_t)0x00000001;RCC->CR是一个结构体指向CR寄存器,与0x00000001进行或运算,就是把最后一位赋值给1即HSION=1;
ps:(0x00000001是一个十六进制的00000001,这个是表示每一位上的数字代表的二进制的0000的四位,所以每一个代表四个二进制位,一共8个数,所以4*8=32对应寄存器的32位,)。
由此,可以根据寄存器位来编写我们所需要的寄存器位。将相应的位置零之后进入到SetSysClock();

二、SetSysClock()解读

1.引入库

代码如下(示例):

#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
#endif

这是配置相应频率的时钟,在这里直接使用系统初始配置的72M时钟,(修改其他频率可以直接修改宏定义)。

2.SetSysClockTo72()解读

在这里插入图片描述

代码如下(示例):

RCC->CR |= ((uint32_t)RCC_CR_HSEON);//第16位使能
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)
  {
    **/* FLASH先不管 */**
    FLASH->ACR |= FLASH_ACR_PRFTBE;
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//HCLK = SYSCLK要使它相等,需要不分频
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//同上
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//第十位置1,表示HCLK 2分频
     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);//因为HSE默认8Mhz 所以9倍频输出为72Mhz    
```RCC->CR |= RCC_CR_PLLON;//配置完打开PLL

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* Select PLL as system clock source *///设置pll时钟
    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)0x08)
    {}
/********RCC_CR寄存器宏定义**********/
#define  RCC_CR_HSION                        ((uint32_t)0x00000001)      
#define  RCC_CR_HSIRDY                       ((uint32_t)0x00000002)       
#define  RCC_CR_HSITRIM                      ((uint32_t)0x000000F8)      
#define  RCC_CR_HSICAL                       ((uint32_t)0x0000FF00)        
#define  RCC_CR_HSEON                        ((uint32_t)0x00010000)        
#define  RCC_CR_HSERDY                       ((uint32_t)0x00020000)        
#define  RCC_CR_HSEBYP                       ((uint32_t)0x00040000)        
#define  RCC_CR_CSSON                        ((uint32_t)0x00080000)      
#define  RCC_CR_PLLON                        ((uint32_t)0x01000000)        
#define  RCC_CR_PLLRDY                       ((uint32_t)0x02000000) 
//
#define  RCC_CFGR_HPRE_DIV1                  ((uint32_t)0x00000000)
#define  RCC_CFGR_PPRE2_DIV1                 ((uint32_t)0x00000000)
#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00000400)
#define  RCC_CFGR_PLLSRC_HSE                ((uint32_t)0x00010000)  
#define  RCC_CFGR_PLLMULL9                  ((uint32_t)0x001C0000) 
#define  RCC_CFGR_SW_PLL                     ((uint32_t)0x00000002) 

总结

这种将数值代入,跟寄存器位的功能对比就一目了然,记忆更深刻。

在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32f407的时钟初始化包括以下几个步骤: 1. 使能HSE时钟:HSE(High Speed External)是外部高速晶振,需要先使能HSE时钟。 ``` RCC->CR |= RCC_CR_HSEON; // 使能HSE时钟 while(!(RCC->CR & RCC_CR_HSERDY)); // 等待HSE稳定 ``` 2. 配置PLL时钟STM32f407的主频通常是通过PLL时钟倍频得到。需要选择合适的倍频系数、分频系数和PLL时钟源。 ``` RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLQ); // 清零PLL配置位 RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE; // 选择HSE为PLL时钟源 RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_1; // PLL输入分频系数 RCC->PLLCFGR |= RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_3 | RCC_PLLCFGR_PLLN_2 | RCC_PLLCFGR_PLLN_0; // PLL倍频系数 RCC->PLLCFGR &= ~RCC_PLLCFGR_PLLP; // PLL输出分频系数 RCC->PLLCFGR |= RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLQ_1; // PLL时钟输出分频系数 RCC->CR |= RCC_CR_PLLON; // 使能PLL时钟 while(!(RCC->CR & RCC_CR_PLLRDY)); // 等待PLL稳定 ``` 3. 配置系统时钟:将PLL时钟作为系统时钟,并设置合适的AHB、APB1和APB2分频系数。 ``` RCC->CFGR &= ~(RCC_CFGR_HPRE | RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2); // 清零分频系数 RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // AHB时钟不分频 RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; // APB1时钟分频4 RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // APB2时钟分频2 RCC->CFGR |= RCC_CFGR_SW_PLL; // 选择PLL时钟作为系统时钟 while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 等待PLL时钟成为系统时钟 ``` 以上是STM32f407的时钟初始化步骤,需要根据具体的应用场景进行调整。注意在使用PLL时钟之前必须先使能HSE时钟,并等待HSE稳定。在修改时钟分频系数和时钟源时需要先将对应的配置位清零,再设置新的分频系数和时钟源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值