Erklärung des STM32-Uhrensystems

Zusammenfassung der STM32-Uhr:

Systemuhrdiagramm: (Gehen Sie zuerst zum Diagramm, um zu schließen!)
Fügen Sie hier eine Bildbeschreibung ein

1. Zusammenfassung der Uhrensystemstruktur

1. STM32 verfügt über 5 Taktquellen: HSI, HSE, LSI, LSE, PLL. (Nach dem Einschalten der Taktquelle kommt es zu einer Verzögerung der Stabilisierung!)
  ①, HSI ist ein interner Hochgeschwindigkeitstakt, RC-Oszillator, die Frequenz beträgt 8 MHz, die Genauigkeit ist nicht hoch.
   ② HSE ist ein externer Hochgeschwindigkeitstakt, der an einen Quarz / Keramik-Resonator oder eine externe
Taktquelle angeschlossen werden kann. Der Frequenzbereich liegt zwischen 4 MHz und 16 MHz.
   ③ LSI ist ein langsamer RC-Oszillator mit niedriger Geschwindigkeit und einer Frequenz von 40 kHz, der einen Takt mit geringer Leistung liefert. WDG
   ④, LSE ist ein externer Takt mit niedriger Geschwindigkeit, der mit einem Quarzkristall mit einer Frequenz von 32,768 kHz verbunden ist. RTC
   PL, PLL ist ein Frequenzmultiplikationsausgang mit Phasenregelkreis, und seine Takteingangsquelle kann als HSI / 2, HSE oder HSE / 2 ausgewählt werden.
Die Multiplikationsfrequenz kann 2- bis 16-mal gewählt werden, die maximale Ausgangsfrequenz sollte jedoch 72 MHz nicht überschreiten.
2. Der Systemtakt SYSCLK kann aus drei Taktquellen stammen:
①, HSI-Oszillatortakt
②, HSE-Oszillatortakt
③, PLL-Takt
3. STM32 kann ein Taktsignal für die Ausgabe an den MCO-Pin (PA8) auswählen, das als PLL ausgewählt werden kann
Ausgang geteilt durch 2, HSI, HSE oder Systemuhr.

4. Mehrere wichtige Takte:
SYSCLK (Systemtakt):
AHB-Bustakt
APB1-Bustakt (niedrige Geschwindigkeit): bis zu 36
MHz APB2-Bustakt (hohe Geschwindigkeit): bis zu 72 MHz
PLL-Takt

4. Bevor ein Peripheriegerät verwendet wird, muss zuerst die entsprechende Uhr aktiviert werden.

2. Zusammenfassung der RCC-Registerkonfiguration

