STM32H7 - pengaturan jam tanpa HAL

Belum lama berselang, perusahaan STM meluncurkan di pasar yang sangat kuat, dengan standar mikrokontroler, garis kristal STM32H7. Apa yang membuat saya tertarik padanya:

  • meningkatkan frekuensi inti hingga 400 MHz
  • peningkatan RAM, hingga 1 MB
  • 16 bit ADC
  • kompatibilitas pin-to-pin dengan seri F7

Saya berpikir dengan sempurna, saya menyolder kristal STM32H743IIT6 ke papan, bukan STM32F746IGT6 dan memulai proyek baru di SW4STM32.

Lebih mudah menggunakan tab Konfigurasi Jam program STM32CubeMX untuk menghitung koefisien pembagi dan faktor-faktor sistem jam mikrokontroler.

Pengaturan Jam:

  • kuarsa eksternal - 8 MHz
  • sumber frekuensi untuk PLL1 - kuarsa eksternal (HSE)
  • pembagi untuk PLL1 - 4 (DIVM1)
  • pengganda PLL1 - 400 (DIVN1)
  • pembagi keluaran - 2 (DIVP1, DIVQ1, DIVR1)

Dengan demikian, frekuensi inti (SYSCLK) adalah 400 MHz.



Selain STM32CubeMX, ada juga paket firmware STM32CubeH7, yang berisi sejumlah besar contoh untuk bekerja dengan periferal untuk STM32H7. Dari dia bahwa urutan inisialisasi sistem jam mikrokontroler diambil.

Informasi dan komentar diambil dari sumber-sumber berikut:

  • SystemClock_Config dari paket firmware STM32CubeH7
  • Manual referensi STM32H743 / 753 dan STM32H750 MCU 32-bit berbasis ARM tingkat lanjut
  • - Lembar Data STM32H743xI

Jadi mari kita mulai.

1. Menyalakan kuarsa eksternal dan menunggu kesiapan.

// Enable HSE RCC->CR |= RCC_CR_HSEON; // Wait till HSE is ready while((RCC->CR & RCC_CR_HSERDY) == 0); 

2. Indikasi sumber frekuensi untuk PLL1 - kuarsa eksternal.

 //RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC -> PLLCKSELR |= RCC_PLLCKSELR_PLLSRC_HSE; 

3. Nilai pembagi diatur ke 4.

 //PLLM = 4 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_5; //0 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_4; //0 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_3; //0 RCC -> PLLCKSELR |= RCC_PLLCKSELR_DIVM1_2; //1 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_1; //0 RCC -> PLLCKSELR &= ~RCC_PLLCKSELR_DIVM1_0; //0 

4. Faktor N dan pembagi P, Q, R

  //PLL1DIVR bits //DIVN1[8:0] 0 - 8 PLLN = 400 //DIVP1[6:0] 9 - 15 PLLP = 2 //DIVQ1[6:0] 16 - 22 PLLQ = 2 //DIVR1[6:0] 24 - 30 PLLR = 2 RCC -> PLL1DIVR |= 0x0101038F; 

5. PLL pembagi frekuensi pecahan (jika perlu)

 // /* Configure PLL PLL1FRACN */ //__HAL_RCC_PLLFRACN_CONFIG(RCC_OscInitStruct->PLL.PLLFRACN); RCC -> PLL1FRACR = 0; 

6. Indikasi rentang frekuensi input PLL1

  /* Select PLL1 input reference frequency range: VCI */ //__HAL_RCC_PLL_VCIRANGE(RCC_OscInitStruct->PLL.PLLRGE) ; RCC->PLLCFGR |= RCC_PLLCFGR_PLL1RGE_3; 

7. Indikasi rentang frekuensi keluaran PLL1

  /* Select PLL1 output frequency range : VCO */ //__HAL_RCC_PLL_VCORANGE(RCC_OscInitStruct->PLL.PLLVCOSEL) ; RCC->PLLCFGR &= ~RCC_PLLCFGR_PLL1VCOSEL; 

8. Menghidupkan pembagi output PLL1: P, Q, R

  /* Enable PLL System Clock output. */ // __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVP); //Bit 16 DIVP1EN: PLL1 DIVP divider output enable RCC->PLLCFGR |= RCC_PLLCFGR_DIVP1EN; /* Enable PLL1Q Clock output. */ //__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ); RCC->PLLCFGR |= RCC_PLLCFGR_DIVQ1EN; /* Enable PLL1R Clock output. */ // __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVR); RCC->PLLCFGR |= RCC_PLLCFGR_DIVR1EN; 

