最近用STM32F1系列单片机做一个触摸屏USB鼠标,考虑不用外部晶振而使用STM32内部8MHz HSI RC作为时钟源。由于USB协议规定了48MHz 的USB时钟,故必须对HIS作PLL倍频处理后得到PLLCLK作为STSCLK时钟。时钟关系见如下STM32F1时钟树:$ H$ i6 T9 v" {9 O- C% w
8 ?/ q2 N* g# Y, K
+ z( H$ f( X9 N, p: ~ w2 ^9 q, D) i! G4 z2 h: n
类比正点原子STM32F1寄存器版本使用外部晶振的时钟初始化函数,改动得到使用HSI作为时钟源,SYSCLK为48MHz的初始化代码:
4 K) G' h1 W1 i# b
: h2 s- ~& s- @4 a3 _" m: \. z/ w h- void Stm32_Clock_Init(u8 PLL). y. m; S* _ [: n Z8 F8 K
- {
' O3 \/ a: v9 _. } - unsigned char temp=0;4 D3 D) g! [% G) }2 t
- MYRCC_DeInit(); //复位并配置向量表
- L4 A: m8 `5 H0 w: _( Q - RCC->CR|=0x00000001; //内部高速时钟使能HSION5 J" o& |9 n( j4 Y/ B0 E
- while(!(RCC->CR>>1));//等待内部时钟就绪
$ q& P& m7 ]( r( W; K - RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;& s. U5 l/ Q, z& Y; n
- PLL-=2;//抵消2个单位
) U+ U( f& P: m6 h" W6 T - RCC->CFGR|=PLL<<18; //设置PLL值 2~16
, b7 k. Z3 ^3 A2 `* } - RCC->CFGR|=0<<16; //PLLSRC ON HSI经2分频后作为PLL输入时钟2 l2 n2 g2 I: B& }
- FLASH->ACR|=0x32; //FLASH 2个延时周期
- i- G' w/ D1 h6 K0 ?( [ -
% D8 K, i# \, }% R! W - RCC->CR|=0x01000000; //PLLON
/ a9 b& l; }3 r' T2 b5 U# `3 d: h - while(!(RCC->CR>>25));//等待PLL锁定9 e0 Y3 U, z d8 X8 a
- RCC->CFGR|=0x00000002;//PLL作为系统时钟% j) U; p( r- f) T: z
- while(temp!=0x02) //等待PLL作为系统时钟设置成功
7 k0 Y- A7 h/ V6 m8 f, S% G: U - {
5 u* `2 X" w( Q& m - temp=RCC->CFGR>>2;7 F7 S6 ^% c) O5 X7 b9 J
- temp&=0x03;# @% S: `6 a. \9 f& _) `0 q) Y
- }
5 J% ?+ ^2 Z+ b) x Z - }
复制代码
/ E" i) Y) N% @* @8 n" [9 u其中MYRCC_DeInit()代码如下:( N% U$ D) G. G" m. k4 y0 t) N
7 L7 A# y9 `0 c9 G4 _- void MYRCC_DeInit(void). n: G- h/ D# Q" b7 ^# R1 w
- { % g- L$ j9 `7 |
- RCC->APB1RSTR = 0x00000000;//复位结束
- p5 b4 {) Z) F7 U - RCC->APB2RSTR = 0x00000000; ; S: T7 a3 n: k: I+ {
-
2 X2 f# W0 X3 C/ v( X9 r - RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能.其他关闭.
7 y9 S8 g% f' f% g1 `' ] - RCC->APB2ENR = 0x00000000; //外设时钟关闭. 0 c+ _( q& [# D x0 \
- RCC->APB1ENR = 0x00000000;
% g7 `( P) f' [4 V/ P: J3 A1 y" i - RCC->CR |= 0x00000001; //使能内部高速时钟HSION
- [1 F" F/ v. X6 j+ t1 J; |" G - RCC->CFGR &= 0xF8FF0000; //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0] + {1 P! @1 f1 i
- RCC->CR &= 0xFEF6FFFF; //复位HSEON,CSSON,PLLON" }) N0 ?: P: z7 T" P
- RCC->CR &= 0xFFFBFFFF; //复位HSEBYP ! P! p) Y* ~1 e# j# ]
- RCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE 9 i" G" G( ~6 G# e
- RCC->CIR = 0x00000000; //关闭所有中断 6 |+ v# m. x8 T1 C9 w) {; U
- //配置向量表 / ^9 ^2 `8 x/ Y% k. M5 Q0 [4 I
- #ifdef VECT_TAB_RAM
: n7 J% N, Z! k - MY_NVIC_SetVectorTable(0x20000000, 0x0);
3 ]" s; e& W, I9 E+ w& J0 u2 s - #else . t* l# c; `% w5 y. r1 L6 s
- MY_NVIC_SetVectorTable(0x08000000,0x0);
+ F" }, ?- Z* ?2 x1 e$ ] - #endif1 |( \7 ^& R! V" y/ B* {
- }
复制代码 2 W, Y4 a2 g( v0 R7 u, ~
MY_NVIC_SetVectorTable()代码如下:
0 K; }6 r! G* F3 k& |% P
# T9 J; ~% i% q L1 E& V! R* a# T- void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset) % z, v- o( Y9 G* K Y6 z
- {
& F' D, [5 k1 y# k( [9 c$ j# n, r - SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//设置NVIC的向量表偏移寄存器
. m, l! C6 v3 G# U - //用于标识向量表是在CODE区还是在RAM区
6 v; W4 E4 j k* L# d - }
复制代码
% T# c. v2 t: t8 J/ H' ?(1)使用时在main()函数中应写成:Stm32_Clock_Init(12),即8/2*12=48MHz.1 Z2 {( l. B- o9 d8 J ]$ g
9 \9 ]' N5 _# O2 ^; A(2)为使delay_ms()等函数时钟准确,应在system_stm32f10x.c中将. W. J0 g4 d& g' k& K. g, D
$ |( v: \- k% \2 m$ W" N(3)#define SYSCLK_FREQ_48MHz 48000000解除屏蔽
# @* B* w8 I/ D- {1 B
( H9 t7 N7 E/ o3 z! O4 X9 ?(4)同时要注意在USB时钟初始化函数中不再对PLL时钟分频。即时钟配置寄存器(RCC_CFGR)第22位应设置为13 ^: ^8 S. v+ {- j- H' g \
3 H8 B9 j8 k7 s* H" H
(5)最后,内部时钟要想正确使用,需要在启动.s文件中屏蔽sysinit4 U- n, O" i8 s6 a9 J
————————————————
8 A+ g# T! Z, G& t2 t1 O版权声明:qhw52794 F' q) X3 I* t) h
F+ V$ t* D" A: x8 D6 }4 @ |