STM32F407RCC配置.docx

上传人:b****5 文档编号:7708942 上传时间:2023-01-25 格式:DOCX 页数:16 大小:161.92KB
下载 相关 举报
STM32F407RCC配置.docx_第1页
第1页 / 共16页
STM32F407RCC配置.docx_第2页
第2页 / 共16页
STM32F407RCC配置.docx_第3页
第3页 / 共16页
STM32F407RCC配置.docx_第4页
第4页 / 共16页
STM32F407RCC配置.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

STM32F407RCC配置.docx

《STM32F407RCC配置.docx》由会员分享,可在线阅读,更多相关《STM32F407RCC配置.docx(16页珍藏版)》请在冰豆网上搜索。

STM32F407RCC配置.docx

STM32F407RCC配置

RCC(ResetandClockControl)配置

这里介绍RCC的时钟控制功能

在STM32F103上,由于小组所有的板子都使用用同样的芯片,同样的晶振,以及同样的库函数,即使我们不去理解RCC,仍然可以将大多数功能调试出来。

但如果使用不同型号的芯片,例如用STM32F407与STM32103进行通信,如果不去弄清楚RCC,在调试中可能会遇到麻烦。

下面就我调试STM32F407的这段时间,介绍一下RCC的部分功能。

文档的前半部分是关于RCC的部分功能描述,后半部分是关于库函数的使用。

时钟结构

(原图请参考STM32F407参考手册RCC部分)

STM32F407最高层是SYSCLK系统时钟,由其生成了AHB时钟,再由AHB时钟生成APB时钟。

SYSCLK系统时钟可以由3个基本的时钟源获得:

HSE(外部高速晶振)或HSI(内部高速晶振)或PLL锁相环倍频。

例如:

板子上焊了8MHz的晶振,则HSE=8MHz。

如果焊了25MHz的,则HSE=25MHz。

HSI是芯片内部自带的晶振,其大小由芯片型号决定,如STM32F407的HSI是16MHz。

PLL倍频的功能是:

将HSE或HSI的频率放大,最大可以放大到168MHz.

 

SYSCLK系统时钟可以由HSE/HSI/PLL提供。

例如使用库函数:

RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);代表用HSE外部高速晶振作为系统时钟源。

如果HSE=8MHz,则SYSCLK=8M,即STM32F407就会运行在8M的速度;

如果HSE=25M,则SYSCLK=25M,即STM32F407就会运行在25M。

RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);代表用HSI内部高速晶振作为系统时钟源,

如果HSI=16M,则SYSCLK=16M,即STM32F407就会运行在16M的速度。

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);代表用PLL时钟作为系统时钟源。

如果配置PLL倍频至168M,则SYSCLK=168M,即STM32F407会运行在168M;

如果倍频至144M,则SYSCLK=144M,STM32F407就会运行在144M;

如果倍频至72M,STM32F407也会像STM32F103运行在72M;

 

从SYSCLK,紧接着分得AHB时钟(也叫HCLK)。

假设此时我们已经选择PLL作为系统时钟源,且PLL倍频至168M,即SYSCLK=168M。

那么AHB的最高频率就为168MHz。

方框底部的数字/1,2...512代表AHB时钟预分频数,范围1~512,

如果是1,即HCLK为SYSCLK的1分频,HCLK=SYSCLK/1=168/1=168MHz

如果是2,即HCLK为SYSCLK的2分频,HCLK=SYSCLK/2=168/2=84MHz

注意,HCLK是受SYSCLK约束的,

如果我们配置SYSCLK=144M,那么此时HCLK最大只能达到144MHz。

 

将AHB时钟继续分割,得到的是APB时钟(也叫PCLK)。

假设在此之前,SYSCLK=168M,SYSCLK2分频得HCLK=84M。

(HCLK代表AHB时钟)

与前面AHB时钟类似,方框底部的数字代表预分频数,范围1~16.

如果是1,即PCLK(APB时钟)为HCLK的1分频,PCLK=HCLK/1=84/1=84MHz

如果是2,即PCLK为HCLK的2分频,PCLK=HCLK/2=84/2=42MHz。

APB时钟可以继续分给APB总线上的外设,如果继续配置外设的预分频,可以进一步修改外设的时钟频率。

例如:

