STM32学习之路-RCC

发布者:TranquilDreamer最新更新时间:2022-10-20 来源: csdn关键字:STM32  学习之路  RCC 手机看文章 扫描二维码
随时随地手机看文章

RCC-复位和时钟控制.主要看下时钟控制这部分

系统时钟树:

有三种时钟源可以驱动系统时钟(SYSCLK)


分别是HSI振荡器、HSE振荡器、PLLCLK


HSI时钟信号:由内部8MHZ的RC振荡器产生,可直接作为SYSCLK或者2分频以后给PLL当输入,当HSI作为PLL时钟的输入时,SYSCLK最大为64MHZ(8/2*16)


HSE时钟信号:由外部振荡器产生频率在4-16MHZ,在时钟控制寄存器RCC_CR中用HSERDY位用来指示高速外部振荡器是否稳定


在启动时,直到这一位被硬件置'1',时钟才背释放,如果在时钟中断寄存器RCC_CIR中允许产生中断,将会产生相应的中断。


HSE可以通过RCC_CR中的HSEON设置启动和关闭


在system_stm32f10x.c中系统时钟初始化函数:


void SystemInit (void)

{

  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */

  /* Set HSION bit */

  RCC->CR |= (uint32_t)0x00000001;

 

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */

#ifndef STM32F10X_CL

  RCC->CFGR &= (uint32_t)0xF8FF0000;

#else

  RCC->CFGR &= (uint32_t)0xF0FF0000;

#endif /* STM32F10X_CL */   

  

  /* Reset HSEON, CSSON and PLLON bits */

  RCC->CR &= (uint32_t)0xFEF6FFFF;

 

  /* Reset HSEBYP bit */

  RCC->CR &= (uint32_t)0xFFFBFFFF;

 

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

  RCC->CFGR &= (uint32_t)0xFF80FFFF;

 

#ifdef STM32F10X_CL

  /* Reset PLL2ON and PLL3ON bits */

  RCC->CR &= (uint32_t)0xEBFFFFFF;

 

  /* Disable all interrupts and clear pending bits  */

  RCC->CIR = 0x00FF0000;

 

  /* Reset CFGR2 register */

  RCC->CFGR2 = 0x00000000;

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

  /* Disable all interrupts and clear pending bits  */

  RCC->CIR = 0x009F0000;

 

  /* Reset CFGR2 register */

  RCC->CFGR2 = 0x00000000;      

#else

  /* Disable all interrupts and clear pending bits  */

  RCC->CIR = 0x009F0000;

#endif /* STM32F10X_CL */

    

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)

  #ifdef DATA_IN_ExtSRAM

    SystemInit_ExtMemCtl(); 

  #endif /* DATA_IN_ExtSRAM */

#endif 

 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */

  /* Configure the Flash Latency cycles and enable prefetch buffer */

  SetSysClock();

 

#ifdef VECT_TAB_SRAM

  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */

#else

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */

#endif 

}


可以看到相关的寄存器配置,具体的配置可以看STM32的datasheet

setSysClock()函数


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


这里就是选择系统的时钟频率函数,默认情况下是72MHZ

在system_stm32f10x.c中可以看到


/* #define SYSCLK_FREQ_HSE    HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz  24000000 */ 

/* #define SYSCLK_FREQ_36MHz  36000000 */

/* #define SYSCLK_FREQ_48MHz  48000000 */

/* #define SYSCLK_FREQ_56MHz  56000000 */

#define SYSCLK_FREQ_72MHz  72000000

接下来就是SetSysClockTo72()的内容了

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);

 

  /* 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 */

    FLASH->ACR |= FLASH_ACR_PRFTBE;

 

    /* Flash 2 wait state */

    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;

      

    /* PCLK2 = HCLK */

    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

    

    /* PCLK1 = HCLK */

    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

 

#ifdef STM32F10X_CL

    /* Configure PLLs ------------------------------------------------------*/

    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */

    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */

        

    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |

                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);

    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |

                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);

  

    /* Enable PLL2 */

    RCC->CR |= RCC_CR_PLL2ON;

    /* Wait till PLL2 is ready */

    while((RCC->CR & RCC_CR_PLL2RDY) == 0)

    {

    }

    

   

    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 

    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);

    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 */

    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)0x08)

    {

    }

  }

  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 */

  }

}

#endif


这函数就干了一下的事情:

(1)使能HSE


(2)等待高速外部晶振准备就绪


(3)使能FLASH的预取功能


(4)设置FLASH延迟2个周期


(5)设置AHB时钟(HCLK)为系统时钟(SYSCLK)


(6)设置 PCLK2 = HCLK


(7)设置 PCLK1 = HCLK


(8)设置PLL为HSE的9倍频(8*9=72)


(9)使能PLL


(10)等待PLL准备好


(11)设置PLL为系统时钟源


(12)判断PLL是否为系统时钟


关键字:STM32  学习之路  RCC 引用地址:STM32学习之路-RCC

上一篇:STM32学习之路-不得不说的SysTick时钟
下一篇:STM32学习之路-外部中断(2)

推荐阅读最新更新时间:2024-11-10 10:35

