Pingf的stm32学习笔记之GPIO_Part2[0913]

本文详细解析了STM32F103系列微控制器的时钟配置过程,包括如何启用外部高速时钟(HSE)、配置PLL以达到72MHz的系统时钟频率,以及相关的寄存器设置。
GPIO Part 2

【前文中有几处错误,已更正,另外以后关于stm32的代码若未明确声明都是针对103系列的】
接着上文中未分析完的部分,

首先回顾下SystemInit中的几步

1 Set HSION bit 

2. Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits

3. Reset HSEON, CSSON and PLLON bits 

4. Reset HSEBYP bit 

5. Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits 

6. Disable all interrupts and clear pending bits 

7. sysclock的配置

可以看到在前面几步时只有HSIONSET【置位了】,这说明开始用的是HIS

其它诸如PLL什么的都暂时不用到了后面提到的sysclock配置时会把时钟调整到72Mhz,当然PLL是肯定要用的。

 

这里简单说明下具体寄存器的配置

这里面捡两个重点说一下

下面这是RCC_CR[CR对应的是control register]



之所以为control就是为了说明启用与否等功能用的。

可以看到里面有很多ONRDY[就是ready]分别用来说明该时钟源是否开启,以及其状态的检测

HSI相关的东西似乎多了点,主要是因为HIS是内置的时钟源,可能会因为制程等产生差异,在器件初始时HSICAL里面会载入the factory calibration value【应该是叫做工厂校准值吧】,但因为湿度温度可能会产生影响,我们可以通过设置HSITRIMHIS校准至一个较为标准的频率【而HSITRIM中步进为40Khz{据说在校准后精度依旧一般}

另外还有个CSS代表的是Clock security system它可以对信号源进行检测,保证其正确性【似乎这么说不是很准确,感觉应该是有些跳沿检测或同步的东西】

还有就是HSE BYPBYP代表ByPass旁路】,当使用别的时钟源而非晶振时启用此选项

 

下面看下RCC_CFGR[configuration register]


其中PRE代表prescaler,是分频用的度量,具体看我前文的那个时钟树图吧

出了用于分频的系数之外,CFGR中还要配置的是信号的选择

比如MCOPLLSRCSWSWS则是硬件设置的用来反映SW的状态】都是用来选择不同的时钟源的,具体看还是看前文的那个时钟树图

另外补充说明下几个缩写PPRE2,PPRE1,HPRE分别对应了AHBAPB1,APB2的分频设置项

 

其它的寄存器像RCC_CIR之类就不多赘述了

 

下面再看下SetSysClock
ContractedBlock.gifExpandedBlockStart.gifCode
static void SetSysClock(void)
{
#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
}

我们在system_stm32f10x.c中定义了SYSCLK_FREQ_72MHz所以展开下SetSysClockTo72

具体如下

ContractedBlock.gifExpandedBlockStart.gifCode
static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter 
= 0, HSEStatus = 0;
  RCC
->CR |= ((uint32_t)RCC_CR_HSEON);
  
do
  {
    HSEStatus 
= RCC->CR & RCC_CR_HSERDY;
    StartUpCounter
++;  
  }
 
while((HSEStatus == 0&& (StartUpCounter != HSEStartUp_TimeOut));

  
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus 
= (uint32_t)0x01;
  }
  
else
  {
    HSEStatus 
= (uint32_t)0x00;
  }  

  
if (HSEStatus == (uint32_t)0x01)
  {
    FLASH
->ACR |= FLASH_ACR_PRFTBE;
    FLASH
->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH
->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
    RCC
->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
    RCC
->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    RCC
->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
    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);
    RCC
->CR |= RCC_CR_PLLON;
    
while((RCC->CR & RCC_CR_PLLRDY) == 0);
    RCC
->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC
->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
    
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08);
  }
  
else
  { 
    
while (1);
  }
}

前面用的是HSI,现在要换成HSE,并把PLLFLASH等的时钟配置好,而前面说道的RCC_CFGR则是这个函数主要针对的。

 

上面这个函式虽然复杂,但却很明了

其大致分为如下几步[只列出了正常状态下的步骤]

1.    HSE使能

2.    等待并检测HSE使能状态【还做了简单的超时检测。。吼吼。。XD

3.    HSE使能则进行如下

【1】    配置FLASH时钟,72Mhz要求两周期的等待,这点很是不如LM

【2】    配置AHB APB1APB2【里面的DIV什么的就是用来分频的系数】

【3】    配置PLL【这个是用来倍频的】

【4】    等待并检测PLL状态若是能则

(1)选择系统时钟

(2)没了。。。。。XD

应该很清楚了,关于RCC的配置就写到这里,有时间再继续。







转载于:https://www.cnblogs.com/pingf/archive/2009/09/13/1565897.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值