9. Dimasukkannya pembagi fraksional.

  /* Enable PLL1FRACN . */ //__HAL_RCC_PLLFRACN_ENABLE(); RCC->PLLCFGR |= RCC_PLLCFGR_PLL1FRACEN; 

10. Mulai PLL1 dan tunggu kesiapan

  /* Enable the main PLL. */ //__HAL_RCC_PLL_ENABLE(); RCC->CR |= RCC_CR_PLLON; while((RCC->CR & RCC_CR_PLL1RDY) == 0); 

PLL1 dikonfigurasikan dan dijalankan. Sekarang pilih sumber frekuensi SYSCLK dan atur pembagi bus.

11. Pembagi dengan 2 HPRE

  //RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; // MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); //HPRE[3:0]: D1 domain AHB prescaler //1000: rcc_hclk3 = sys_d1cpre_ck / 2 RCC -> D1CFGR |= RCC_D1CFGR_HPRE_3; //1 RCC -> D1CFGR &= ~RCC_D1CFGR_HPRE_2; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_HPRE_1; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_HPRE_0; //0 

12. Tanpa divisi D1CPRE

  //RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; //MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1CPRE, RCC_ClkInitStruct->SYSCLKDivider); //D1CPRE[3:0]: D1 domain Core prescaler //0xxx: sys_ck not divided (default after reset) RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_3; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_2; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_1; //0 RCC -> D1CFGR &= ~RCC_D1CFGR_D1CPRE_0; //0 

13. Tetapkan PLL1 sebagai sumber SYSCLK dan tunggu kesiapan

  //RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); //SW[2:0]: System clock switch //011: PLL1 selected as system clock (pll1_p_ck) RCC->CFGR &= ~RCC_CFGR_SW_2; //0 RCC->CFGR |= RCC_CFGR_SW_1; //1 RCC->CFGR |= RCC_CFGR_SW_0; //1 while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL1); 

14. Pembagi oleh 2 D1PPRE

  //D1PCLK1 Configuration //RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; //MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1PPRE, RCC_ClkInitStruct->APB3CLKDivider); //Bits 6:4 D1PPRE[2:0]: D1 domain APB3 prescaler //100: rcc_pclk3 = rcc_hclk3 / 2 RCC -> D1CFGR |= RCC_D1CFGR_D1PPRE_2; RCC -> D1CFGR &= ~RCC_D1CFGR_D1PPRE_1; RCC -> D1CFGR &= ~RCC_D1CFGR_D1PPRE_0; 

15. Pembagi oleh 2 D2PPRE1

  //PCLK1 Configuration //RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; //MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE1, (RCC_ClkInitStruct->APB1CLKDivider)); //Bits 6:4 D2PPRE1[2:0]: D2 domain APB1 prescaler //100: rcc_pclk1 = rcc_hclk1 / 2 RCC -> D2CFGR |= RCC_D2CFGR_D2PPRE1_2; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE1_1; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE1_0; 

16. Divider oleh 2 D2PPRE2

  //PCLK2 Configuration //RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; //MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE2, (RCC_ClkInitStruct->APB2CLKDivider)); //Bits 10:8 D2PPRE2[2:0]: D2 domain APB2 prescaler //100: rcc_pclk2 = rcc_hclk1 / 2 RCC -> D2CFGR |= RCC_D2CFGR_D2PPRE2_2; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE2_1; RCC -> D2CFGR &= ~RCC_D2CFGR_D2PPRE2_0; 

17. Pembagi oleh 2 D3PPRE

  //D3PCLK1 Configuration //RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; //MODIFY_REG(RCC->D3CFGR, RCC_D3CFGR_D3PPRE, (RCC_ClkInitStruct->APB4CLKDivider) ); //Bits 6:4 D3PPRE[2:0]: D3 domain APB4 prescaler //100: rcc_pclk4 = rcc_hclk4 / 2 RCC -> D3CFGR |= RCC_D3CFGR_D3PPRE_2; RCC -> D3CFGR &= ~RCC_D3CFGR_D3PPRE_1; RCC -> D3CFGR &= ~RCC_D3CFGR_D3PPRE_0; 

Untuk memastikan bahwa konfigurasi dan mulai berhasil, kami menggunakan output dari mikrokontroler MCO2. Output ini harus memiliki frekuensi 26.666 MHz dengan output splitter 15.



Bagus Frekuensi hadir, maka semuanya dilakukan dengan benar.

Source: https://habr.com/ru/post/id427435/


All Articles