嵌入式stm32学习:DMA-存储到外设
bsp_usart_dma.h #ifndef __USART_DMA_H #define __USART_DMA_H #include stm32f4xx.h #include stdio.h //USART #define DEBUG_USART USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_RX_GPIO_PORT GPIOA #define DEBUG_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOA #define DE
[单片机]
字符转整型STM32史上最短 字符转整形 简简单单
一直奇怪为什么stm32处理数据那么麻烦,要指针数组判断等等跳来跳去的。 直到今天,我发现了 #include “string.h” #include “stdlib.h” !!! 那我就可以两句话搞定我的数据了!!! 而不是像之前那样子那么麻烦了:STM32字符转整型处理 ’ stm32c语言字符转正型,并且进行数据分割 #include string.h #include stdlib.h u8 DATA = X12Y34Y56Y78 ; int shuju_chuli(const char *shuju,char zifu ) { char *shu_ju_1=strchr(shuju,zifu)+1; /
[单片机]
字符转整型<font color='red'>STM32</font>史上最短 字符转整形 简简单单
基于stm32的can总线彻底研究
1、CAN总线的初始化 void can_init(void) { CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; /* CAN register init */ CAN_DeInit(); CAN_StructInit(&CAN_InitStructure); /* CAN cell init */ CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式 CAN_InitStructure.CAN_ABOM=DISA
[单片机]
基于<font color='red'>stm32</font>的can总线彻底研究
STM32-时钟树
学习一个硬件,首先要把它的时钟单元弄的清晰一点,这会有助于加快你的学习进度,一开始我也有点迷糊,感觉STM32的时钟系统挺复杂,挺难懂的,但是深入接触了之后,发现也是挺简单的,可能一开始没有仔细看的原因 时钟系统就相当于人类的心跳一样,它为整个硬件系统提供时钟周期,只有它的正常运行,系统或者说片上系统才能够正常的工作。 首先,应该找到时钟源,也就是心跳的发源地,STM32有4个时钟源,分别是内部高速时钟,内部低速始终,外部高速时钟,外部低速时钟,其中外部高速时钟和外部低速始终是由片外晶体振荡器提供的,片内的时钟系统由内部RC震荡器提供。下面贴上STM32的时钟树框图: 如果早期看不明白,也不用着急去弄明白了,等到使用的时候自然
[单片机]
【菜鸟入门】stm32 之 实时时钟
经过这么10天的瞎搞,我的库已经初具规模了,于是,不用每次都把所有的文件copy过去,直接在Option里面把path给加上就ok了。 RTC的时钟配置,RTC的时间寄存器是2个32位的寄存器,无非就是一个计数器,大概可以这样理解吧,我们先看看时钟吧 RTC的时钟可以从这3路来,我们需要PTCSEL寄存器来进行设置, 上面这个图是摘自李想老师的课件里面的,我觉得这个是做的相对好的! 位了保证RTC正常工作,我们需要在系统断电时,RTC不受影响,当然我们一般都需要接一个Battery,作为rtc的后备电源,这里设计到电源管理,我们先来看看电源管理里面关于rtc的 只要我们把第八位置1我们就可以对其进行正常供电,我
[单片机]
【菜鸟入门】<font color='red'>stm32</font> 之 实时时钟
STM32速成笔记(3)—中断
一、什么是中断 首先介绍一下什么是中断。在实际开发过程中,中断是很有必要的。比如需要针对某种特殊情况进行快速响应,单纯的使用一个while轮询似乎并不能满足。中断的概念非常好理解,举个经典例子。比如你在家里看电视,忽然有人敲门,你临时把电视暂停了,转去开门。开完门之后再次回来继续看电视。 中断也就是这种流程。看电视的行为就类似于程序中main函数的while,轮询执行业务。忽然有人敲门,对应程序运行过程中忽然产生了一个中断请求。此时暂停电视,对应于此时程序中断当前的业务,转而去处理中断业务(开门)。最后,中断业务处理完成后,再继续执行main函数while轮询中的业务。简单用一个图来表示一下 中断概念示意图 根据中文参
[单片机]
<font color='red'>STM32</font>速成笔记(3)—中断
CORTEX-M3与STM32_M3内核STM32的三相多功能电能表解决方案
电能表作为电能计量的基本设备,受到国家电力部门的长期重视,电能表生产企业更是不遗余力地寻求设计与开发性能俱佳且成本更低的解决方案。目前国内的电能表设计已经走过了由8位MCU向通用DSP甚至专用DSP的变革,通用DSP的应用方案的劣势在于DSP的专业应用和嵌入程度不够深的问题,成本偏高;而专用 DSP功能相对固定,这样给电能表设计和生产厂家带来功能差异化空间不足的困难。基于ARM的方案也已经出现,但是适合应用的ARM7 TDMI在性能上不尽人意,同时外设资源不足;而更高端的ARM9系统的复杂程度很高,成本也较高。选择一颗合适且低成本的微处理器日益成为电能表行业的关键所在,直到意法半导体公司(STMicroelectronic公司,下
[单片机]
CORTEX-M3与STM32_M3内核<font color='red'>STM32</font>的三相多功能电能表解决方案
STM32 usb_pwr.c文件分析
usb_pwr.c 这个文件看文件名就知道跟功耗有关了,有很多的状态:上电、掉电、挂起、恢复。 当首先是usb的上电和断电函数的定义了。 usb上电函数如下: /******************************************************************************* * Function Name : PowerOn * Description : 上电 * Input : None. * Output : None. * Return : USB_SUCCESS. *******************************************
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved