你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32入门系列-STM32时钟系统,时钟初始化配置函数

[复制链接]
STMCU小助手 发布时间:2022-7-1 13:11
在前面推文的介绍中,我们知道STM32系统复位后首先进入SystemInit函数进行时钟的设置,然后进入主函数main。那么我们就来看下SystemInit()函数到底做了哪些操作,首先打开我们前面使用库函数编写的LED程序,在system_stm32f10x.c文件中可以找到SystemInit()函数,SystemInit()代码如下:

void SystemInit (void)
( ]- t3 Q* e; ]! d) j3 w2 ~{
0 U- A( [/ W: p! N/* Reset the RCC clock configuration to the default reset state(for debug purpose) */% s  _* C% n' L9 ?' ?; [9 Q  H
/* Set HSION bit */5 k7 ]: H2 g9 Q8 x( I' g7 u
RCC->CR |= (uint32_t)0x00000001;, C8 N6 H  d4 @3 m8 i' ^$ L, f, N8 _. G
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
4 v' y+ X, J0 z+ O+ Z# H$ t2 Y#ifndef STM32F10X_CL3 O- L- U; t5 ~0 w0 `4 @0 V- |7 s
RCC->CFGR &= (uint32_t)0xF8FF0000;
8 n' \4 v* z  r7 k#else
  U1 z( E! _0 a+ o0 @% ]  IRCC->CFGR &= (uint32_t)0xF0FF0000;
( g4 z6 N# _% B. C1 `#endif /* STM32F10X_CL */4 g4 {& E1 z. ^
/* Reset HSEON, CSSON and PLLON bits */
* C; K& v9 X; v( _RCC->CR &= (uint32_t)0xFEF6FFFF;
  ^: y; H& u8 z+ p" ]/* Reset HSEBYP bit */2 x. H/ v, l# u) C! Z0 l; |
RCC->CR &= (uint32_t)0xFFFBFFFF;0 }; s4 J) H) N6 k' C. L
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */- w; X' F& N+ I9 c7 ^  ^4 i
RCC->CFGR &= (uint32_t)0xFF80FFFF;* v9 s1 S1 |' q2 f8 q
#ifdef STM32F10X_CL- j/ p& \3 R' K& X
/* Reset PLL2ON and PLL3ON bits */1 T) K7 F6 \$ F
RCC->CR &= (uint32_t)0xEBFFFFFF; $ i$ L+ g) }* q+ A* m
/* Disable all interrupts and clear pending bits */
$ E9 M0 b0 g7 d4 F. P& JRCC->CIR = 0x00FF0000;
; y/ G1 ]" t  ~' s/ C- A/* Reset CFGR2 register */
5 H, w' b7 m+ K% f  U5 mRCC->CFGR2 = 0x00000000;# p* j3 C  U. K5 L" U" \) v/ J
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined
% o0 U2 h' p0 v6 ISTM32F10X_HD_VL)
* A. v: o& O. m6 R: W/* Disable all interrupts and clear pending bits */
: H. F$ z- |/ w+ W* L) H6 G) r7 sRCC->CIR = 0x009F0000;
  }6 a1 }( V7 s! b/ ?5 A6 m3 K/* Reset CFGR2 register */" _4 f$ j. j0 z- E4 J1 A- d' B, u0 f
RCC->CFGR2 = 0x00000000;8 \2 X: e& }; s$ c( l7 G4 k& q
#else6 b& l* D% U# t3 b" s
/* Disable all interrupts and clear pending bits */
7 X9 q( k; ~/ VRCC->CIR = 0x009F0000;6 `9 |5 ~. ]9 O( z
#endif /* STM32F10X_CL */# D! E5 }' i% e3 [5 M+ B) x0 ?7 W
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined
- B( D' K' Y6 M5 J7 {0 N4 ?STM32F10X_HD_VL)' C) j7 }1 |- `# D/ F0 J
#ifdef DATA_IN_ExtSRAM
# v; ~/ Z; u' r" _- h- S$ K& P& g& KSystemInit_ExtMemCtl();+ n. |1 b' ?$ R5 O: u9 D) s/ @
#endif /* DATA_IN_ExtSRAM */$ H! N& Z, B9 M: f$ [' n( c) l" n
#endif. B% g5 j: u0 x; U3 l2 @" L& l
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */1 _7 t1 B5 B- T6 K/ ]$ i" H& r0 ~
/* Configure the Flash Latency cycles and enable prefetch buffer */
+ |! A! D* b" Q8 r4 h4 cSetSysClock();2 E+ r& A1 `$ ~9 N7 ^6 O
#ifdef VECT_TAB_SRAM" Y* R/ P* C% T/ j; A
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */# G; E1 X; s" I* ]2 W- J
#else1 o2 U. v/ b  }4 T
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in
0 d4 f* L  u% r* b& Y# T+ ^! xInternal FLASH. */
3 X1 ~" D' l; ^+ Q: w, G#endif6 U  I: L/ w( ?& E' P) u, I- t8 n
}

