STM32H7クロックツリーRCC分析---HALライブラリ構成(2)

前回の講義では、H7クロックツリーの基本的な概念について説明しました。次に、HALライブラリとCubeMxを使用して構成します。

繰り返しになりますが、この記事には時間がかかります。RCCの初期化プロセスを理解したい場合は、よくお読みください。最初は理解できないかもしれませんが、注意深く読むと必ず何かが得られます。

プロセスを開始する

H7の起動プロセスについて話しましょう。

システムの電源がオンになってリセットされ、スタートアップファイルstartup_stm32h743xx.sを入力して、このファイルのリセット割り込みサービスルーチンを実行します。

  • ファイルsystem_stm32h7xx.cにあるリセット割り込みサービスルーチンで関数SystemInitを実行します。
  • その後、スタートアップファイル__mainが呼び出され、最後にmain関数に入ります。

main関数を入力して、ユーザーアプリケーションプログラミングを開始します。プログラムを実行する前に、次のものが必要です。

  • MPUの初期化には、ライブラリファイルstm32h7xx_hal_cortex.cおよびstm32h7xx_hal_cortex.hが必要です。
  • キャッシュの初期化にはcore_cm7.hファイルが必要です。
  • Systickティックタイマーを初期化するためのHALライブラリ初期化関数HAL_Initには、ファイルstm32h7xx_hal.cが必要です。
  • システムクロックの初期化には、ライブラリファイルstm32h7xx_hal_rcc.cが必要です

HalライブラリのSystemInit関数はクロックに対してのみ実行することに注意してください。RCCクロック構成をデフォルトのリセット値にリセットし(HSIはデフォルトで有効になっています)、他の構成は実行しないため、クロックの初期化は次のようにする必要があります。ユーザーが構成します。

今日私たちが気にしているのは、システムクロックの初期化の最後のステップです

上記の4つのステップでは、HAL_Initを実行した後も、システムは内部高速クロックHSIを使用しています。H7の場合、HSIの主周波数は64MHzです。

クロック構成を変更する

それでは、時計の構成を変更する方法を見てみましょう。

ステップ1:
ボードの実際の水晶発振器サイズと一致するようにstm32h7xx_hal_conf.hファイルのHSE_VALUE構成のサイズを構成します。

私が使用する外部水晶は25Mhzなので、構成は25000000です。

#if !defined (HSE_VALUE) 
#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

ステップ2:次に、クロックを初期化します。主なものは、2つの構造パラメーターと2つの関数です。

RCC_ClkInitTypeDef RCC_ClkInitStruct;  // 配置时钟源相关参数
RCC_OscInitTypeDef RCC_OscInitStruct;  //配置系统时钟源及各个外设分频系数
 HAL_RCC_OscConfig()  //配置时钟源相关参数
 HAL_RCC_ClockConfig() //配置系统时钟源及各个外设分频系数

HAL_RCC_OscConfig()

HAL_RCC_OscConfig()、この関数はHALライブラリキーヘッダーファイルstm32h7xx_hal_rcc.hで宣言され、ファイルstm32h7xx_hal_rcc.cで定義されています。まず、関数宣言を見てみましょう。

__weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);

RCC_OscInitTypeDef構造体パラメーターは1つだけです。この構造体を見てみましょう。

typedef struct
{
    
    
 uint32_t OscillatorType; //需要选择配置的振荡器类型 
 uint32_t HSEState; //HSE 状态 
 uint32_t LSEState; //LSE 状态 
 uint32_t HSIState; //HIS 状态 
 uint32_t HSICalibrationValue; //HIS 校准值
 uint32_t LSIState; //LSI 状态 
uint32_t HSI48State //HSI48 的状态
uint32_t CSIState; //CSI 状态
uint32_t CSICalibrationValue; //CSI 校准值
 RCC_PLLInitTypeDef PLL; //PLL 配置
}RCC_OscInitTypeDef;

1つ目は、オシレーターのタイプを選択することです。たとえば、HSEをオンにする場合は、OscillatorTypeの値をRCC_OSCILLATORTYPE_HSEに設定し、次にHSEStateの値をRCC_HSE_ONに設定してHSEをオンにします。他のクロックソースHSI、LSI、およびLSEの場合、設定方法は同様です。

