STM32之时钟
2016-05-07 09:59
288 查看
1、时钟源
三个不同的时钟源可做系统时钟(SYSCLK):HSI 振荡器时钟 :高速内部时钟
HSE 振荡器时钟:高速外部时钟
PLL 时钟
两个二级时钟
LSI(低速内部时钟) :32kHz 低速内部 RC (LSI RC) 独立看门狗时钟源,RTC 可用于自动唤醒停止/待机模式。
LSE(低速外部时钟):32.768kHz 低速外部晶振 (LSE crystal) ,可选择作为 RTC(RTCCLK) 时钟源
每一个时钟源不需要时都可以被选择性关闭,用来节省系统电源消耗
预分频器被用来设置 AHB, APB (APB2) 和 APB (APB1) 频率。 AHB域最大频率可设置为168 MHz。APB2 域最高频率可达 84 MHz。APB1 域最高频率可达 42 MHz。AHB:主要用于控制USB,网卡,IO口,DMA等设备 APB:主要用于控制串口,AD,I2C等设备 以上总线时钟分频系数在RCC_CFGR 寄存器的10到15位设置
2、时钟输出
一共有两个微控制器时钟输出脚MCO1:配置预分频器可以选择四种时钟源输出到MCO1引脚
(PA8)HSI LSE HSE PLL
配置 MCO1PRE[2:0] 和 MCO1[1:0] 位来选择上面给出时钟源
MCO2:配置预分频器可以选择四种时钟源输出到MCO2引脚(PC9)
HSE PLL SYSCLK PLLI2S
配置 MCO2PRE[2:0] 和 MCO2 位来选择上面给出的时钟源
另:输出时钟的最高频率不得超过100MHz,因为引脚的最高速不超过100MHz
3、时钟测量
STM32F407ZG允许用TIM5 channel 4 和 TIM11 channel 1捕获时钟源,以此间接的测量所有片上时钟源的频率TIM5 channel 4
TIM5有一个复用控制器可用来选择输入捕获由I/O触发还是由内部时钟触发。可通过设置 TIM5_OR 的 TI4_RMP [1:0] 位来选择。
测量LSI时钟频率的设置步骤:
使能 TIM5 时钟,并配置 channel 4 为输入捕获模式
设置 TIM5_OR 寄存器的 TI4_RMP 位为 0x01 来连接 LSI 时钟
用TIM5 4个事件或者中断来捕获/比较测量内部时钟
4.用测量到的 LSI 频率来更新 RTC 的预分频对看门狗时钟输出编程
TIM11 channel 1
TIM11有一个复用控制器可用来选择输入捕获由I/O触发还是由内部时钟触发。可通过设置 TIM11_OR 的 TI1_RMP [1:0] 位来选择。
设置步骤与TIM5 channel 4 类似
4、PLL的数值设置
f(VCO clock) = f(PLL clock input) × (PLLN / PLLM) f(PLL general clock output) = f(VCO clock) / PLLP f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
标号 | 意义 |
---|---|
f(PLL clock input) | 也就是输入到PLL锁相环的时钟,输入源可选择,系统刚刚上电的时候是HSI源,参见下面的:系统复位时钟设置 |
f(VCO clock) | 暂且理解为经倍频之后待输出的频率,之后要进行分频设置,频率大小与芯片硬件相关 |
f(PLL general clock output) | PLL实际输出的时钟频率,参照STM32时钟树图的中间部分SYSCLK 168MHz max处,这个点的时钟频率就是f(PLL general clock output),之后又会经过分频以供不同的设备使用 |
f(USB OTG FS, SDIO, RNG clock output) | 也就是USB SDIO等等的频率,通常48MHz |
5、时钟树图
对比S3C2440与该STM32也就是Cortex M4的时钟图(S3C2440画的更清晰明了,更详细一点)STM32的时钟树图:
S3C2440的时钟树图:
ARM的时钟基本就是采用PLL锁相环结构,之后分出来FCLK,PCLK与HCLK分别给系统内核,片内外设,以及硬件提供时钟。
6、系统复位时时钟设置
寄存器 | 复位值 | 意义 |
---|---|---|
RCC_CR | 0x00000083 | 开启HSI,系统运行刚上电就是以HSI为时钟源运行的 |
RCC_PLLCFGR | 0x24003010 | PLLQ = 4, HSI为PLL源,PLLP = 2,PLLM = 16,PLLN = 192 |
RCC_CFGR | 0x00000000 | 系统时钟不分频,系统时钟源为HSI |
7、时钟初始化最简编程实例
#define BYM_RCC_struct \ ((RCC_TypeDef *)(AHB1PERIPH_BASE + 0x3800)) #define BYM_FLASH_struct \ ((FLASH_TypeDef *)(AHB1PERIPH_BASE + 0x3C00)) #define F_VCO_CLK_336 ((336 << 6) | (8 << 0)) #define PLL_OUT_CLK_168 (0 << 16) #define USB_OUT_CLK_48 (7 << 24) /* * Initialize system clock * f(VCO clock) = f(PLL clock input) * (PLLN / PLLM) * f(PLL general clock output) = f(VCO clock) / PLLP * f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ * * PLLP = 2; PLLQ = 7; PLLN / PLLM = 42; * f(PLL clock input) = 8M; f(VCO clock) = 336M; * f(PLL general clock output) = 168M; f(USB OTG FS, SDIO, RNG clock output) = 48M */ void sys_clk_init(void) { /* 开启HSE高速外部时钟 */ BYM_RCC_struct->CR &= ~(1 << 16); //Disable HSE, be required by bit18 if you want to write bit18 BYM_RCC_struct->CR &= ~(1 << 18); //HSE not bypassed BYM_RCC_struct->CR |= (1 << 16); //Enable HSE while((BYM_RCC_struct->CR & (1 << 17)) == 0); //Wait for HSE ready /* 设置倍频系数确定时钟频率(PLL模式) */ BYM_RCC_struct->PLLCFGR &= ~(0xf << 24); //Clear old data BYM_RCC_struct->PLLCFGR |= USB_OUT_CLK_48; //Flush new data BYM_RCC_struct->PLLCFGR &= ~(0x3 << 16); //Clear old data BYM_RCC_struct->PLLCFGR |= PLL_OUT_CLK_168; //Flush new data BYM_RCC_struct->PLLCFGR &= ~(0x7fff << 0); //Clear old data BYM_RCC_struct->PLLCFGR |= F_VCO_CLK_336; //Flush new data /* 选择PLL源为HSE,开启PLL */ BYM_RCC_struct->PLLCFGR |= (1 << 22); //HSE oscillator clock selected as PLL and PLLI2S clock entry BYM_RCC_struct->CR &= ~(1 << 26); //Close PLLI2S BYM_RCC_struct->CR |= (1 << 24); //Enable PLL while((BYM_RCC_struct->CR & (1 << 25)) == 0); /* 使能指令预取与指令数据Cache(调试过程发现此步是必须的,否则程序没法运行) */ BYM_FLASH_struct->ACR |= (1 << 8); // BYM_FLASH_struct->ACR |= (1 << 9); //Enable ICache BYM_FLASH_struct->ACR |= (1 << 10); //Enable DCache BYM_FLASH_struct->ACR |= (5 << 0); //Wait /* 配置预分频器来对时钟进行分频 */ BYM_RCC_struct->CFGR &= ~(0x7 << 13); BYM_RCC_struct->CFGR |= (4 << 13); //APB2 max value = 84M, 2 devided as system clock = 168M BYM_RCC_struct->CFGR &= ~(0x7 << 10); BYM_RCC_struct->CFGR |= (5 << 10); //APB1 max value = 42M, 4 devided as system clock = 168M BYM_RCC_struct->CFGR &= ~(0xf << 4); //system clock not devided /* 选择系统时钟来源 */ BYM_RCC_struct->CFGR &= ~(0x3 << 0); BYM_RCC_struct->CFGR |= (2 << 0); //PLL used as system clock while((BYM_RCC_struct->CFGR & (2 << 2)) == 0); BYM_RCC_struct->CR &= ~(1 << 0); //Close HSI while((BYM_RCC_struct->CR & (1 << 1))); }
8、初始化时钟的步骤,PLL模式
开启HSE高速外部时钟设置倍频系数确定时钟频率(PLL模式)
配置预分频器来对时钟进行分频
选择PLL源为HSE,开启PLL
使能指令预取与指令数据Cache(调试过程发现此步是必须的,否则程序没法运行)
选择系统时钟来源
由上面的程序可知,某些步骤可以被打乱,但是开启PLL之前必须选择好PLL源以及设置好倍频系数。设置系统时钟来源之前必须先启动ICache与DCache。要关闭HSI的话要在上述步骤设置完之后才能够关闭,因为系统上电之后默认的是HSI为系统时钟源并且使用PLL,所以在HSI还在被使用的时候是不可能被关闭的,只有系统时钟源改变之后才能够被关闭,关闭HSI以节省电量
相关文章推荐
- codeforces 670C Cinema
- 【OpenCV】SIFT原理与源码分析
- 分布式 ES 操作流程解析
- wifi开发总结
- 方法覆盖和方法重载
- win10右键intel显卡图形选项该怎么去掉?
- sigmoid cross entorpy loss
- Myeclipse启动不了的解决方法
- 指针重难、易错点
- 1个人2个月做到6000W的阅读量,我都做了什么?
- 【Asp.Net MVC 以小见大】一步一步改写简单的登录注册(一)
- 最长字段和
- random
- 5-50 畅通工程之局部最小花费问题 (35分)
- Unity3D 摄像机(Camera)
- TCP/IP协议栈中的TimeStamp选项
- 华为实习生招聘总结
- 天平称量问题
- HAProxy安装
- python-Scapy网络的掌控者