原创 stm32库函数学习篇----RCC模块

2012-11-29 17:04 1756 13 16 分类: MCU/ 嵌入式 文集: 轉載

 

其实接触stm32单片机已经有很久了,但就是一直处在入门级的水平不得前进,直接原因是从未用它做个实际的项目,隔段时间沾一下,到目前为止还是一片混沌,就能操作一下IO口而已。最开始接触它是不喜欢用库函数的,总觉得要记的数据结构东西太多,不如用寄存器操作来的简单实在。但是,看了芯片手册后彻底心死了,每个外设寄存器多的数不清,而且功能都非常复杂,唉,还是选择库函数吧。这两天琢磨了不少时间,就学习了它的时钟配置部分,附带点亮一个led灯,很是尴尬,但也记录一下,真正开始我的学习旅程。


上面是stm32时钟布置的局部图,有几个时钟的名称必须注意,它们是:SYSCLK、HCLK、PCLK1还有PCLK2。一定要对准他们指的是那个时钟,因为库函数里面就是用他们的名字做指示。

我用的是3.5版本的库,每次都是用里面的模板做工程。而且我手上的板子是正点原子的F103RBT6,下面就以它作为主体进行时钟配置。

首先,如果在自己的main函数中不作时钟配置,默认时钟是怎么样的呢?

看模板中main函数里这么一段代码

int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */  

也就是说,进入main函数前,系统已经做了时钟配置,调用的是SystemInit()函数,那么我们就进入此函数看过究竟。

 

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
}

 其他的我先都不想管,我就看准了这几句:

 /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
那么就是告诉我们,给HCLK、PCLK1和PCLK2的配置是调用 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
 
 /* If none of the define above is enabled, the HSI is used as System clock
    source (default after reset) */
}

这其实就告诉我们,SYSCLK的设置就是根据我们定义来设定,如果定义了SYSCLK_FREQ_HSE
,那么SYSCLK就是HSE(默认8MHz),如果定义了SYSCLK_FREQ_24MHz,那么SYSCLK就是24MHz,一次类推。而设置时钟是靠SetSysClockToXX()函数来实现的!

好了,既然这样,我就想继续跟进,去找SetSysClockToXX(),但是惊讶地发现,提示此函数没有定义!为啥,那是因为我去找的刚好是未被编译的,当然找不到定义,事实上这些XX函数都存在在system_stm32f10x.c文件中,但是只有一个能被跟踪找到,那就是对应的宏被定义了的那个。这些定义到底在哪?跟进!得到如下:

//system_stm32f10x.c文件

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
 #define SYSCLK_FREQ_24MHz  24000000
#else
/* #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
#endif
这下我想起来了,每次用keil建立工程,总是要求预先定义两个宏:USE_STDPERIPH_DRIVER和STM32F10X_MD,原来这儿就体现出作用了!

因为我的芯片是STM32F10X_MD型,所以SYSCLK就被选择了72MHz!

至于static void SetSysClockTo72(void)此函数到底是怎么把SYSCLK设置成为72MHz的,我懒得去管了,代码很长,也在system_stm32f10x.c文件中,说实话我真没兴趣去搞明白,但要知道,在这个函数里,顺便把HLCK、PCLK1和PCLK2都做了默认设置!

话说回来,我真不想去看寄存器操作的,但是,这个函数里面有一个我认为是ST公司的工程师们大意写错了的地方,如下:

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

从时钟布局图中可以知道,PCLK1的最大时钟为36MHz,PCLK1怎么能等于HCLK呢?此时的HCLK可是72MHz,从下面代码也可看到,确实2分频嘛,那就是36MHz,肯定是注释错了!

以上就是今天看了近一天的库函数的收获,关于RCC,收获微小,但慢慢来吧!

文章评论3条评论)

登录后参与讨论

用户429514 2012-12-4 21:52

楼主,我总觉得用库函数不是很爽,虽然寄存器操作有点麻烦。你觉得呢?

用户429514 2012-12-4 21:50

正点原子,还可以

用户1411206 2012-12-4 09:38

想问各位大虾一下,哪里可以买到既好用又便宜的STM32开发板啊?
相关推荐阅读
用户580190 2012-12-21 16:34
如何自动检测串行通讯中的波特率
最近有个项目上要用到自动检测串行通讯中的波特率,关于这方面的资料好像比较的少,广州周立功单片机发展有限公司有一文章是介绍这个的。我想的方法比较的简单,能实现,但是不是很理想,具体做法是,由于我上位...
用户580190 2012-12-06 11:51
将win7电脑无线网变身WiFi热点,让手机、笔记本共享上网
将win7电脑无线网变身WiFi热点,让手机、笔记本共享上网 将win7电脑变身WiFi热点,让手机、笔记本共享上网 用win7建立无线局域网,可以共享上网可以局域网游戏。 开启windows 7的...
用户580190 2012-12-06 11:39
ucosii 建立一个新任务
建立任务 /***************************************************************************************** 125 ...
用户580190 2012-12-06 11:34
视频压缩编解码标准综述
摘要:本文从目前视频流传输中最为重要的编解码标准国际电联的H.261、H.263,运动静止图像专家组的M-JPEG,国际标准化组织运动图像专家组的MPEG系列标准,以及在互联网上被广泛应用的Real ...
用户580190 2012-12-06 11:28
视频格式
    ASF   ASF 是 Advanced Streaming format 的缩写,由字面(高级流格式)意思就应该看出这个格式的用处了吧。说穿了 ASF 就是 MICROSOFT 为了和现在的...
用户580190 2012-12-06 11:18
图像和图形知识
1.有关色彩的基本常识   我们知道,只要是彩色都可用亮度、色调和饱和度来描述,人眼中看到的任一彩色光都是这三个特征的综合效果。那么亮度、色调和饱和度分别指的是什么呢?  ★ 亮度:是光作用于人眼时所...
我要评论
3
13
关闭 站长推荐上一条 /2 下一条