STM32有三种不同的时钟源可被用来驱动系统时钟(SYSCLK): 1:HSI振荡器时钟(内部时钟) 2:HSE振荡器时钟(外部时钟,即晶振所提供) 3:PLL时钟(锁相环时钟) 这些设备有以下2种二级时钟源: (1)40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。RTC用于从停机/待机模式下自动唤醒系统。 (2)32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。 当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功 下面是以外部晶振8M,系统时钟72M为例。 STM32系统时钟初始化流程如下: 1、复位并配置向量表; 2、使能外部高速中断HSEON,并等待就绪; 3、RCC->CFGR=0X00000400;设置APB1,如先把前面的设置好之后,再来设置APB1就已经来不及了,所以必须先二分频,因为要求APB1不超过36MHz,前面最大为72MHz,故二分频即可; 4、RCC->CFGR|=PLL<<18;设置锁相环放大倍数,及时钟树的PLLMUL; 5、RCC->CFGR|=1<<16; 选择HSE作为PLL输入; 6、FLASH->ACR|=0x32; FLASH 2个延迟周期 7、RCC->CR|=0x01000000; 使能PLL,并等待就绪; 8、RCC->CFGR|=0x00000002;设置PLL作为系统时钟,并等待就绪。 ! j+ ~; D/ M3 X1 ^
时钟树如下:大致流程如时钟树里面的顺序标号 ! n! L* O, C* B" b
& H1 w- F; w: U# I" PSTM32系统时钟初始化代码如下: void Stm32_Clock_Init(u8 PLL) { unsigned char temp=0; MYRCC_DeInit(); //复位并配置向量表 RCC->CR|=0x00010000; //外部高速时钟使能 while(!(RCC->CR>>17));//等待外部时钟就绪 RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1; //二分频
- [6 ~ E1 b' \; g
PLL-=2;//抵消两个单位,具体看STM32中文参考手册 RCC->CFGR|=PLL<<18; //设置PLL的值,2~16 RCC->CFGR|=1<<16; //PLLSRC ON FLASH->ACR|=0x32; //FLASH 2个延迟周期 RCC->CR|=0x01000000; //PLLON while(!(RCC->CR>>25));//等待PLL锁定 RCC->CFGR|=0x00000002;//PLL作为系统时钟 while(temp!=0x02) //等待PLL作为系统时钟设置成功 { temp=RCC->CFGR>>2; //不断的查询寄存器看系统时钟是否设置成功 temp&=0x03; } } 在跑裸机程序时,利用芯片提供的滴答定时器SysTick来进行延迟,是一种比较准确的延迟 Systick :系统心跳定时器,提供系统节拍,裸机程序中可作为独立的延时定时器 它有四个寄存器 STK_CSR, 0xE000E010 -- 控制寄存器 STK_LOAD, 0xE000E014 -- 重载寄存器 STK_VAL, 0xE000E018 -- 当前值寄存器 STK_CALRB, 0xE000E01C -- 校准值寄存器
$ P) y+ \. Q; P8 j延时编程原理 systick定时器是24位的递减计数器,设定初值并使能它后,它会每个系统时钟周期计数器减1, 计数到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息. 延时编程步骤 1.计算出产生1us 需要多少个时钟周期 fac_us; 2.计算出RELOAD寄存器的值 也就是产生相应延时所需要的时钟周期数 RELOAD=fac_us * nus 3.开启计数 4.循环检测计数到0的标志位; 5.清空计数器,关闭定时器 寄存器版代码注解(可以看上面的时钟树也能够看出来) 使用外部8M时钟,锁相环里出来的频率是72M,AHB预分频后是72M, systick固定HCLK时钟的1/8,即9M,那么延时1us是9个时钟 : b5 o) p0 F! r
还有一个注意点: LOAD寄存器是24位的 最大值0xffffff 那么延时最大值计算公式为 nms<=0xffffff*8*1000/SYSCLK (SYSCLK单位Hz) 则nms的最大值为1864.135ms ,即1864毫秒。 |