目錄
一、PLL主時(shí)鐘初始化
1.1 時(shí)鐘使能
?1.2 配置好主時(shí)鐘配置結(jié)構(gòu)體
1.3 將配置好的值寫入到對(duì)應(yīng)的寄存器、初始化PLL主時(shí)鐘;
1.3.1 __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState)分析:?
1.3.2 給PLL相關(guān)寄存器賦值:
二、外設(shè)時(shí)鐘初始化
2.1等待周期的驗(yàn)證和寫入;
2.2 HCLK配置
2.3 SYSCLK配置、時(shí)鐘源選擇
2.3.1? PLL時(shí)鐘就緒檢測(cè)和__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)宏定義的分析
2.3.2 系統(tǒng)時(shí)鐘源選擇
2.4PCLK1和PCLK2配置
2.5 更新hal庫(kù)參數(shù)
三、總結(jié)
本人使用的單片機(jī)stm32f407vg,代碼來源stm32CubeMx。
時(shí)鐘配置如下
?主函數(shù)調(diào)用SystemClock_Config();,這也是RCC初始化函數(shù);
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 144;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
一、PLL主時(shí)鐘初始化
1.1 時(shí)鐘使能
__HAL_RCC_PWR_CLK_ENABLE();
#define __HAL_RCC_PWR_CLK_ENABLE() ? ? do { \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??__IO uint32_t tmpreg = 0x00U; \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SET_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* Delay after an RCC peripheral clock enabling */ \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UNUSED(tmpreg); \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??} while(0U)#define SET_BIT(REG, BIT) ? ? ((REG) |= (BIT))
?#define READ_BIT(REG, BIT) ? ?((REG) & (BIT))
#define RCC_APB1ENR_PWREN_Pos ? ? ? ? ? ? ?(28U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_APB1ENR_PWREN_Msk ? ? ? ? ? ? ?(0x1UL<<RCC_APB1ENR_PWREN_Pos)?
#define RCC_APB1ENR_PWREN ? ? ? ? ? ? ? ? ?RCC_APB1ENR_PWREN_Msk ? ?
把0x1左移28位,即使能電源接口時(shí)鐘;
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
這個(gè)函數(shù)是調(diào)壓器輸出電壓級(jí)別選擇,選擇級(jí)別1模式(默認(rèn)的模式),暫時(shí)不了解有什么作用;
?1.2 配置好主時(shí)鐘配置結(jié)構(gòu)體
?32的時(shí)鐘樹,暫時(shí)用到這些;
?RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
?RCC_OscInitStruct.HSEState = RCC_HSE_ON;#define RCC_OSCILLATORTYPE_NONE ? ? ? ? ? ?0x00000000U
#define RCC_OSCILLATORTYPE_HSE ? ? ? ? ? ? 0x00000001U
#define RCC_OSCILLATORTYPE_HSI ? ? ? ? ? ? 0x00000002U
#define RCC_OSCILLATORTYPE_LSE ? ? ? ? ? ? 0x00000004U
#define RCC_OSCILLATORTYPE_LSI ? ? ? ? ? ? 0x00000008U#define RCC_HSE_OFF ? ? ? ? ? ? ? ? ? ? ?0x00000000U
#define RCC_HSE_ON ? ? ? ? ? ? ? ? ? ? ? RCC_CR_HSEON
#define RCC_HSE_BYPASS ? ? ? ? ? ? ? ((uint32_t)(RCC_CR_HSEBYP | RCC_CR_HSEON))分別是配置時(shí)鐘源為(HSE\HSI\LSE\LSI); 選擇HSE時(shí)鐘狀態(tài)(使能、關(guān)閉、旁路)
? RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
? RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
? RCC_OscInitStruct.PLL.PLLM = 25;
? RCC_OscInitStruct.PLL.PLLN = 144;
? RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
? RCC_OscInitStruct.PLL.PLLQ = 4;#define RCC_PLL_NONE ? ? ? ? ? ? ? ? ? ? ?((uint8_t)0x00)
#define RCC_PLL_OFF ? ? ? ? ? ? ? ? ? ? ? ((uint8_t)0x01)
#define RCC_PLL_ON ? ? ? ? ? ? ? ? ? ? ? ?((uint8_t)0x02)#define RCC_PLLSOURCE_HSI ? ? ? ? ? ? ? ?RCC_PLLCFGR_PLLSRC_HSI
#define RCC_PLLSOURCE_HSE ? ? ? ? ? ? ? ?RCC_PLLCFGR_PLLSRC_HSE#define RCC_PLLCFGR_PLLSRC_HSE_Pos ? ? ? ? (22U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_PLLCFGR_PLLSRC_HSE_Msk? ??????????????????????????????????????????????????????????????????(0x1UL <<RCC_PLLCFGR_PLLSRC_HSE_Pos)?
#define RCC_PLLCFGR_PLLSRC_HSE ? ? ? ? ? ? RCC_PLLCFGR_PLLSRC_HSE_Msk?#define RCC_PLLP_DIV2 ? ? ? ? ? ? ? ? ?0x00000002U
#define RCC_PLLP_DIV4 ? ? ? ? ? ? ? ? ?0x00000004U
#define RCC_PLLP_DIV6 ? ? ? ? ? ? ? ? ?0x00000006U
#define RCC_PLLP_DIV8 ? ? ? ? ? ? ? ? ?0x00000008U分別為PLL時(shí)鐘(使能、關(guān)閉);PLL時(shí)鐘源選擇(HSE\HSI);PLL M\N\P,Q分頻器賦值;
1.3 將配置好的值寫入到對(duì)應(yīng)的寄存器、初始化PLL主時(shí)鐘;
? if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
? {
? ? Error_Handler();
? }調(diào)用這個(gè)函數(shù)進(jìn)行賦值,并通過返回值判斷是否初始化成功;
代碼很長(zhǎng),只留下HSE和PLL配置部分;
__weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
{
uint32_t tickstart, pll_config;
/* Check Null pointer */
if(RCC_OscInitStruct == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
/*------------------------------- HSE Configuration ------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
{
/* Check the parameters */
assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
/* When the HSE is used as system clock or clock source for PLL in these cases HSE will not disabled */
if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||\
((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
{
if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
{
return HAL_ERROR;
}
}
else
{
/* Set the new HSE configuration ---------------------------------------*/
__HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
/* Check the HSE State */
if((RCC_OscInitStruct->HSEState) != RCC_HSE_OFF)
{
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till HSE is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
{
if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till HSE is bypassed or disabled */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET)
{
if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
}
/*-------------------------------- PLL Configuration -----------------------*/
/* Check the parameters */
assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
{
/* Check if the PLL is used as system clock or not */
if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
{
if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
{
/* Check the parameters */
assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
/* Disable the main PLL. */
__HAL_RCC_PLL_DISABLE();
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till PLL is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
{
if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Configure the main PLL clock source, multiplication and division factors. */
WRITE_REG(RCC->PLLCFGR, (RCC_OscInitStruct->PLL.PLLSource | \
RCC_OscInitStruct->PLL.PLLM | \
(RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos) | \
(((RCC_OscInitStruct->PLL.PLLP >> 1U) - 1U) << RCC_PLLCFGR_PLLP_Pos) | \
(RCC_OscInitStruct->PLL.PLLQ << RCC_PLLCFGR_PLLQ_Pos)));
/* Enable the main PLL. */
__HAL_RCC_PLL_ENABLE();
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till PLL is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
{
if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Disable the main PLL. */
__HAL_RCC_PLL_DISABLE();
/* Get Start Tick */
tickstart = HAL_GetTick();
/* Wait till PLL is ready */
while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
{
if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
else
{
/* Check if there is a request to disable the PLL used as System clock source */
if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF)
{
return HAL_ERROR;
}
else
{
/* Do not return HAL_ERROR if request repeats the current configuration */
pll_config = RCC->CFGR;
if((READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLM) != RCC_OscInitStruct->PLL.PLLM) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLN) != RCC_OscInitStruct->PLL.PLLN) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLP) != RCC_OscInitStruct->PLL.PLLP) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLQ) != RCC_OscInitStruct->PLL.PLLQ))
{
return HAL_ERROR;
}
}
}
}
return HAL_OK;
}
首先是很長(zhǎng)一堆判斷是否出錯(cuò)的語句,不用管;
1.3.1 __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState)分析:?
? ? ? /* Set the new HSE configuration ---------------------------------------*/
? ? ? __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);?
而函數(shù)本身如下#define __HAL_RCC_HSE_CONFIG(__STATE__) ? ? ? ? ? ? ? ? ? ? ? ? \
? ? ? ? ? ? ? ? ? ? do { if ((__STATE__) == RCC_HSE_ON) ?????????????????????????? ? ????????? SET_BIT(RCC->CR, RCC_CR_HSEON); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
? ? ? ? ? ? ? ? ? ? ???????else if ((__STATE__) == RCC_HSE_BYPASS) ? \
? ? ? ? ? ? ? ? ? ? ???????{? ? ? ? ?SET_BIT(RCC->CR, RCC_CR_HSEBYP); ? ? ? ?\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SET_BIT(RCC->CR, RCC_CR_HSEON); ?? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \??????????????????????else ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\
? ? ? ? ? ? ? ? ? ? ????? { ? ? ? ? ??CLEAR_BIT(RCC->CR, RCC_CR_HSEON); ? ? ? \
? ? ? ? ? ? ? ? ? ? ? ? ???????????????CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????? ? } while(0U)簡(jiǎn)單看就是判斷HSE使能還是旁路。然后給RCC_CR對(duì)應(yīng)位賦值;
SET_BIT(RCC->CR, RCC_CR_HSEON); ?
#define SET_BIT(REG, BIT) ? ? ((REG) |= (BIT))
之前初始化的語句是:
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
對(duì)應(yīng)的值如下
#define RCC_CR_HSEON_Pos ? ? ? ? ? ? ? ? ? (16U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_CR_HSEON_Msk ? ? ? ? ? ? ? ? ? (0x1UL << RCC_CR_HSEON_Pos)? ? ? ? ??
#define RCC_CR_HSEON ? ? ? ? ? ? ? ? ? ? ? RCC_CR_HSEON_Msk ?即1左移16位;
而,SET_BIT(RCC->CR, RCC_CR_HSEBYP);
#define RCC_CR_HSEBYP_Pos ? ? ? ? ? ? ? ? ?(18U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_CR_HSEBYP_Msk ? ? ? ? ? ? ? ? ?(0x1UL << RCC_CR_HSEBYP_Pos)? ? ? ? ?
#define RCC_CR_HSEBYP ? ? ? ? ? ? ? ? ? ? ?RCC_CR_HSEBYP_Msk?即1左移18位;
暫時(shí)沒用過HSE旁路,好像是不用晶振、用外部信號(hào)輸入代替晶振。
1.3.2 給PLL相關(guān)寄存器賦值:
先關(guān)閉PLL時(shí)鐘:
__HAL_RCC_PLL_DISABLE();
#define __HAL_RCC_PLL_DISABLE() (*(__IO uint32_t *) RCC_CR_PLLON_BB = DISABLE)
#define RCC_PLLON_BIT_NUMBER ? ? ? 0x18U
#define RCC_CR_PLLON_BB ? ? ? ? ? ?(PERIPH_BB_BASE + (RCC_CR_OFFSET * 32U) + (RCC_PLLON_BIT_NUMBER * 4U))
#define PERIPH_BB_BASE ? ? ? ?0x42000000UL
/* --- CR Register --- */
#define RCC_CR_OFFSET ? ? ? ? ? ? ?(RCC_OFFSET + 0x00U)#define RCC_OFFSET ? ? ? ? ? ? ? ? (RCC_BASE - PERIPH_BASE)
簡(jiǎn)單點(diǎn)看就是在RCC_CR寄存器里。
0x18轉(zhuǎn)換為10進(jìn)制就是24,即bit24;
?賦0就是關(guān)閉PLL;使能PLL同理
主要賦值語句
WRITE_REG(RCC->PLLCFGR, (RCC_OscInitStruct->PLL.PLLSource | \
RCC_OscInitStruct->PLL.PLLM | \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos) ? ? ? ? ? ? | \???????(((RCC_OscInitStruct->PLL.PLLP >> 1U) - 1U) << RCC_PLLCFGR_PLLP_Pos) | \
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(RCC_OscInitStruct->PLL.PLLQ << RCC_PLLCFGR_PLLQ_Pos)));#define WRITE_REG(REG, VAL) ? ((REG) = (VAL))
首先是RCC_PLLSOURCE_HSE之前寫結(jié)構(gòu)體如下:
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
#define RCC_PLLSOURCE_HSE ? ? ? ? ? ? ? ?RCC_PLLCFGR_PLLSRC_HSE
#define RCC_PLLCFGR_PLLSRC_HSE_Pos ? ? ? ? (22U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_PLLCFGR_PLLSRC_HSE_Msk ? ? ? ? (0x1UL << RCC_PLLCFGR_PLLSRC_HSE_Pos) /*!< 0x00400000 */
#define RCC_PLLCFGR_PLLSRC_HSE ? ? ? ? ? ? RCC_PLLCFGR_PLLSRC_HSE_Msk ?即1左移22位,在RCC_PLLCFGR寄存器中作用選擇HSE;
?寄存器其他位和分頻器計(jì)算如下:
#define RCC_PLLCFGR_PLLN_Pos ? ? ? ? ? ? ? (6U)?
#define RCC_PLLP_DIV2 ? ? ? ? ? ? ? ? ?0x00000002U
#define RCC_PLLP_DIV4 ? ? ? ? ? ? ? ? ?0x00000004U
#define RCC_PLLP_DIV6 ? ? ? ? ? ? ? ? ?0x00000006U
#define RCC_PLLP_DIV8 ? ? ? ? ? ? ? ? ?0x00000008U#define RCC_PLLCFGR_PLLP_Pos ? ? ? ? ? ? ? (16U)?
#define RCC_PLLCFGR_PLLQ_Pos ? ? ? ? ? ? ? (24U) ??
PLLM不移動(dòng),PLLN左移6位,PLLQ左移24位
PLLP分頻的值右移1位、即除以2再減1,2~8分頻對(duì)應(yīng)00~11兩位,PLLP左移16位;
最后把各個(gè)數(shù)相或,數(shù)值寫到寄存器。
完畢后使能PLL時(shí)鐘。
這兒使用write,是因?yàn)椴僮鞯奈槐容^多,直接相與再寫入比較方便。
二、外設(shè)時(shí)鐘初始化
?
時(shí)鐘樹如上,結(jié)構(gòu)體成員賦值如下:
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
? RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
? RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
? RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
? RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;#define RCC_CLOCKTYPE_SYSCLK ? ? ? ? ? ? 0x00000001U
#define RCC_CLOCKTYPE_HCLK ? ? ? ? ? ? ? 0x00000002U
#define RCC_CLOCKTYPE_PCLK1 ? ? ? ? ? ? ?0x00000004U
#define RCC_CLOCKTYPE_PCLK2 ? ? ? ? ? ? ?0x00000008U#define RCC_SYSCLKSOURCE_HSI ? ? ? ? ? ? RCC_CFGR_SW_HSI
#define RCC_SYSCLKSOURCE_HSE ? ? ? ? ? ? RCC_CFGR_SW_HSE
#define RCC_SYSCLKSOURCE_PLLCLK ? ? ? ? ?RCC_CFGR_SW_PLL#define RCC_SYSCLK_DIV1 ? ? ? ? ? ? ? ? ?RCC_CFGR_HPRE_DIV1
#define RCC_SYSCLK_DIV2 ? ? ? ? ? ? ? ? ?RCC_CFGR_HPRE_DIV2...
#define RCC_SYSCLK_DIV512 ? ? ? ? ? ? ? ?RCC_CFGR_HPRE_DIV512#define RCC_HCLK_DIV1 ? ? ? ? ? ? ? ? ? ?RCC_CFGR_PPRE1_DIV1
#define RCC_HCLK_DIV2 ? ? ? ? ? ? ? ? ? ?RCC_CFGR_PPRE1_DIV2
...
#define RCC_HCLK_DIV16 ? ? ? ? ? ? ? ? ? RCC_CFGR_PPRE1_DIV16分別是要使能的外設(shè)時(shí)鐘(HCLK\SYSCLK\PCLK1\PCLK2);
系統(tǒng)時(shí)鐘源選擇(HSI\HSE\PLLCLK);AHB分頻器,APB1分頻器,APB2分頻器。
將配置好的結(jié)構(gòu)體成員寫到對(duì)應(yīng)的寄存器內(nèi);
? if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
? {
? ? Error_Handler();
? }調(diào)用這個(gè)函數(shù)并且判斷是否出錯(cuò);
函數(shù)主體如下:?
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
{
uint32_t tickstart;
/* Check Null pointer */
if(RCC_ClkInitStruct == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
assert_param(IS_FLASH_LATENCY(FLatency));
/* To correctly read data from FLASH memory, the number of wait states (LATENCY)
must be correctly programmed according to the frequency of the CPU clock
(HCLK) and the supply voltage of the device. */
/* Increasing the number of wait states because of higher CPU frequency */
if(FLatency > __HAL_FLASH_GET_LATENCY())
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
__HAL_FLASH_SET_LATENCY(FLatency);
/* Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register */
if(__HAL_FLASH_GET_LATENCY() != FLatency)
{
return HAL_ERROR;
}
}
/*-------------------------- HCLK Configuration --------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
{
/* Set the highest APBx dividers in order to ensure that we do not go through
a non-spec phase whatever we decrease or increase HCLK. */
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
{
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV16);
}
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
{
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, (RCC_HCLK_DIV16 << 3));
}
assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
}
/*------------------------- SYSCLK Configuration ---------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
{
assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
/* HSE is selected as System Clock Source */
if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
{
/* Check the HSE ready flag */
if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
{
return HAL_ERROR;
}
}
/* PLL is selected as System Clock Source */
else if((RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) ||
(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLRCLK))
{
/* Check the PLL ready flag */
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
{
return HAL_ERROR;
}
}
/* HSI is selected as System Clock Source */
else
{
/* Check the HSI ready flag */
if(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
{
return HAL_ERROR;
}
}
__HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
/* Get Start Tick */
tickstart = HAL_GetTick();
while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
{
if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
/* Decreasing the number of wait states because of lower CPU frequency */
if(FLatency < __HAL_FLASH_GET_LATENCY())
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
__HAL_FLASH_SET_LATENCY(FLatency);
/* Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register */
if(__HAL_FLASH_GET_LATENCY() != FLatency)
{
return HAL_ERROR;
}
}
/*-------------------------- PCLK1 Configuration ---------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
{
assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
}
/*-------------------------- PCLK2 Configuration ---------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
{
assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
}
/* Update the SystemCoreClock global variable */
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> RCC_CFGR_HPRE_Pos];
/* Configure the source of time base considering new system clocks settings */
HAL_InitTick (uwTickPrio);
return HAL_OK;
}
2.1等待周期的驗(yàn)證和寫入;
? if(FLatency > __HAL_FLASH_GET_LATENCY())
? {
? ? /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
? ? __HAL_FLASH_SET_LATENCY(FLatency);? ? /* Check that the new number of wait states is taken into account to access the Flash
? ? memory by reading the FLASH_ACR register */
? ? if(__HAL_FLASH_GET_LATENCY() != FLatency)
? ? {
? ? ? return HAL_ERROR;
? ? }
? }初步看是判斷等待周期的,
#define FLASH_LATENCY_2 ? ? ? ? ? ? ? ?FLASH_ACR_LATENCY_2WS ?
???????????????????????????????????????????????????????????????? /*!< FLASH Two Latency cycles ? ? ?*/
#define FLASH_ACR_LATENCY_2WS ? ? ? ? ?0x00000002U ??
#define __HAL_FLASH_GET_LATENCY() ? ? (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY))
?#define __HAL_FLASH_SET_LATENCY(__LATENCY__) (*(__IO uint8_t *)ACR_BYTE0_ADDRESS = (uint8_t)(__LATENCY__))
#define ACR_BYTE0_ADDRESS ? ? ? ? ? 0x40023C00U?
我們主要操作RCC_CFGR寄存器,所以在切換時(shí)鐘源時(shí)要插入1、2個(gè)等待周期。
所以做法是調(diào)用函數(shù)__HAL_FLASH_GET_LATENCY()
讀取FLASH_ACR寄存器LATENCY位。當(dāng)?shù)却芷谛∮?時(shí)要進(jìn)行處理。
方法就是給LATENCY地址寫值,寫的值就是FLASH_LATENCY_2。
至于為什么沒有用很多基地址組合,因?yàn)镕LASH下的寄存器很重要,能自主讀寫的很少。
2.2 HCLK配置
? /*-------------------------- HCLK Configuration --------------------------*/
? if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
? {
? ? /* Set the highest APBx dividers in order to ensure that we do not go through
? ? ? ?a non-spec phase whatever we decrease or increase HCLK. */
? ? if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
? ? {
? ? ? MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV16);
? ? }? ? if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
? ? {
? ? ? MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, (RCC_HCLK_DIV16 << 3));
? ? }? ? assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
? ?MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
? }之前結(jié)構(gòu)體HCLK和其他三個(gè)相或,所以這兒的if判斷都要進(jìn)入里面;
后面兩個(gè)if語句都是判斷欲開啟的外設(shè)時(shí)鐘有沒有PCLK1、PCLK2,都有,然后賦值16分頻,具體的后面詳解;
這部分主要是
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
#define MODIFY_REG(REG, CLEARMASK, SETMASK) ?WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
這兒括號(hào)很多,一開始看錯(cuò)了,看成前面的寄存器和后面一堆相與,怎么也不對(duì),其實(shí)是寄存器和中間那部分相與,再和后面那部分相或;這個(gè)宏定義作用是給這個(gè)寄存器寫數(shù)值,后面一堆按位運(yùn)算的作用是只寫給想修改的位,其他的保持不變。
READ_REG(REG)就是讀RCC_CFGR寄存器的值;
#define RCC_CFGR_HPRE_Pos ? ? ? ? ? ? ? ? ?(4U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_HPRE_Msk ? ? ? ? ? ? ? ? ?(0xFUL << RCC_CFGR_HPRE_Pos) ? ? ? ?????????????????????????????????????????????????????????????????????????????????/*!< 0x000000F0 */
#define RCC_CFGR_HPRE ? ? ? ? ? ? ? ? ? ? ?RCC_CFGR_HPRE_Msk ?RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
#define RCC_SYSCLK_DIV1 ? ? ? ? ? ? ? ? ?RCC_CFGR_HPRE_DIV1
#define RCC_CFGR_HPRE_DIV1 ? ? ? ? ? ? ? ? 0x00000000U? ? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_HPRE_DIV2 ? ? ? ? ? ? ? ? 0x00000080U? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_HPRE_DIV4 ? ? ? ? ? ? ? ? 0x00000090U? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_CFGR_HPRE_DIV8 ? ? ? ? ? ? ? ? 0x000000A0U? ? ? ? ? ? ? ? ? ? ??
...? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_HPRE_DIV512 ? ? ? ? ? ? ? 0x000000F0U?這個(gè)宏定義的邏輯就是寄存器本來的值和(0x000000f0取反)也就是0xffffff0f相與,得到的值是bit[5:8]清零,其他位不變,這個(gè)值再和分頻的值相或,0的位置變?yōu)橄雽懭氲闹怠?/strong>
2.3 SYSCLK配置、時(shí)鐘源選擇
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
? {
? ? assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
? ? /* PLL is selected as System Clock Source */
? ? else if((RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) ? ||
? ? ? ? ? ? (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLRCLK))
? ? {
? ? ? /* Check the PLL ready flag */
? ? ? if(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
? ? ? {
? ? ? ? return HAL_ERROR;
? ? ? }
? ? }? ? __HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
? ? /* Get Start Tick */
? ? tickstart = HAL_GetTick();? ? while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
? ? {
? ? ? if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
? ? ? {
? ? ? ? return HAL_TIMEOUT;
? ? ? }
? ? }
? }? /* Decreasing the number of wait states because of lower CPU frequency */
? if(FLatency < __HAL_FLASH_GET_LATENCY())
? {
? ? ?/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
? ? __HAL_FLASH_SET_LATENCY(FLatency);? ? /* Check that the new number of wait states is taken into account to access the Flash
? ? memory by reading the FLASH_ACR register */
? ? if(__HAL_FLASH_GET_LATENCY() != FLatency)
? ? {
? ? ? return HAL_ERROR;
? ? }
? }代碼很長(zhǎng),去掉一部分HSE、HSI作為時(shí)鐘源的代碼原理和PLL的一致。
2.3.1? PLL時(shí)鐘就緒檢測(cè)和__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)宏定義的分析
首先是時(shí)鐘就緒標(biāo)志位的檢測(cè),就比如我要PLL作為主時(shí)鐘的時(shí)鐘源。那么在開啟主時(shí)鐘之前必須要保證PLL是打開的,軟件通過CR寄存器下PLLRDY判斷。
?通過函數(shù)? ? ?
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
? ? ? {
? ? ? ? return HAL_ERROR;
? ? ? }#define __HAL_RCC_GET_FLAG(__FLAG__) (((((((__FLAG__) >> 5U) == 1U)? RCC->CR :((((__FLAG__) >> 5U) == 2U) ? RCC->BDCR :((((__FLAG__) >> 5U) == 3U)? RCC->CSR :RCC->CIR))) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))!= 0U)? 1U : 0U)
這個(gè)宏定義很長(zhǎng),下面是__FLAG__可以選的值/* Flags in the CR register */
#define RCC_FLAG_HSIRDY ? ? ? ? ? ? ? ? ?((uint8_t)0x21)
#define RCC_FLAG_HSERDY ? ? ? ? ? ? ? ? ?((uint8_t)0x31)
#define RCC_FLAG_PLLRDY ? ? ? ? ? ? ? ? ?((uint8_t)0x39)
#define RCC_FLAG_PLLI2SRDY ? ? ? ? ? ? ? ((uint8_t)0x3B)/* Flags in the BDCR register */
#define RCC_FLAG_LSERDY ? ? ? ? ? ? ? ? ?((uint8_t)0x41)/* Flags in the CSR register */
#define RCC_FLAG_LSIRDY ? ? ? ? ? ? ? ? ?((uint8_t)0x61)
#define RCC_FLAG_BORRST ? ? ? ? ? ? ? ? ?((uint8_t)0x79)
#define RCC_FLAG_PINRST ? ? ? ? ? ? ? ? ?((uint8_t)0x7A)
#define RCC_FLAG_PORRST ? ? ? ? ? ? ? ? ?((uint8_t)0x7B)
#define RCC_FLAG_SFTRST ? ? ? ? ? ? ? ? ?((uint8_t)0x7C)
#define RCC_FLAG_IWDGRST ? ? ? ? ? ? ? ? ((uint8_t)0x7D)
#define RCC_FLAG_WWDGRST ? ? ? ? ? ? ? ? ((uint8_t)0x7E)
#define RCC_FLAG_LPWRRST ? ? ? ? ? ? ? ? ((uint8_t)0x7F)#define RCC_FLAG_MASK ?((uint8_t)0x1FU)
將宏定義拆開來看:
if((((((__FLAG__) >> 5U) == 1U)? RCC->CR :((((__FLAG__) >> 5U) == 2U) ? RCC->BDCR :((((__FLAG__) >> 5U) == 3U)? RCC->CSR :RCC->CIR))) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))!= 0U)? ?return 1;
else? ? ? ?return 0;
把((__FLAG__) >> 5U) 看成 b;就是
if(b == 1)
{
? ? ? ? if(RCC_CR & (1U << ((__FLAG__) & RCC_FLAG_MASK)) != 0u)
? ? ? ? ????????return 1;
? ? ? ? else
? ? ? ? ? ? ? ? return 0;
}
else if (b == 2)
{
????????
? ? ? ? if(RCC_BDCR & (1U << ((__FLAG__) & RCC_FLAG_MASK)) != 0u)
? ? ? ? ????????return 1;
? ? ? ? else
? ? ? ? ? ? ? ? return 0;
}
...
#define RCC_FLAG_PLLRDY ? ? ? ? ? ? ? ? ?((uint8_t)0x39)
對(duì)于PLL標(biāo)準(zhǔn)位,0x39右移5位等于1,0x39和0x1f相與,也就是取后5位,得到0x19;1左移0x19位是1左移25位,也就是PLLRDY位,其他位都是0。再和RCC_CR相與,就是取第25位是0,還是1.
當(dāng)是1時(shí),也就是PLL開啟時(shí)得到的結(jié)果不等于0;當(dāng)未硬件置一時(shí),0和1相與也是0,得到的結(jié)果就是0;
2.3.2 系統(tǒng)時(shí)鐘源選擇
__HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
#define __HAL_RCC_SYSCLK_CONFIG(__RCC_SYSCLKSOURCE__) MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, (__RCC_SYSCLKSOURCE__))
?#define RCC_CFGR_SW_Pos ? ? ? ? ? ? ? ? ? ?(0U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_SW_Msk ? ? ? ? ? ? ? ? ? ?(0x3UL << RCC_CFGR_SW_Pos) ? ? ? ? ?#define RCC_CFGR_SW ? ? ? ? ? ? ? ? ? ? ? ?RCC_CFGR_SW_Msk ?????????/*!< 0x00000003 */
#define RCC_SYSCLKSOURCE_PLLCLK ? ? ? ? ?RCC_CFGR_SW_PLL
#define RCC_CFGR_SW_HSI ? ? ? ? ? ? ? ? ? ?0x00000000U? ? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_SW_HSE ? ? ? ? ? ? ? ? ? ?0x00000001U? ? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_SW_PLL ? ? ? ? ? ? ? ? ? ?0x00000002U? ? ? ? ? ? ? ? ? ? ? ? ?
函數(shù)邏輯和之前一樣,給最后兩位賦值,其他位保持不變。
? if(FLatency < __HAL_FLASH_GET_LATENCY())
? {
? ? ?/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
? ? __HAL_FLASH_SET_LATENCY(FLatency);? ? /* Check that the new number of wait states is taken into account to access the Flash
? ? memory by reading the FLASH_ACR register */
? ? if(__HAL_FLASH_GET_LATENCY() != FLatency)
? ? {
? ? ? return HAL_ERROR;
? ? }
? }這部分是減少等待周期;大于2時(shí),寫入到FLASH_ACR_LATENCY,和之前一樣。
2.4PCLK1和PCLK2配置
?/*-------------------------- PCLK1 Configuration ---------------------------*/
? if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
? {
? ? assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
? }? /*-------------------------- PCLK2 Configuration ---------------------------*/
? if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
? {
? ? assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
? ? MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2,????????????????????????????????????????????????????????((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
? }RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
#define RCC_CFGR_PPRE1_Pos ? ? ? ? ? ? ? ? (10U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_CFGR_PPRE1_Msk ? ? ? ? ? ? ? ? (0x7UL << RCC_CFGR_PPRE1_Pos) ? ? ??????????????????????????????????????????????????????????????????????????????????????????/*!< 0x00001C00 */
#define RCC_CFGR_PPRE1 ? ? ? ? ? ? ? ? ? ? RCC_CFGR_PPRE1_Msk?#define RCC_CFGR_PPRE2_Pos ? ? ? ? ? ? ? ? (13U) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_CFGR_PPRE2_Msk ? ? ? ? ? ? ? ? (0x7UL << RCC_CFGR_PPRE2_Pos) ? ? ??????????????????????????????????????????????????????????????????????????????????????????/*!< 0x0000E000 */
#define RCC_CFGR_PPRE2 ? ? ? ? ? ? ? ? ? ? RCC_CFGR_PPRE2_Msk#define RCC_HCLK_DIV1 ? ? ? ? ? ? ? ? ? ?RCC_CFGR_PPRE1_DIV1
#define RCC_HCLK_DIV2 ? ? ? ? ? ? ? ? ? ?RCC_CFGR_PPRE1_DIV2
...
#define RCC_HCLK_DIV16 ? ? ? ? ? ? ? ? ? RCC_CFGR_PPRE1_DIV16#define RCC_CFGR_PPRE1_DIV1 ? ? ? ? ? ? ? ?0x00000000U? ? ? ? ? ? ? ? ? ? ? ??
#define RCC_CFGR_PPRE1_DIV2 ? ? ? ? ? ? ? ?0x00001000U? ? ? ? ? ? ? ? ? ? ? ??
...? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_PPRE1_DIV16 ? ? ? ? ? ? ? 0x00001C00U?分別是給RCC_CFGR,bit[10:12]和bit[13:15]寫入數(shù)據(jù),數(shù)據(jù)內(nèi)容是分頻值。
對(duì)于PCLK2分頻值用到PPRE1的值,所以要左移三位。
在這兒可以直接用PPER2的分頻值,但不知道為什么沒有用;
#define RCC_CFGR_PPRE2_DIV1 ? ? ? ? ? ? ? ?0x00000000U? ? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_PPRE2_DIV2 ? ? ? ? ? ? ? ?0x00008000U? ? ? ? ? ? ? ? ? ? ? ?
...? ? ? ? ? ? ? ? ? ? ?
#define RCC_CFGR_PPRE2_DIV16 ? ? ? ? ? ? ? 0x0000E000U?
2.5 更新hal庫(kù)參數(shù)
? /* Update the SystemCoreClock global variable */
? SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE)>> RCC_CFGR_HPRE_Pos];? /* Configure the source of time base considering new system clocks settings */
? HAL_InitTick (uwTickPrio);翻譯下來的意思是:更新SystemCoreClock全局變量;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 鑒于新的系統(tǒng)時(shí)鐘設(shè)置來配置時(shí)基。
這兒涉及到hal庫(kù),目前還不太懂,希望有大佬補(bǔ)充。
三、總結(jié)
時(shí)鐘的配置最核心的還是看懂時(shí)鐘樹,知道時(shí)鐘源怎么選,時(shí)鐘這個(gè)路怎么走的,到哪個(gè)外設(shè)。至于配置完全可以利用軟件的便利,節(jié)省大量的工作,對(duì)于函數(shù)的分析其實(shí)是筆者較真了。但是一點(diǎn)點(diǎn)梳理下來,還是學(xué)習(xí)到很多函數(shù)的寫法,宏定義的運(yùn)用。同時(shí),以后可能面對(duì)的時(shí)鐘配置遠(yuǎn)超過CubeMX軟件使用的復(fù)雜度,掌握配置時(shí)鐘整體的思路至關(guān)重要。文章來源:http://www.zghlxwxcb.cn/news/detail-616752.html
參考資料:stm32f4xx中文參考手冊(cè)文章來源地址http://www.zghlxwxcb.cn/news/detail-616752.html
到了這里,關(guān)于stm32 hal庫(kù) RCC初始化函數(shù)SystemClock_Config()梳理分析、初步細(xì)致學(xué)習(xí)(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!