配置CAN总线。

第一步:

利用PLL,我们配置系统时钟SYSCLK=168MHz。

第二步:

此时已有SYSCLK=168MHz。

设置AHB分频数为2,即得:

HCLK=SYSCLK/2=84MHz。

第三步:

此时已有HCLK=84MHz。

设置APB分频数为2,即得:

PCLK=HCLK/2=42MHz。

第四步:

此时已有PCLK=42MHz。

设置CanInitStruct.CAN_Prescaler=7,即得CAN时钟=PCLK/7=6MHz。

这样,正确配置了CAN的时钟,配置CAN时才能计算出实际的波特率,从而实现通现。

我们借助CAN总线的例子继续说明RCC的作用。

接着上面的例子,例如:

我们使用STM32F407与STM32F103进行CAN通信,且到这一步已经保证所有的配置都正确,波特率为1M/s。

其中STM32F407与STM32103的CAN都配置成:

CAN_InitStruct.CAN_Prescaler=2;

CAN_InitStruct.CAN_SJW=CAN_SJW_1tq;

CAN_InitStruct.CAN_BS1=CAN_BS1_9tq;

CAN_InitStruct.CAN_BS2=CAN_BS2_8tq;

这样STM32F407与STM32F103在绝大多数情况下是无法通信的,原因如下:

启动后,STM32F407自动执行SystemInit(),并配置成如下规格:

(可在库函数中找到)

根据上图,即可知启动后的STM32F407:

SYSCLK=168MHz

HCLK=SYSCLK/1=168MHz

PCLK1=HCLK/4=42MHz

STM32F407的CAN属于APB1,又由于CAN_InitStruct.CAN_Prescaler=2;

则CAN的时钟为PCLK1/2=21MHz。

根据前面我们对CAN的配置:

CAN_InitStruct.CAN_Prescaler=2;

CAN_InitStruct.CAN_SJW=CAN_SJW_1tq;

CAN_InitStruct.CAN_BS1=CAN_BS1_9tq;

CAN_InitStruct.CAN_BS2=CAN_BS2_8tq;

我们CAN的波特率实际上是:

CAN波特率=(1+9+8)/21=0.857M/s(并非1M/s)

 

而同样对于STM32103,默认情况下:

SYSCLK=72MHz

HCLK=SYSCLK/1=72MHz

PCLK=HCLK/2=36MHz,

因而根据配置:

CAN_InitStruct.CAN_Prescaler=2;

CAN_InitStruct.CAN_SJW=CAN_SJW_1tq;

CAN_InitStruct.CAN_BS1=CAN_BS1_9tq;

CAN_InitStruct.CAN_BS2=CAN_BS2_8tq;

CAN时钟=18MHz。

因此对于STM32F103:

CAN波特率=(1+9+8)/18=1M/s

STM32F407CAN为0.857M/s,而STM32F103CAN为1M/s,因此无法通信。

为了实现通信,我们需要使得STM32F407和STM32F103CAN的最终时钟相一致,这一点可以通过配置RCC实现。

在这个例子中可以直接通过修改CAN的预分频,但归根结底就是要正确配置RCC。

