STM32クロックの概要:
システムクロック図:(最初に解雇の図に移動してください!)
1.クロックシステム構造の要約
1. STM32には、HSI、HSE、LSI、LSE、PLLの5つのクロックソースがあります。(クロックソースをオンにした後、安定するまでに遅延があります!)
①、HSIは高速内部クロック、RC発振器、周波数は8MHz、精度は高くありません。
②HSEは、クォーツ/セラミック共振器または外部
クロックソースに接続できる高速外部クロックです。周波数範囲は4MHz〜16MHzです。
③LSIは、周波数40kHzの低速内蔵クロックRC発振器で、低電力クロックを提供します。WDG④
、LSEは低速外部クロックで、周波数32.768kHzの水晶振動子に接続されています。RTC
⑤、PLLが位相ロックループ周波数逓倍出力され、そのクロック入力ソースは、HSI / 2、HSE又はHSE / 2として選択することができます。
増倍周波数は2〜16回から選択できますが、最大出力周波数は72MHzを超えてはなりません。
2.システムクロックSYSCLKは
、①、HSIオシレータークロック
②、HSEオシレータークロック
③、PLLクロックの3つのクロックソースから取得できます。STM32は、PLL
として選択できるMCOピン(PA8)に出力するクロック信号を選択できます。
出力を2で割った値、HSI、HSE、またはシステムクロック。
4.いくつかの重要なクロック:
SYSCLK(システムクロック):
AHBバスクロック
APB1バスクロック(低速):最大36MHz
APB2バスクロック(高速):最大72MHzPLL
クロック
4.周辺機器を使用する前に、対応するクロックを最初に有効にする必要があります。
2.RCCレジスタ構成の要約
呼び出し構造の各メンバーは対応するレジスタです:(イタリックは一般的な構成です)すべて32ビットです!
typedef struct
{ __IO uint32_t CR; // HSI、HSE、CSS、PLLなどのフラグを有効にして準備完了__IO uint32_t CFGR; // PLLなどのクロックソースの選択、周波数分割係数の設定__IO uint32_t CIR; //クリア/クロックレディ割り込みを有効にする__IOuint32_t APB2RSTR; // APB2オンラインペリフェラルリセットレジスタ__IOuint32_t APB1RSTR; // APB1オンラインペリフェラルリセットレジスタ__IOuint32_t AHBENR; // DMA、SDIOおよびその他のクロックイネーブル__IO uint32_t APB2ENR; // APB2ラインペリフェラルクロックイネーブル__IOuint32_t APB1ENR; // APB1ラインペリフェラルクロックイネーブル__IOuint32_t BDCR; //バックアップドメイン制御レジスタ__IOuint32_t CSR; //制御ステータスレジスタ} RCC_TypeDef; stm32中国語の各レジスタの詳細な説明リファレンスガイドに詳細な説明があります。自分で確認する必要があります。レジスタの原理を理解するには、詳細を読む必要があります。クロックソースをオンにした後、安定するまで待ちます。
Stm32ライブラリ関数の分析:
最初にSystemInit();関数に移動します。
この関数は、上記のレジスタを初期化するために使用されます。
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();関数固有の構成
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
}
どの周波数を呼び出すために、マクロ定義は構成する周波数を定義します。構成
する周波数を保持し、構成する必要のない周波数をメモします
/ * #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
/上記の定義のいずれも有効になっていない場合、HSIがシステムクロックソースとして使用されます(リセット後のデフォルト)* /
周波数設定機能の内容を詳しく説明してください。例として72Mを取り上げます。(警告の大きな波!)
レジスタに関するマクロ定義の最後の波は
スキップするには多すぎます。。。詳細な解釈!
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
{
}
}
オーバー
追加するには、メイン関数の前にプリセット関数を設定するメソッド:
挿入:ヘッダーファイル内
:;はコメントの意味です。このセクションでは、最初にコンパイルSystemInitを実行します(最初にコメントを削除します)。
; 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