最後に、RCC_PLLInitTypeDef PLL;//PLL構成があります

これは、フェーズロックループを構成するためのものです。構造パラメータは次のとおりです。

typedef struct
{
    
    
 uint32_t PLLState; //PLL 状态
 uint32_t PLLSource; //PLL 时钟源
 uint32_t PLLM; //PLL 分频系数 M
 uint32_t PLLN; //PLL 倍频系数 N
 uint32_t PLLP; //PLL 分频系数 P
 uint32_t PLLQ; //PLL 分频系数 Q
uint32_t PLLR; //PLL 分频系数 R
uint32_t PLLRGE; //PLL1 时钟输入范围
uint32_t PLLVCOSEL; //PLL1 时钟输出范围
uint32_t PLLFRACN; //PLL1 VCO 乘数因子的小数部分
}RCC_PLLInitTypeDef;

ここでの周波数分割係数はすべてPLLフェーズロックループによって制御されます。私たちがしなければならないのは、特定の式を理解することだけです。

  • Fvco:VCO周波数
  • Fsys:システムクロック周波数。これは、PLL1のp分割出力クロック周波数でもあります。pll1_p_ck
  • Fpllq:PLL1のq分割出力クロック周波数pll1_q_ck
  • ref1_ck:PLL入力クロック周波数。HSI、CSI、HSEなどが可能です。

  • plln:PLL1周波数増倍率(PLL周波数増倍)、値の範囲:4〜512。
  • pllm:PLL1プリスケール係数(PLLに入る前の周波数分割)、値の範囲:2〜63。
  • pllp:周波数分割後のシステムクロックとして使用されるPLL1(PLL後の周波数分割)のp周波数分割係数、値の範囲:2〜128。(2の倍数である必要があります)
  • pllq:q PLL1の周波数分割係数(PLL後の周波数分割)、値の範囲:1〜128。

ここに画像の説明を挿入

VCO频率: Fvco= ref1_ck*(plln/pllm);
pll1_p_ck频率: Fsys=Fvco/pllp= ref1_ck*(plln/(pllm*pllp));
pll1_q_ck频率: Fpllq=Fvco/pllq= ref1_ck*(plln/(pllm*pllq));

ここに画像の説明を挿入
具体的な計算式は次のとおりです。これは前の記事でも説明されています。
ここに画像の説明を挿入

HAL_RCC_ClockConfig()

次に、次のように宣言されているHAL_RCC_ClockConfig()関数を確認します。

HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, 
uint32_t FLatency);

2つのパラメータがあります。最初のエントリパラメータRCC_ClkInitStructは、構造RCC_ClkInitTypeDefのポインタタイプであり
、SYSCLKクロックソースとSYSCLK、AHB、APB1、APB2、APB3、およびAPB4の周波数分割係数を設定するために使用され
ます。2番目のエントリパラメータFLatencyは、FLASH遅延を設定するために使用されます

stm32h7xx_hal_rcc.hで宣言されたRCC_ClkInitTypeDefの特定の場所を見てみましょう。

typedef struct
{
    
    
  uint32_t ClockType;             /*!< 要配置的时钟。
                              该参数可以是@ref RCC_System_Clock_Type 的值     */

  uint32_t SYSCLKSource;          /*!< 用作系统时钟的时钟源(SYSCLKS)*/

  uint32_t SYSCLKDivider;         /*!< 系统时钟分频    */

  uint32_t AHBCLKDivider;         /*!< AHB分频 */

  uint32_t APB3CLKDivider;        /*!APB3分频*/

  uint32_t APB1CLKDivider;        /*!APB1分频*/
  uint32_t APB2CLKDivider;        /*!APB2分频*/
  uint32_t APB4CLKDivider;      /*!APB4分频*/
}RCC_ClkInitTypeDef;