SystemInit函数开始通过条件编译, 先复位RCC寄存器,同时通过设置CR寄存器的HSI时钟使能位来打开HSI时钟。默认情况下如果CR寄存器复位,是选择HSI作为系统时钟,这点大家可以查看RCC->CR寄存器相关位描述可以得知,当低两位配置为00的时候(复位之后),会选择HSI振荡器为系统时钟。也就是说,调用SystemInit函数之后,首先是选择HSI作为系统时钟。在设置完相关寄存器后才换成HSE作为系统时钟,接下来SystemInit函数内部会调用SetSysClock()函数。这个函数内部是根据宏定义设置系统时钟频率。函数如下:

static void SetSysClock(void)
) D. i* j4 `0 O: V2 c! E( c{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
' B- O  b7 x+ |7 y/ L* |SetSysClockTo36();$ m( j$ b3 h3 O
#elif defined SYSCLK_FREQ_48MHz3 q4 [; y- O9 j' z+ B3 E
SetSysClockTo48();. j: ]7 b1 }( c! ^7 ^8 T
#elif defined SYSCLK_FREQ_56MHz
1 }  G) Q' t' R$ VSetSysClockTo56();
! e( }* w, p7 Y' d' R- ~1 n" ?2 d#elif defined SYSCLK_FREQ_72MHz
8 C) K! [; }) G, @* [9 \- fSetSysClockTo72();2 P) A0 [1 b- F& F8 d5 \1 m9 @# ^
#endif
}

  在system_stm32f10x.c文件的开头就有对此宏定义,系统默认的宏定义是72MHz,如下:
; v) p: q& g5 h+ Y- ]% \( S& Q

#define SYSCLK_FREQ_72MHz 72000000- D8 {1 U) a- U2 ^0 e5 v

  如果你要设置为36MHz,只需要注释掉上面代码,然后加入下面代码即可:
$ n. ], i6 ^6 L! D

#define SYSCLK_FREQ_36MHz 360000009 p# ]9 ]% G% b1 h& H1 G' |- t) v; [

  根据该函数内部实现过程可知,直接调用SetSysClockTo72()函数,此函数功能是将系统时钟SYSCLK设置为72M,AHB总线时钟设置为72M,APB2总线时钟设置为72M,APB1总线时钟设置为36M,PLL时钟设置为72M。函数具体实现大家可以打开库函数查看,这里我们就不截取出来。如果SystemInit内实现过程看不懂没有关系,大家只要知道SystemInit函数执行完,时钟大小设置如下:; M9 p- K7 E; B6 z- Y. Y

SYSCLK(系统时钟) =72MHz' K  b) t2 J3 v8 f$ R, A
AHB 总线时钟(HCLK=SYSCLK) =72MHz
3 ~; y' n6 a  Z4 iAPB1 总线时钟(PCLK1=SYSCLK/2) =36MHz7 Z8 H8 ]6 N6 m! L9 E
APB2 总线时钟(PCLK2=SYSCLK/1) =72MHz1 ?+ \) p* A( E0 x# x
PLL 主时钟 =72MHz
; B3 H5 A: ]( \' ]+ F

       在STM32中,这些时钟值是要熟悉的。

8 [( @+ ]. E- z3 r* r5 X
赞 收藏 评论0 发布时间:2022-7-1 13:11

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版