(写到这里,有一点我不确定:

APB外设的时钟是否有最大值限制?

因为根据参考手册

图标上有:

是不是外设的最高时钟只能到48MHz?

这一点希望各位深入研究一下。

 

下面介绍RCC库函数的使用

在V1.0.0版本的库中,提供了如下函数:

(选择stm32f4xx_rcc.h把文件拉到最后,所有的文件都可以这么做来查看函数)

这里介绍棕色标记的函数。

/*FunctionusedtosettheRCCclockconfigurationtothedefaultresetstate*/

/*用于配置RCC时钟和复位的函数*/

voidRCC_DeInit(void);

/*Internal/externalclocks,PLL,CSSandMCOconfigurationfunctions*****/

/*内部外部时钟,PLL,CSS,MCO配置函数*/

voidRCC_HSEConfig(uint8_tRCC_HSE);

ErrorStatusRCC_WaitForHSEStartUp(void);

voidRCC_AdjustHSICalibrationValue(uint8_tHSICalibrationValue);

voidRCC_HSICmd(FunctionalStateNewState);

voidRCC_LSEConfig(uint8_tRCC_LSE);

voidRCC_LSICmd(FunctionalStateNewState);

voidRCC_PLLConfig(uint32_tRCC_PLLSource,uint32_tPLLM,uint32_tPLLN,uint32_tPLLP,uint32_tPLLQ);

voidRCC_PLLCmd(FunctionalStateNewState);

voidRCC_PLLI2SConfig(uint32_tPLLI2SN,uint32_tPLLI2SR);

voidRCC_PLLI2SCmd(FunctionalStateNewState);

voidRCC_ClockSecuritySystemCmd(FunctionalStateNewState);

voidRCC_MCO1Config(uint32_tRCC_MCO1Source,uint32_tRCC_MCO1Div);

voidRCC_MCO2Config(uint32_tRCC_MCO2Source,uint32_tRCC_MCO2Div);

/*System,AHBandAPBbussesclocksconfigurationfunctions******************/

/*系统时钟,AHB时钟,APB时钟配置函数*/

voidRCC_SYSCLKConfig(uint32_tRCC_SYSCLKSource);

uint8_tRCC_GetSYSCLKSource(void);

voidRCC_HCLKConfig(uint32_tRCC_SYSCLK);

voidRCC_PCLK1Config(uint32_tRCC_HCLK);

voidRCC_PCLK2Config(uint32_tRCC_HCLK);

voidRCC_GetClocksFreq(RCC_ClocksTypeDef*RCC_Clocks);

/*Peripheralclocksconfigurationfunctions**********************************/

/*外设时钟配置函数*/

voidRCC_RTCCLKConfig(uint32_tRCC_RTCCLKSource);

voidRCC_RTCCLKCmd(FunctionalStateNewState);

voidRCC_BackupResetCmd(FunctionalStateNewState);

voidRCC_I2SCLKConfig(uint32_tRCC_I2SCLKSource);

voidRCC_AHB1PeriphClockCmd(uint32_tRCC_AHB1Periph,FunctionalStateNewState);

voidRCC_AHB2PeriphClockCmd(uint32_tRCC_AHB2Periph,FunctionalStateNewState);

voidRCC_AHB3PeriphClockCmd(uint32_tRCC_AHB3Periph,FunctionalStateNewState);

voidRCC_APB1PeriphClockCmd(uint32_tRCC_APB1Periph,FunctionalStateNewState);

voidRCC_APB2PeriphClockCmd(uint32_tRCC_APB2Periph,FunctionalStateNewState);

voidRCC_AHB1PeriphResetCmd(uint32_tRCC_AHB1Periph,FunctionalStateNewState);

voidRCC_AHB2PeriphResetCmd(uint32_tRCC_AHB2Periph,FunctionalStateNewState);

voidRCC_AHB3PeriphResetCmd(uint32_tRCC_AHB3Periph,FunctionalStateNewState);

voidRCC_APB1PeriphResetCmd(uint32_tRCC_APB1Periph,FunctionalStateNewState);

voidRCC_APB2PeriphResetCmd(uint32_tRCC_APB2Periph,FunctionalStateNewState);

voidRCC_AHB1PeriphClockLPModeCmd(uint32_tRCC_AHB1Periph,FunctionalStateNewState);

voidRCC_AHB2PeriphClockLPModeCmd(uint32_tRCC_AHB2Periph,FunctionalStateNewState);

voidRCC_AHB3PeriphClockLPModeCmd(uint32_tRCC_AHB3Periph,FunctionalStateNewState);

voidRCC_APB1PeriphClockLPModeCmd(uint32_tRCC_APB1Periph,FunctionalStateNewState);

voidRCC_APB2PeriphClockLPModeCmd(uint32_tRCC_APB2Periph,FunctionalStateNewState);

/*Interruptsandflagsmanagementfunctions**********************************/

/*中断和标志管理函数*/

voidRCC_ITConfig(uint8_tRCC_IT,FunctionalStateNewState);

FlagStatusRCC_GetFlagStatus(uint8_tRCC_FLAG);

voidRCC_ClearFlag(void);

ITStatusRCC_GetITStatus(uint8_tRCC_IT);

voidRCC_ClearITPendingBit(uint8_tRCC_IT);

 

这里我们写一个RCC配置函数来说明各函数的用途,其中HSE=8MHz。

/**

*@说明配置STM32F407的时钟系统

*@参数无

*@返回无

*@说明voidClock_Config(void)按如下表格配置时钟

*

*==================================================================

*SupportedSTM32F4xxdevicerevision|RevA

*-----------------------------------------------------------------------------

*SystemClocksource|PLL(HSE)

*-----------------------------------------------------------------------------

*SYSCLK(Hz)|168000000

*-----------------------------------------------------------------------------

*HCLK(Hz)|168000000

*-----------------------------------------------------------------------------

*AHBPrescaler|1

*-----------------------------------------------------------------------------

*APB1Prescaler|4

*-----------------------------------------------------------------------------

*APB2Prescaler|2

*-----------------------------------------------------------------------------

*HSEFrequency(Hz)|8000000

*-----------------------------------------------------------------------------

*PLL_M|8

*-----------------------------------------------------------------------------

*PLL_N|336

*-----------------------------------------------------------------------------

*PLL_P|2

*-----------------------------------------------------------------------------

*PLL_Q|7

*===================================================================

*/

voidClock_Config(void){

ErrorStatusState;

uint32_tPLL_M;

uint32_tPLL_N;

uint32_tPLL_P;

uint32_tPLL_Q;

/*配置前将所有RCC重置为初始值*/

RCC_DeInit();

/*这里选择外部晶振(HSE)作为时钟源,因此首先打开外部晶振*/

RCC_HSEConfig(RCC_HSE_ON);

/*等待外部晶振进入稳定状态*/

while(RCC_WaitForHSEStartUp()!

=SUCCESS);

/*

**我们要选择PLL时钟作为系统时钟,因此这里先要对PLL时钟进行配置

*/

/*选择外部晶振作为PLL的时钟源*/

/*到这一步为止,已有HSE_VALUE=8MHz.

PLL_VCOinputclock=(HSE_VALUEorHSI_VALUE/PLL_M),

根据文档,这个值被建议在1~2MHz,因此我们令PLL_M=8,

即PLL_VCOinputclock=1MHz*/

PLL_M=8;

/*到这一步为止,已有PLL_VCOinputclock=1MHz.

PLL_VCOoutputclock=(PLL_VCOinputclock)*PLL_N,

这个值要用来计算系统时钟,我们令PLL_N=336,

即PLL_VCOoutputclock=336MHz.*/

PLL_N=336;

/*到这一步为止,已有PLL_VCOoutputclock=336MHz.

SystemClock=(PLL_VCOoutputclock)/PLL_P,

因为我们要SystemClock=168Mhz,因此令PLL_P=2.

*/

PLL_P=2;

/*这个系数用来配置SD卡读写,USB等功能,暂时不用,根据文档,暂时先设为7*/

PLL_Q=7;

/*配置PLL并将其使能,获得168Mhz的SystemClock时钟*/

RCC_PLLConfig(RCC_PLLSource_HSE,PLL_M,PLL_N,PLL_P,PLL_Q);

RCC_PLLCmd(ENABLE);

/*到了这一步,我们已经配置好了PLL时钟。

下面我们配置SyetemClock*/

/*选择PLL时钟作为系统时钟源*/

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

/*到了这一步,我们已经配置好了系统时钟,频率为168MHz.下面我们可以对AHB,APB,外设等的时钟进行配置*/

/*时钟的结构请参考用户手册*/

/*首先配置AHB时钟(HCLK).为了获得较高的频率,我们对SYSCLK1分频,得到HCLK*/

RCC_HCLKConfig(RCC_HCLK_Div1);

/*APBx时钟(PCLK)由AHB时钟(HCLK)分频得到,下面我们配置PCLK*/

/*APB1时钟配置.4分频,即PCLK1=42MHz*/

RCC_PCLK1Config(RCC_HCLK_Div4);

/*APB2时钟配置.2分频,即PCLK2=84MHz*/

RCC_PCLK2Config(RCC_HCLK_Div2);

/*****函数结束******/

/*以上函数可以大体上说明这些库函数的作用*/

}

对于RCC_PLLConfig();函数,大家可能会迷惑。

其函数原型为:

voidRCC_PLLConfig(uint32_tRCC_PLLSource,

uint32_tPLLM,

uint32_tPLLN,

uint32_tPLLP,

u

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1