最初のパラメーターClockType構成は、SYSCLK、HCLK、D1PCLK1(PCLK3)、PCLK1、PCLK2、およびD3PCLK1(PCLK4)の6つのクロックを構成することを示しています。
2番目のパラメーターSYSCLKSource構成は、システムクロックソースをPLLとして選択します。
3番目のパラメーターSYSCLKDividerは、SYSCLK周波数分割係数を構成し
ます。4番目のパラメーターAHBCLKDividerは、AHB周波数分割係数
を構成します。5番目のパラメーターAPB1CLKDividerは、APB1周波数分割係数を構成します。6番目のパラメーターAPB2CLKDividerは、APB2周波数分割係数
を構成します。係数
。7番目のパラメーターAPB3CLKDividerは、APB3周波数分割係数を
構成します。8番目のパラメーターAPB4CLKDividerは、 APB4周波数分割係数を構成します。

これについては、以下で詳しく説明します

次に、2番目のパラメーターを確認します。FLatencyはFLASH遅延と電圧レギュレーターVOSを設定するために使用されます

次に、フラッシュの読み取り操作を知る必要があります

フラッシュ読み取り操作は、毎回フラッシュデータを読み取ることであり、その後の通常のデータ送信を確実にするために、一定時間遅延する必要があります。

VOS:STM32H7では、システムフラッシュは(電力制御レジスタ内の)電圧レギュレータ出力電圧レベル選択(VOS)の影響を受けます。

最高のフラッシュ読み取り速度を得るには、VOSレベルを1に設定してから、待機カウントを4に設定して、最高のフラッシュ読み取り速度を得る必要があります。ST公式ルーチンは4つの待機状態を使用します
ここに画像の説明を挿入
。STM32H7xxリファレンスマニュアルページ112

最終的なコードは次のとおりです。

注釈付き