Jedes Mitglied in der Aufrufstruktur ist das entsprechende Register : (Kursiv ist die allgemeine Konfiguration) sind alle 32 Bit!
typedef struct
{ __IO uint32_t CR; // Aktivieren und Bereitstellen von Flags für HSI, HSE, CSS, PLL usw. __IO uint32_t CFGR; // Auswahl der Taktquelle für PLL usw., Einstellung des Frequenzteilungskoeffizienten __IO uint32_t CIR; // Löschen / Clock Ready Interrupt aktivieren __IO uint32_t APB2RSTR; // APB2 Online-Peripherie-Reset-Register __IO uint32_t APB1RSTR; // APB1 Online-Peripherie-Reset-Register __IO uint32_t AHBENR; // DMA, SDIO und andere Clock aktivieren __IO uint32_t APB2ENR; // APB2-Leitungsperipherietakt aktivieren __IO uint32_t APB1ENR; // APB1-Leitungsperipherietakt aktivieren __IO uint32_t BDCR; // Sicherungsdomänensteuerregister __IO uint32_t CSR; // Steuerstatusregister } RCC_TypeDef; detaillierte Erläuterung jedes Registers in stm32-Chinesisch Ausführliche Erklärungen finden Sie im Referenzhandbuch . Sie müssen es selbst überprüfen. Um das Prinzip des Registers zu verstehen , müssen Sie mehr lesen. Warten Sie nach dem Einschalten der Taktquelle auf deren Stabilität












Analyse der Stm32-Bibliotheksfunktion:
Gehen Sie zuerst zu SystemInit (); function. Mit
dieser Funktion werden die oben beschriebenen Register initialisiert

void SystemInit (void)
{
// 配置RCC_CR寄存器,对比指南:打开HSI RC时钟振荡器
  RCC->CR |= (uint32_t)0x00000001;

  /* 置零CFGR寄存器中 SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO 位 */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* 置零CR寄存器中 HSEON, CSSON and PLLON 位 */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /*置零CR寄存器中  HSEBYP */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* 置零CFGR寄存器中  PLLSRC, PLLXTPRE, PLLMUL  和 USBPRE/OTGFSPRE */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL
  /* 置零CR寄存器中  PLL2ON and PLL3ON*/
  RCC->CR &= (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /*关掉中断及其相应位 */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif         // 一般未执行

//以上的配置完成,下面是一个重点函数涉及到具体设置系统时钟的频率
  SetSysClock();


以下结束
#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

SetSysClock (); funktionsspezifische Konfiguration

static void SetSysClock(void)
{
// 配置对应的频率
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
#endif
}

Aufzurufen , die Frequenz, die Makrodefinition definiert die Frequenz zu konfigurieren:
halten Sie die Frequenz , die Sie konfigurieren möchten, beachten Sie die Frequenz , die nicht sein muss konfiguriert
/ * #define SYSCLK_FREQ_HSE HSE_VALUE /
/
define SYSCLK_FREQ_24MHz 24000000 /
/
define SYSCLK_FREQ_36MHz 36000000 /
/
define SYSCLK_FREQ_48MHz 48000000 /
/
#define SYSCLK_FREQ_56MHz 56000000 /
#define SYSCLK_FREQ_72MHz 72000000
/
Wenn keine der oben genannten Definitionen aktiviert ist, wird HSI als Systemtaktquelle verwendet (Standard nach dem Zurücksetzen) * /

Erläutern Sie den Inhalt der Frequenzkonfigurationsfunktion im Detail. Nehmen Sie als Beispiel 72M! (Eine große Warnwelle!) Die
letzte Welle von Makrodefinitionen zu Registern ist
zu viel, um sie zu überspringen. . . Detaillierte Interpretation!

static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* 使能打开 HSE CR低16位 */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /*  等待HSE稳定  */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;   //CR_低17位
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  //判断就绪
  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* 使能预取用缓存区,资料参考FALSH闪存参考资料! */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* 等待!参考资料*/
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

 //下面的是配置分频!分频!分频!,即配置开头图中AHB后面各个输出的频率(通过分频器分频)
    /* HCLK = SYSCLK  */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK/2  */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;


#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 
#else  //CL系列的暂时不看
  
    /* 输入频率配置 PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);   // 倍频 9倍 8*9 = 72!
#endif /* STM32F10X_CL */

    /* 使能打开 PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* 等待稳定 Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /*设置PLL作为系统时钟源  */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* 等待PLL生效 */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { 
  }
}

ÜBER

Um eine Methode zum Festlegen der voreingestellten Funktion festzulegen, die vor der Hauptfunktion ausgeführt werden soll:
In die Header-Datei einfügen
:; ist die Bedeutung des Kommentars. In diesem Abschnitt wird zuerst die Kompilierung SystemInit ausgeführt (zuerst den Kommentar entfernen).

; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
				;寄存器版本代码,因为没有用到SystemInit函数,所以注释掉以下代码为防止报错!
				;库函数版本代码,建议加上这里(外部必须实现SystemInit函数),以初始化stm32时钟等。
                ;IMPORT  SystemInit			
                ;LDR     R0, =SystemInit	
                ;BLX     R0                  
                LDR     R0, =__main
                BX      R0
                ENDP

Ich denke du magst

Origin blog.csdn.net/qq_45396672/article/details/103020133
Empfohlen
Rangfolge