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

【经验分享】STM32F103单片机使用内部RC振荡器做时钟源

[复制链接]
STMCU小助手 发布时间:2022-3-22 13:00
平时在做项目的时候都用的是外部晶振做为时钟源,想试试用内部RC振荡器做为时钟源,在网上搜了一下如何设置内部时钟,发现资料比较少的。决定将设置内部RC振荡器做为时钟源的方法记录下来。
) }1 T1 i6 a2 k$ m& E用的单片机是STM32F103C8T6,项目工程是在正点原子的示例代码上修改来的。用一个LED工程测试,在主程序中闪烁LED灯。7 ]( V/ u  E3 d' w  L  H
6 O5 X: [- s/ S# p7 l- ?/ \1 {
  1. #include "sys.h"
    4 r) \: ^# [: K' N1 a% j$ C
  2. #include "delay.h"
    ) ]# R9 R  ~9 Y/ a8 o" z& W
  3. #include "usart.h"2 [! @/ i- O# A  ~2 Z* U1 j. e: s
  4. #include "led.h"
    3 Z1 c& j) B  k
  5. int main ( void )" @! I9 W: d4 c* z( Q% J" e
  6. {5 b' h5 D1 x- v# ?6 w
  7.     delay_init();       //延时函数初始化
    . ?' F5 x# D1 m; H2 o$ g
  8.     LED_Init();         //初始化与LED连接的硬件接口! D0 b/ `2 x# O. c' E
  9.     while ( 1 )
    9 R% {  g2 F, W1 m. {
  10.     {
    ! d5 s( Y1 K! p% W5 l
  11.         LED = 0;2 f' y1 |: O& Q) W. y
  12.         delay_ms ( 100 ); //延时300ms8 p# a) K3 `6 F3 b3 ?2 h4 u
  13.         LED = 1;& L' @1 x- v+ c/ Y2 C
  14.         delay_ms ( 100 ); //延时300ms( H8 c* y7 i  V  m( H6 }) x
  15.     }+ M) w0 n" Z9 ]; V: p
  16. }
复制代码

2 W2 M3 B0 v, M" W, V1 T首先使用默认时钟设置,也就是外部8M晶振做为时钟源。LED灯灭100ms,然后再亮100ms。7 M  F) H. G2 B4 d
下来看默认时钟设置的代码:
# N  P, `  ]0 P: V在 system_stm32f10x.c 文件里面, SystemInit()函数设置时钟。
( k# x! H6 d8 |! Y/ U
4 L! l4 _" }" q+ {/ g
  1. void SystemInit (void)
    , r+ I& x0 T+ h8 k9 x0 J  a/ N8 G% E
  2. {1 ~/ }! p- W" a' m) `) [
  3.     /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
    " g2 ?$ ?$ c  U* H2 [
  4.     /* Set HSION bit */9 @0 o- }. Q. m8 @3 X, o
  5.     RCC->CR |= (uint32_t)0x00000001;
    % |0 U" B+ ?  [8 D9 n
  6.     /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
    / M: u3 i; V5 A
  7. #ifndef STM32F10X_CL
    & f( K7 l, w2 m. f' {7 f
  8.     RCC->CFGR &= (uint32_t)0xF8FF0000;3 A/ ]3 w0 h3 V" `3 w
  9. #else5 W: v- D6 M% Y
  10.     RCC->CFGR &= (uint32_t)0xF0FF0000;& Q, w1 S' ]6 H- o* y
  11. #endif /* STM32F10X_CL */' |& s, m8 {" W- E2 g. [, P* b" X
  12.     /* Reset HSEON, CSSON and PLLON bits */
    4 d2 X5 i1 O: l; C2 A
  13.     RCC->CR &= (uint32_t)0xFEF6FFFF;. L  ?2 N8 ~* t# j3 V$ S4 }
  14.     /* Reset HSEBYP bit */# N9 s' P) C/ m: Y& x& B6 }; G
  15.     RCC->CR &= (uint32_t)0xFFFBFFFF;5 N6 k7 J1 ]  b' P" G
  16.     /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */  N) p( h# S7 N" D1 \# N: \
  17.     RCC->CFGR &= (uint32_t)0xFF80FFFF;
    $ W+ x6 E  o: f# E0 `. C
  18. #ifdef STM32F10X_CL% R3 y. ^& \1 ^# m% v' Z
  19.     /* Reset PLL2ON and PLL3ON bits */- x* T) M/ }( N* I  z! B
  20.     RCC->CR &= (uint32_t)0xEBFFFFFF;! P; `' Q/ |- K; q: ~3 c
  21.     /* Disable all interrupts and clear pending bits  */
    " V6 R( c' V' p2 l( s
  22.     RCC->CIR = 0x00FF0000;# t5 u( Q. E4 L$ b+ O3 ?* l
  23.     /* Reset CFGR2 register */
    $ J4 Q7 o$ u) }( X! K$ g3 z
  24.     RCC->CFGR2 = 0x00000000;
    ) P9 A* }$ ~+ f/ f
  25. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    6 j; {. [7 _& |2 B. W5 o* w/ {0 ?& i
  26.     /* Disable all interrupts and clear pending bits  */
    3 q2 o% j: F9 D( I  H4 K% x
  27.     RCC->CIR = 0x009F0000;
    3 C1 M1 b. M+ I4 \" i% ?3 k
  28.     /* Reset CFGR2 register */& I5 O4 Q4 f) K" h% T  C! P
  29.     RCC->CFGR2 = 0x00000000;
    ! m: D- q: v) L& W9 a* `
  30. #else
    ( K0 b0 \( T, I9 q; K
  31.     /* Disable all interrupts and clear pending bits  */
    : B( R5 o) s5 u- @
  32.     RCC->CIR = 0x009F0000;8 N" r: N$ o& i
  33. #endif /* STM32F10X_CL */
    / m2 j9 U" W3 \# d& ?0 h$ Y
  34. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
    2 [7 P: l/ i. F' h1 Z( L8 j/ f) q9 t
  35. #ifdef DATA_IN_ExtSRAM
    - `# a& o* F6 Z* J. s
  36.     SystemInit_ExtMemCtl();
    ( m0 g# I( ]5 G( U( K
  37. #endif /* DATA_IN_ExtSRAM */6 C  N4 k+ |# p7 |
  38. #endif* M+ l- U% y$ v7 Z# v" H
  39.     /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */$ v  Y8 Y! x+ ?2 _
  40.     /* Configure the Flash Latency cycles and enable prefetch buffer */9 B% h  n# i: z$ u
  41.     SetSysClock();
    , g! _3 z3 {8 B- D2 z

  42. . |- m9 X- L3 \8 T
  43. #ifdef VECT_TAB_SRAM- \- Q* W! V# r7 O* W
  44.     SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */7 L: I5 G) P; ?5 J
  45. #else7 x5 u$ P. r: }7 I) c  |9 d) D. e
  46.     SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
    ; ?/ o8 H: ?5 M  y+ O: L& w; t
  47. #endif9 F, V; o# ^- [2 v/ y
  48. }
复制代码

0 Q1 `4 i# Z9 Q; j# e2 M. T6 g如何要使用内部RC振荡器做时钟源的话,需要重写SystemInit()函数。设置代码如下:
  1.    /* 开启HSI 即内部晶振时钟 */; d- }4 [" ^: z& L$ X- I8 i* B
  2.         RCC->CR |= ( uint32_t ) 0x00000001;" p, W. Z* F5 G0 {& K/ r2 s. _
  3.         /*选择HSI为PLL的时钟源HSI必须2分频给PLL*/
    # c7 B, k. e6 v. t7 C
  4.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLSRC_HSI_Div2;/ D1 z" ~+ m$ s' W7 F# U/ L' F8 R
  5.         /*PLLCLK=8/2*9=36MHz  设置倍频得到时钟源PLL的频率*/
    6 i  Y+ ^) }' o
  6.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLMULL9;                        //设置倍频后的频率
    0 l% X' b1 o6 Z9 t% C6 P
  7.         /* PLL不分频输出 ?*/
    ! e  r% T: x4 v6 |- P$ h) |# @
  8.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_HPRE_DIV1;# t' R0 e$ I% M# F( ~7 }: y$ h# Q
  9.         /* 使能 PLL时钟 *// `, F" c5 Z& b2 e7 m2 ?
  10.         RCC->CR |= RCC_CR_PLLON;
    : o& z, T7 S7 K5 t+ V
  11.         /* 等待PLL时钟就绪*/5 B! q. C4 [" \( ]5 b
  12.         while ( ( RCC->CR & RCC_CR_PLLRDY ) == 0 ); l3 }6 ?5 _. o) h
  13.         {
    , c1 n' w$ J' [
  14.         }$ M9 R' b( j4 Y' [7 ^0 J
  15.         /* 选择PLL为系统时钟的时钟源 */$ m. X( ^3 _2 B7 d& ?8 i# O* N
  16.         RCC->CFGR &= ( uint32_t ) ( ( uint32_t ) ~ ( RCC_CFGR_SW ) );
    6 W" D0 }( `: V; Y
  17.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_SW_PLL;
    ; o  e. v- A% k+ s, W' n5 Y
  18.         /* 等到PLL成为系统时钟的时钟源*/
    ; F, y- `  z) Z
  19.         while ( ( RCC->CFGR & ( uint32_t ) RCC_CFGR_SWS ) != ( uint32_t ) 0x08 ), U1 y0 h* [# t* t) H& K% C
  20.         { }
复制代码

8 a! g" o. f$ V5 E% y! S' d( U为了方便和以前的代码兼容,这里使用条件编译来选择使用外部晶振或者内部RC震荡。代码流程如下:
% b1 k0 D* ]0 z3 @! ?#if USE_HSI3 `1 G: S% n: S  q" K/ V' F2 N
{undefined  r! {1 Y6 ~8 E& W
//使用内部RC
+ ~1 o8 M( `5 h- ], K/ L7 A4 U. N}3 G& A( b/ k4 [1 {, F" _7 }$ {
else
% l# v& D8 D) q+ j% P{undefined- f4 m( j- U1 b8 V+ L- }( X3 O
//使用外部晶振
3 Y# \/ N. W/ f7 f+ c, B}
. _5 f) ^8 `& d! \! c# W: G#endif
1 ~4 {9 s6 ]7 H/ G% B7 I8 K通过宏定义 USE_HSI 来选择时钟源,USE_HSI 为1时,使用内部RC做为时钟源,USE_HSI 为0时,使用外部晶振做为时钟源。5 K5 b- {& H3 z% I( l0 f7 }( y4 p
修改后的代码如下:2 h- H) x+ X0 V: T2 Y+ J' v. U# G
  1. 3 C$ l1 I+ C' a4 _- \& k+ S
  2. #define  USE_HSI   0                        // 是否使用内部晶振  0 不使用  1使用1 G  y4 ^4 @  o* e% @3 h
  3. void SystemInit ( void )
    9 j2 g/ @7 _4 N- k
  4. {
    6 H  J, P5 G0 x, m* l( K/ @- n
  5. 7 r4 H4 J! Q. L. E% h. a2 p" h
  6. #if USE_HSI/ d* Y  s4 s: H5 D
  7.     {
    9 J2 G2 @+ R( E. ^. q8 }
  8. //设置使用内部晶振% x0 O$ {5 e5 T4 ^9 r3 u8 \
  9.         /* 开启HSI 即内部晶振时钟 */8 j$ c7 ~- I! s0 }5 Q/ g
  10.         RCC->CR |= ( uint32_t ) 0x00000001;9 W  z2 `- C9 `, Q7 r) e# k/ ^
  11.         /*选择HSI为PLL的时钟源HSI必须2分频给PLL*/
    : u' T; K. w8 a1 B5 W- y3 y: G
  12.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLSRC_HSI_Div2;
    " H' v6 T, o* {4 X( i
  13.         /*PLLCLK=8/2*9=36MHz  设置倍频得到时钟源PLL的频率*/: X# ^+ X3 {, k) H
  14.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLMULL9;                         //设置倍频后的频率; y. o5 w( r9 m. U! v# d/ a' @+ y
  15.         /* PLL不分频输出 ?*/3 i' m" K; o+ ~* w* ^
  16.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_HPRE_DIV1;9 o2 B, @. |5 R" p7 y6 [( \; m
  17.         /* 使能 PLL时钟 */6 F8 g( d4 ~1 y* _& C" H
  18.         RCC->CR |= RCC_CR_PLLON;
    0 ?3 s3 K3 h$ o5 |4 K1 {
  19.         /* 等待PLL时钟就绪*/- Q1 h2 j* J% N* @' t6 Z/ f9 r
  20.         while ( ( RCC->CR & RCC_CR_PLLRDY ) == 0 )
    + A  g+ U1 A/ ]; ~) ~. w/ I
  21.         {. y! e4 {8 \9 P" K8 f
  22.         }
    0 g. w# L) e: L
  23.         /* 选择PLL为系统时钟的时钟源 */
    # V' {; B2 s) P3 i
  24.         RCC->CFGR &= ( uint32_t ) ( ( uint32_t ) ~ ( RCC_CFGR_SW ) );) V$ e' G/ F9 y$ g
  25.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_SW_PLL;( w2 m  @- h2 q; D0 \0 \
  26.         /* 等到PLL成为系统时钟的时钟源*/
    , |+ L3 o+ b* h0 ^( V: p. F/ X+ e
  27.         while ( ( RCC->CFGR & ( uint32_t ) RCC_CFGR_SWS ) != ( uint32_t ) 0x08 )
    9 i/ S1 n/ R" k( s: s1 L
  28.         { }' @  f4 e" g6 Z  j
  29.     }
    2 G: K  S5 e: z
  30. #else, z( X6 y0 B' ^3 E
  31.     {! Y* s' b: M+ Q) ?! n+ k. j- R
  32. //设置使用外部8M晶振
    6 M) i. ]" j% P1 c, f1 Z
  33.         /* Reset the RCC clock configuration to the default reset state(for debug purpose) */7 I. m; G2 E0 B+ L
  34.         /* Set HSION bit */7 }% y8 ?6 X! }2 x
  35.         RCC->CR |= ( uint32_t ) 0x00000001;+ A6 t# f  c, I- Y

  36. 3 q+ _, r4 u' n' b, f
  37.         /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
    0 a- ^( w: @3 X7 y% d
  38. #ifndef STM32F10X_CL8 f" A. X6 ?* @
  39.         RCC->CFGR &= ( uint32_t ) 0xF8FF0000;0 w1 B+ O6 Y9 W! k4 H: C# S# q
  40. #else
    7 B* v( M) I& c8 D( q
  41.         RCC->CFGR &= ( uint32_t ) 0xF0FF0000;
    $ ~. P+ f& z: K8 d+ u5 c) @0 N& N
  42. #endif /* STM32F10X_CL */+ a3 d: Q- r& g/ ^! A( I
  43. - x& A- q1 Z) T& Q* o1 T: G) i
  44.         /* Reset HSEON, CSSON and PLLON bits */
    2 \/ ~. J- g( d9 {/ y
  45.         RCC->CR &= ( uint32_t ) 0xFEF6FFFF;2 a2 ^' N# Y8 T' u
  46. 0 o6 j5 a) K- L2 f" N
  47.         /* Reset HSEBYP bit */  X% e) _" b0 G9 d, i  x
  48.         RCC->CR &= ( uint32_t ) 0xFFFBFFFF;
    0 R# L* |) `% C9 g# k! V# ?

  49. ) p0 O  i0 W1 C$ u# u' `& }
  50.         /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
      h! r% P! T2 y' Q
  51.         RCC->CFGR &= ( uint32_t ) 0xFF80FFFF;
    , i1 G3 T4 _  _( g% ]" ~) T

  52. 6 O8 ], O% J) A7 b2 d
  53. #ifdef STM32F10X_CL: Z, w3 A! G5 g
  54.         /* Reset PLL2ON and PLL3ON bits *// Z9 b# J8 v2 h' _: }
  55.         RCC->CR &= ( uint32_t ) 0xEBFFFFFF;% E2 s) H# h- F( u) i
  56. 5 P1 ~7 U, g% S. r7 ~+ n
  57.         /* Disable all interrupts and clear pending bits  */% K, S! {3 w! G. ?
  58.         RCC->CIR = 0x00FF0000;
    5 d+ J, `( i7 F: r9 w+ a

  59. * B+ a& Q$ e+ H( Y' G. D
  60.         /* Reset CFGR2 register */7 e5 c" Q; [- [8 j/ e. M
  61.         RCC->CFGR2 = 0x00000000;
    3 p$ V" ]7 g7 ]% B
  62. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)' [6 S" E8 x$ p  j% M; D
  63.         /* Disable all interrupts and clear pending bits  */9 \* f0 {2 M4 A1 g  N
  64.         RCC->CIR = 0x009F0000;
    ; b+ R5 W1 o) T; W+ a
  65. : A8 y% ?  H2 r) Y
  66.         /* Reset CFGR2 register */9 {! f+ y* Y0 R' |
  67.         RCC->CFGR2 = 0x00000000;
    - A$ h4 |0 h5 |: I4 o3 l  k
  68. #else
    / @* O. {4 l7 u! H
  69.         /* Disable all interrupts and clear pending bits  */
    % w4 z6 [; y% S# N- h/ l
  70.         RCC->CIR = 0x009F0000;: D; p7 j& `7 r3 ~
  71. #endif /* STM32F10X_CL */
    ; `$ F8 X' U) s2 I5 Y( M& S

  72. 4 X. ]" \0 p, u, G8 q% k
  73. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
    - Y' _' I' \8 C7 ]2 D
  74. #ifdef DATA_IN_ExtSRAM5 j7 k% l4 @, i: K9 H( P. n3 z
  75.         SystemInit_ExtMemCtl();) y, A$ ], }6 b! ~  t( T
  76. #endif /* DATA_IN_ExtSRAM */
    # H; x7 P8 v# v- z
  77. #endif
    8 p& E' F, a5 X

  78. " o. p7 L# c, E
  79.         /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers *// |  E, |, |6 o2 C: L# [2 K; O
  80.         /* Configure the Flash Latency cycles and enable prefetch buffer */0 v7 E+ l1 N7 W. D* E8 `, R
  81.         SetSysClock();( H9 e2 |; T2 M8 l$ I' N- ]

  82. , M  l+ c9 c5 b1 N
  83. #ifdef VECT_TAB_SRAM
    % L' I8 L+ x7 @2 g  ?
  84.         SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */% o1 \, q, B& R2 V, F1 ?
  85. #else
    " ]5 f$ C, `* M6 z# C
  86.         SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */+ I% J% k$ w' [5 m, T0 I
  87. #endif# l8 [8 K& }% q$ N# `$ q5 K/ j
  88.     }/ r9 f2 n. H$ W

  89. 0 s$ t5 d7 K) Z9 u2 K
  90. #endif3 u/ ?7 E% _, S' Y4 B) R/ M- t
  91. }
复制代码

) g4 s- o- x6 ^+ ?内部RC默认为8M,将倍频数设置为9,这样使用内部RC振荡器之后,时钟频率就是36MHz。为使用外部晶振频率72MHz的一半。4 w% ^8 }3 k% [& U6 X
5 e! {$ |, {9 ], p) g+ r
  1.   /*PLLCLK=8/2*9=36MHz  设置倍频得到时钟源PLL的频率*/1 H- u" n! b) x1 D& T/ J! \" P% U
  2.         RCC->CFGR |= ( uint32_t ) RCC_CFGR_PLLMULL9;                         //设置倍频后的频率
复制代码

- Q$ x, W) _" d: ~$ h3 D这时候在运行代码,用示波器测试LED的电平,发现是高电平200ms,低电平200ms。比使用外部时钟慢了一半,说明使用内部RC振荡器的设置代码是正确的。* Z2 G  P& F1 j5 r' g
* C- z7 b6 r! p- ]9 Q1 c0 V2 D5 [

8 m/ ^1 |2 N3 `+ h8 K: T
收藏 评论0 发布时间:2022-3-22 13:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版