/*
*********************************************************************************************************
*	函 数 名: SystemClock_Config
*	功能说明: 初始化系统时钟
*            	System Clock source            = PLL (HSE)
*            	SYSCLK(Hz)                     = 400000000 (CPU Clock)
*           	HCLK(Hz)                       = 200000000 (AXI and AHBs Clock)
*            	AHB Prescaler                  = 2
*            	D1 APB3 Prescaler              = 2 (APB3 Clock  100MHz)
*            	D2 APB1 Prescaler              = 2 (APB1 Clock  100MHz)
*            	D2 APB2 Prescaler              = 2 (APB2 Clock  100MHz)
*            	D3 APB4 Prescaler              = 2 (APB4 Clock  100MHz)
*            	HSE Frequency(Hz)              = 25000000
*            	VDD(V)                         = 3.3
*            	Flash Latency(WS)              = 4
*	形    参: 
*           plln:PLL1倍频系数(PLL倍频),取值范围:4~512.
*			pllm:PLL1预分频系数(进PLL之前的分频),取值范围:2~63.
*			pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)
*			pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128.
*
*
*            Fvco:VCO频率
*            Fsys:系统时钟频率,也是PLL1的p分频输出时钟频率 pll1_p_ck
*            Fpllq:PLL1的q分频输出时钟频率  pll1_q_ck
*            ref1_ck: PLL输入时钟频率,可以是HSI,CSI,HSE等.
*
*
*            plln:PLL1倍频系数(PLL倍频),取值范围:4~512.
*			 pllm:PLL1预分频系数(进PLL之前的分频),取值范围:2~63.
*		     pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数)
*			 pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128.
*
*
*
*			 VCO频率: Fvco= ref1_ck*(plln/pllm);
*			 pll1_p_ck频率: Fsys=Fvco/pllp= ref1_ck*(plln/(pllm*pllp));
*			 pll1_q_ck频率: Fpllq=Fvco/pllq= ref1_ck*(plln/(pllm*pllq));
*
*			CPU频率(rcc_c_ck)=pll1_p_ck频率=400Mhz 
*			rcc_aclk=rcc_hclk3=200Mhz
*			AHB1/2/3/4(rcc_hclk1/2/3/4)=200Mhz  
*			APB1/2/3/4(rcc_pclk1/2/3/4)=100Mhz  
*			FMC时钟频率=pll2_r_ck=((25/25)*512/2)=256Mhz
*
*
*          外部晶振为25M的时候,推荐值:plln=160,pllm=5,pllp=2,pllq=2.
*          得到:Fvco=25*(160/5)=800Mhz
*          CPU频率Fsys= pll1_p_ck频率=800/2=400Mhz
*          pll1_q_ck频率=800/2=400Mhz
*	返 回 值: 无

*********************************************************************************************************
*/
void SystemClock_Config(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
    
    
	HAL_StatusTypeDef ret=HAL_OK;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_OscInitTypeDef RCC_OscInitStruct;
	 /*使能供电配置更新 */
	MODIFY_REG(PWR->CR3,PWR_CR3_SCUEN, 0);
	
	/* 
      1、芯片内部的LDO稳压器输出的电压范围,可选VOS1,VOS2和VOS3,不同范围对应不同的Flash读速度,
         详情看参考手册的Table 12的表格。
      2、这里选择使用VOS1,电压范围1.15V - 1.26V。
    */
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {
    
    }
  
		
		/* 使能HSE,并选择HSE作为PLL时钟源 */
	RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState=RCC_HSE_ON;
	RCC_OscInitStruct.HSIState=RCC_HSI_OFF;
	RCC_OscInitStruct.CSIState=RCC_CSI_OFF;
	RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource=RCC_PLLSOURCE_HSE;

	RCC_OscInitStruct.PLL.PLLN=plln;
	RCC_OscInitStruct.PLL.PLLM=pllm;
	RCC_OscInitStruct.PLL.PLLP=pllp;
	RCC_OscInitStruct.PLL.PLLQ=pllq;

	RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
	RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
	ret=HAL_RCC_OscConfig(&RCC_OscInitStruct);
	if(ret!=HAL_OK) while(1);
  
		
		
		/* 
       选择PLL的输出作为系统时钟
       配置RCC_CLOCKTYPE_SYSCLK系统时钟
       配置RCC_CLOCKTYPE_HCLK 时钟,对应AHB1,AHB2,AHB3和AHB4总线
       配置RCC_CLOCKTYPE_PCLK1时钟,对应APB1总线
       配置RCC_CLOCKTYPE_PCLK2时钟,对应APB2总线
       配置RCC_CLOCKTYPE_D1PCLK1时钟,对应APB3总线
       配置RCC_CLOCKTYPE_D3PCLK1时钟,对应APB4总线     
		AHB 分频系数为 2,故其频率为HCLK=SYSCLK/2=200MHz。
		APB1 分频系数为 2,故其频率为 PCLK1=HCLK/2=100MHz。
		APB2分频系数为 2,故其频率为 PCLK2=HCLK/2=200/2=100MHz,
		APB3 分频系数为 2,故其频率PCLK3=HCLK/2=200/2=100MHz,
		APB4 的分频系数为 2,故其频率 PLCK4=HCLK/2=200/2=100MHz 
    */
		
	RCC_ClkInitStruct.ClockType=(RCC_CLOCKTYPE_SYSCLK|\
                                RCC_CLOCKTYPE_HCLK |\
                                RCC_CLOCKTYPE_D1PCLK1 |\
                                RCC_CLOCKTYPE_PCLK1 |\
                                RCC_CLOCKTYPE_PCLK2 |\
                                RCC_CLOCKTYPE_D3PCLK1);

	RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.SYSCLKDivider=RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.AHBCLKDivider=RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB1CLKDivider=RCC_APB1_DIV2; 
	RCC_ClkInitStruct.APB2CLKDivider=RCC_APB2_DIV2; 
	RCC_ClkInitStruct.APB3CLKDivider=RCC_APB3_DIV2;  
	RCC_ClkInitStruct.APB4CLKDivider=RCC_APB4_DIV2; 
	
	/* 此函数会更新SystemCoreClock,并重新配置HAL_InitTick */
	ret=HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
	if(ret!=HAL_OK) while(1);



   /*   使用IO的高速模式,要使能IO补偿,即调用下面三个函数 
      (1)使能CSI clock
      (2)使能SYSCFG clock
      (3)使能I/O补偿单元, 设置SYSCFG_CCCSR寄存器的bit0
    */
	__HAL_RCC_CSI_ENABLE() ;

	__HAL_RCC_SYSCFG_CLK_ENABLE() ;

	HAL_EnableCompensationCell();

}

主な関数呼び出し:

	SystemClock_Config(160,5,2,4);            //设置时钟400Mhz 

画像の説明を追加してください
画像の説明を追加してください

おすすめ

転載: blog.csdn.net/as480133937/article/details/123623820