目录
一:前言
我们使用的是STM32F103CT86的型号
1:介绍
时钟在在我们的单片机中非常重要,相当于我们的人类的心脏;简单来说,时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波;
2:默认时钟
#include "stm32f1xx_hal.h"
int main(void){
//这个函数用于初始化HAL库;它必须是主程序中执行的第一条指令
HAL_Init();
//PA8引脚输出系统时钟
HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);
}
每个文件都是从汇编文件开始的,
对于我们的单片机而言不管我们上电复位,按键复位,NVIC system ,程序都会进入复位向量;
可以看到复位向量里面首先调用了SystemInit;然后去__main(多了__,首先做了一些准备的工作,其次才开始调用我们c语言中的mian函数)
二:STM32F407
f4的时钟源和F1相同
简图:
时钟树
挂在APB1总线上面的时钟为:42MHZ。但是定时器时钟为:84MHZ
挂在APB2总线上面的时钟为:84MHZ。但是定时器时钟为:168MHZ
APB2/APB1
外设挂载哪个总线上面:STM32F407VET6数据手册.pdf 17页
三:SystemInit
我们研究源码看看在复位向量第一个调用的SystemInit,SystemInit里面到底做了什么
A:时钟控制寄存器(RCC_CR)
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= 0x00000001U; //时钟控制寄存器(RCC_CR)
B:时钟配置寄存器(RCC_CFGR)
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)
RCC->CFGR &= 0xF8FF0000U;
#else
RCC->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFFU;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= 0xFF80FFFFU;
0xF8FF0000U=1111 1000 1111 1111 0000 0000 0000 0000;
与操作--清零;用于清除需要的 BIT位(0),不影响其他位(1)
C:时钟控制寄存器(RCC_CR)
对时钟控制寄存器(RCC_CR)操作的2次
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFFU;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
0xFEF6FFFFU=1111 1110 1111 0110 1111 1111 1111 1111
第二次操作:RCC->CR &= 0xFFFBFFFFU;-----18位清零
我们可以看到只要失能HSEBYP的前提是关闭振荡器;所以操作RCC->CR寄存器才会分2次写,第一次:关闭振荡器;第二次:失能HSEBYP
D:时钟配置寄存器(RCC_CFGR)
RCC->CFGR &= 0xFF80FFFFU;
在上面配置过了CFGP寄存器为什么还要在配置一遍;因为和上面的CR寄存器一样,关闭某个东西是有前提的
E:实验
#include "stm32f1xx_hal.h"
uint32_t GetPCLK1Freq;
uint32_t GetPCLK2Freq;
uint32_t GetHCLKFreq;
int main(void){
//这个函数用于初始化HAL库;它必须是主程序中执行的第一条指令
HAL_Init();
//PA8引脚输出系统时钟
HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);
SystemCoreClockUpdate();
GetHCLKFreq=HAL_RCC_GetHCLKFreq();
GetPCLK1Freq=HAL_RCC_GetPCLK1Freq();
GetPCLK2Freq=HAL_RCC_GetPCLK2Freq();
}
开启仿真
可以看到HSL系统默认的时钟为----0x007A1200=8000000=8MHZ;可以验证我们的实验正确。
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= 0x00000001U;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)
RCC->CFGR &= 0xF8FF0000U;
#else
RCC->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFFU;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= 0xFF80FFFFU;
#if defined(STM32F105xC) || defined(STM32F107xC)
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= 0xEBFFFFFFU;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000U;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000U;
#elif defined(STM32F100xB) || defined(STM32F100xE)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000U;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000U;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000U;
#endif /* STM32F105xC */
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
#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
}
四:HSL
A:F1
目的:得到64M的系统时钟-------选择内部高速时钟(HSL)做为时钟源,通过PLL的倍率调节为64MHZ;同时PLL锁相环做为系统时钟源
#include "stm32f1xx_hal.h"
void RCC_Clock_HSLInit(void)
{
RCC_OscInitTypeDef RCC_OscInitType;
RCC_ClkInitTypeDef RCC_ClkInitType;
//选择HSL做为时钟源
RCC_OscInitType.OscillatorType=RCC_OSCILLATORTYPE_HSI;
RCC_OscInitType.HSIState=RCC_HSI_ON;
RCC_OscInitType.HSICalibrationValue=RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitType.PLL.PLLState=RCC_PLL_ON;
RCC_OscInitType.PLL.PLLSource=RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitType.PLL.PLLMUL=RCC_PLL_MUL16;
HAL_RCC_OscConfig(&RCC_OscInitType);
//PLL做为系统时钟源
RCC_ClkInitType.ClockType=(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitType.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitType.AHBCLKDivider=RCC_SYSCLK_DIV1;
RCC_ClkInitType.APB1CLKDivider=RCC_HCLK_DIV2;
RCC_ClkInitType.APB2CLKDivider= RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitType,FLASH_LATENCY_2);
}
#include "stm32f1xx_hal.h"
#include "rcc.h"
uint32_t GetPCLK1Freq;
uint32_t GetPCLK2Freq;
uint32_t GetHCLKFreq;
int main(void)
{
//这个函数用于初始化HAL库;它必须是主程序中执行的第一条指令
HAL_Init();
RCC_Clock_HSLInit();
//SystemClock_Config();
//PA8引脚输出系统时钟
HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);
SystemCoreClockUpdate();
GetHCLKFreq=HAL_RCC_GetHCLKFreq();
GetPCLK1Freq=HAL_RCC_GetPCLK1Freq();
GetPCLK2Freq=HAL_RCC_GetPCLK2Freq();
}
频率越高,系统会越来越稳定;所以一般情况下我们选择使用外部的HSE,通过PLL可以转变为72HZ; 除非在外部晶振坏了或者考虑成本的情况下才会不会使用内部的晶振。
根据仿真可以得到: HCLK=64Mhz
PCLK2=64MhZ
PCLK2=32MHZ
和我们实验想要达到的结果一样
B:F407
/**
* @brief 时钟设置函数
* @param plln: 主PLL倍频系数(PLL倍频), 取值范围: 64~432.
* @param pllm: 主PLL和音频PLL预分频系数(进PLL之前的分频), 取值范围: 2~63.
* @param pllp: 主PLL的p分频系数(PLL之后的分频), 分频后作为系统时钟, 取值范围: 2, 4, 6, 8.(仅限这4个值)
* @param pllq: 主PLL的q分频系数(PLL之后的分频), 取值范围: 2~15.
* @note
*
* Fvco: VCO频率
* Fsys: 系统时钟频率, 也是主PLL的p分频输出时钟频率
* Fq: 主PLL的q分频输出时钟频率
* Fs: 主PLL输入时钟频率, 可以是HSI, HSE等.
* Fvco = Fs * (plln / pllm);
* Fsys = Fvco / pllp = Fs * (plln / (pllm * pllp));
* Fq = Fvco / pllq = Fs * (plln / (pllm * pllq));
*
* 外部晶振为 8M的时候, 推荐值: plln = 336, pllm = 8, pllp = 2, pllq = 7.
* 得到:Fvco = 8 * (336 / 8) = 336Mhz
* Fsys = pll_p_ck = 336 / 2 = 168Mhz
* Fq = pll_q_ck = 336 / 7 = 48Mhz
*
* F407默认需要配置的频率如下:
* CPU频率(HCLK) = pll_p_ck = 168Mhz
* AHB1/2/3(rcc_hclk1/2/3) = 168Mhz
* APB1(rcc_pclk1) = pll_p_ck / 4 = 42Mhz
* APB1(rcc_pclk2) = pll_p_ck / 2 = 84Mhz
*
* @retval 错误代码: 0, 成功; 1, 错误;
*/
uint8_t Clock_HSI_Init(uint16_t PLLM,uint16_t PLLN,uint16_t PLLP,uint16_t PLLQ)
{
RCC_OscInitTypeDef RCC_OscInit={0};
RCC_ClkInitTypeDef RCC_ClkInit={0};
__HAL_RCC_PWR_CLK_ENABLE(); /* 使能PWR时钟 */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* 设置调压器输出电压级别,以便在器件未以最大频率工作 */
/* 使能HSE,并选择HSE作为PLL时钟源,配置PLL1,开启USB时钟 */
RCC_OscInit.OscillatorType=RCC_OSCILLATORTYPE_HSI; /*选择振荡器*/
RCC_OscInit.HSIState=RCC_HSI_ON; /*打开HSL*/
/*然而,由于制造工艺的差异和温度等因素的影响,HSI的实际频率可能会有所偏差。
为了补偿这种偏差,STM32提供了HSI校准功能,允许用户通过软件设置校准值来调整HSI的频率。*/
RCC_OscInit.HSICalibrationValue=RCC_HSICALIBRATION_DEFAULT; /*使用默认的HSE校准值。*/
RCC_OscInit.PLL.PLLState=RCC_PLL_ON; /*打开PLL锁相环*/
RCC_OscInit.PLL.PLLSource=RCC_PLLSOURCE_HSI; /*选择HSL为锁相环的时钟来源*/
RCC_OscInit.PLL.PLLM=PLLM;
RCC_OscInit.PLL.PLLN=PLLN;
RCC_OscInit.PLL.PLLP=PLLP;
RCC_OscInit.PLL.PLLQ=PLLQ;
uint8_t ret=HAL_RCC_OscConfig(&RCC_OscInit);
if(ret != HAL_OK)
{
return 1;
}
RCC_ClkInit.ClockType=RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; /*配置的时钟*/
RCC_ClkInit.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; /*系统时钟源PLL*/
RCC_ClkInit.AHBCLKDivider=RCC_SYSCLK_DIV1;
RCC_ClkInit.APB1CLKDivider=RCC_HCLK_DIV4;
RCC_ClkInit.APB2CLKDivider=RCC_HCLK_DIV2;
ret=HAL_RCC_ClockConfig(&RCC_ClkInit,FLASH_LATENCY_5);
if(ret!=HAL_OK)
{
return 1;
}
/* STM32F405x/407x/415x/417x Z版本的器件支持预取功能 */
if (HAL_GetREVID() == 0x1001)
{
__HAL_FLASH_PREFETCH_BUFFER_ENABLE(); /* 使能flash预取 */
}
return 0;
}
#include "sys.h"
#include "usart.h"
#include "delay.h"
uint32_t HCLK;
uint32_t APB1;
uint32_t APB2;
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
//sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
Clock_HSI_Init(16,336,RCC_PLLP_DIV2,7);
delay_init(168); /* 延时初始化 */
while(1)
{
HCLK=HAL_RCC_GetHCLKFreq();
APB1=HAL_RCC_GetPCLK1Freq();
APB2=HAL_RCC_GetPCLK2Freq();
}
}
仿真:
HCLK=168MHZ; APB1=42MHZ ; APB2=84MHZ。 仿真的结果和我们设置的相同。
和下面的HSE外部高速时钟很像,详情看下面的HSE。
五:HSE
A:F1
外部高速时钟:stm32F1C8T6的外部晶振为8MHZ
*HSE外部高速时钟做为系统时钟*/
void sys_stm32_clock_init(uint32_t plln)
{
HAL_StatusTypeDef ret = HAL_ERROR;
RCC_OscInitTypeDef RCC_OscInit = {0};
RCC_ClkInitTypeDef RCC_ClkInit={0};
//HSE外部时钟做为PLL时钟源
RCC_OscInit.OscillatorType=RCC_OSCILLATORTYPE_HSE;/*选择振荡器类型*/
RCC_OscInit.HSEState=RCC_HSE_ON; /*选择HSL状态*/
RCC_OscInit.HSEPredivValue=RCC_HSE_PREDIV_DIV1; /*HSE的分频系数*/
RCC_OscInit.PLL.PLLState=RCC_PLL_ON;
RCC_OscInit.PLL.PLLSource=RCC_PLLSOURCE_HSE;
RCC_OscInit.PLL.PLLMUL=plln; //RCC_PLL_MUL9
ret=HAL_RCC_OscConfig(&RCC_OscInit);
if (ret !=HAL_OK)
{
while (1);
}
//PLL做为系统时钟
RCC_ClkInit.ClockType=RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInit.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInit.AHBCLKDivider=RCC_HCLK_DIV1;
RCC_ClkInit.APB1CLKDivider=RCC_HCLK_DIV2;
RCC_ClkInit.APB2CLKDivider=RCC_HCLK_DIV1;
ret=HAL_RCC_ClockConfig(&RCC_ClkInit,FLASH_LATENCY_2);
if (ret !=HAL_OK)
{
while (1);
}
}
#include "stm32f1xx_hal.h"
#include "rcc.h"
uint32_t GetPCLK1Freq;
uint32_t GetPCLK2Freq;
uint32_t GetHCLKFreq;
#define HSE_VALUE 8000000U
int main(void)
{
//这个函数用于初始化HAL库;它必须是主程序中执行的第一条指令
HAL_Init();
//RCC_Clock_HSLInit(); RCC_PLL_MUL9
sys_stm32_clock_init(RCC_PLL_MUL9);
//PA8引脚输出系统时钟
HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);
SystemCoreClockUpdate();
GetHCLKFreq=HAL_RCC_GetHCLKFreq();
GetPCLK1Freq=HAL_RCC_GetPCLK1Freq();
GetPCLK2Freq=HAL_RCC_GetPCLK2Freq();
}
HAL_StatusTypeDef
是一个在STM32 HAL (硬件抽象层) 库中定义的类型,用于表示函数调用的状态。这个类型通常用于返回函数执行的结果,以指示操作是否成功或出现了错误。
HAL_StatusTypeDef
通常定义为一个枚举,其中包含几个可能的值,如HAL_OK
、HAL_ERROR
、HAL_TIMEOUT
等。这些值用于表示函数调用的不同结果。例如,如果函数成功执行,它可能会返回HAL_OK
;如果发生错误,它可能会返回HAL_ERROR
。在STM32 HAL库中,许多函数都使用
HAL_StatusTypeDef
作为其返回类型。这使得调用者可以轻松地检查函数调用是否成功,并根据需要采取适当的操作。关于您提到的具体函数(如
HAL_CAN_ActivateNotification
、HAL_CAN_Start
、HAL_CAN_ConfigFilter
和HAL_UART_Receive_IT
),它们都是STM32 HAL库中的函数,用于配置和管理CAN和UART(通用异步收发传输器)外设。这些函数使用HAL_StatusTypeDef
作为返回类型,以指示操作是否成功。如果您在移植标准库的GPIO功能到HAL库工程时遇到
HAL_StatusTypeDef
未定义的问题,这通常意味着您可能没有正确包含必要的头文件或库文件。确保您已经包含了定义HAL_StatusTypeDef
的头文件(通常是stm32fxxx_hal.h
),并且您的项目配置正确,以便包含和链接STM32 HAL库。此外,请注意,当您在HAL库环境中工作时,您需要遵循HAL库的规范和约定。例如,使用HAL库提供的函数和数据结构来初始化和配置外设,而不是尝试直接使用标准库中的函数或数据结构。这有助于确保您的代码与HAL库兼容,并能够充分利用HAL库提供的功能和优势。
仿真:
PCLK1(APB1)=36MHZ
PCLK2(APB2)=72MHZ
HCLK(AHB)=72HMZ
使用仿真查看主频注意:
在获取我们的主频值的时候我们想要调用:SystemCoreClockUpdate()。刷新一下.因为我们已经改变了主频,需要刷新一下,在获取
HAL_RCC_ClockConfig(&RCC_ClkInit,FLASH_LATENCY_2);为等待周期,我们设置了72的MHZ,所以需要2个等待周期。
手册32页
/** @defgroup FLASH_Latency FLASH Latency
* @{
*/
#define FLASH_LATENCY_0 0x00000000U /*!< FLASH Zero Latency cycle */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_0 /*!< FLASH One Latency cycle */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_1 /*!< FLASH Two Latency cycles */
B:F407
外部高速晶振比内部的更加稳定,有外部就使用外部的。没有的话使用内部的。
/**
* @brief 时钟设置函数
* @param plln: 主PLL倍频系数(PLL倍频), 取值范围: 64~432.
* @param pllm: 主PLL和音频PLL预分频系数(进PLL之前的分频), 取值范围: 2~63.
* @param pllp: 主PLL的p分频系数(PLL之后的分频), 分频后作为系统时钟, 取值范围: 2, 4, 6, 8.(仅限这4个值)
* @param pllq: 主PLL的q分频系数(PLL之后的分频), 取值范围: 2~15.
* @note
*
* Fvco: VCO频率
* Fsys: 系统时钟频率, 也是主PLL的p分频输出时钟频率
* Fq: 主PLL的q分频输出时钟频率
* Fs: 主PLL输入时钟频率, 可以是HSI, HSE等.
* Fvco = Fs * (plln / pllm);
* Fsys = Fvco / pllp = Fs * (plln / (pllm * pllp));
* Fq = Fvco / pllq = Fs * (plln / (pllm * pllq));
*
* 外部晶振为 8M的时候, 推荐值: plln = 336, pllm = 8, pllp = 2, pllq = 7.
* 得到:Fvco = 8 * (336 / 8) = 336Mhz
* Fsys = pll_p_ck = 336 / 2 = 168Mhz
* Fq = pll_q_ck = 336 / 7 = 48Mhz
*
* F407默认需要配置的频率如下:
* CPU频率(HCLK) = pll_p_ck = 168Mhz
* AHB1/2/3(rcc_hclk1/2/3) = 168Mhz
* APB1(rcc_pclk1) = pll_p_ck / 4 = 42Mhz
* APB1(rcc_pclk2) = pll_p_ck / 2 = 84Mhz
*
* @retval 错误代码: 0, 成功; 1, 错误;
*/
uint8_t Clock_HSE_Init(uint16_t PLLM,uint16_t PLLN,uint16_t PLLP,uint16_t PLLQ)
{
RCC_OscInitTypeDef RCC_OscInit={0};
RCC_ClkInitTypeDef RCC_ClkInit={0};
__HAL_RCC_PWR_CLK_ENABLE(); /* 使能PWR时钟 */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* 设置调压器输出电压级别,以便在器件未以最大频率工作 */
/* 使能HSE,并选择HSE作为PLL时钟源,配置PLL1,开启USB时钟 */
RCC_OscInit.OscillatorType=RCC_OSCILLATORTYPE_HSE; /*选择振荡器*/
RCC_OscInit.HSEState=RCC_HSE_ON; /*打开HSE*/
RCC_OscInit.PLL.PLLState=RCC_PLL_ON; /*打开PLL锁相环*/
RCC_OscInit.PLL.PLLSource=RCC_PLLSOURCE_HSE; /*选择HSE为锁相环的时钟来源*/
RCC_OscInit.PLL.PLLM=PLLM;
RCC_OscInit.PLL.PLLN=PLLN;
RCC_OscInit.PLL.PLLP=PLLP;
RCC_OscInit.PLL.PLLQ=PLLQ;
uint8_t ret=HAL_RCC_OscConfig(&RCC_OscInit);
if(ret != HAL_OK)
{
return 1;
}
RCC_ClkInit.ClockType=RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; /*配置的时钟*/
RCC_ClkInit.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK; /*系统时钟源=*/
RCC_ClkInit.AHBCLKDivider=RCC_SYSCLK_DIV1;
RCC_ClkInit.APB1CLKDivider=RCC_HCLK_DIV4;
RCC_ClkInit.APB2CLKDivider=RCC_HCLK_DIV2;
ret=HAL_RCC_ClockConfig(&RCC_ClkInit,FLASH_LATENCY_5);
if(ret!=HAL_OK)
{
return 1;
}
/* STM32F405x/407x/415x/417x Z版本的器件支持预取功能 */
if (HAL_GetREVID() == 0x1001)
{
__HAL_FLASH_PREFETCH_BUFFER_ENABLE(); /* 使能flash预取 */
}
return 0;
}
#include "sys.h"
#include "usart.h"
#include "delay.h"
uint32_t HCLK;
uint32_t APB1;
uint32_t APB2;
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
//sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
Clock_HSE_Init(8,336,RCC_PLLP_DIV2,7);
delay_init(168); /* 延时初始化 */
while(1)
{
HCLK=HAL_RCC_GetHCLKFreq();
APB1=HAL_RCC_GetPCLK1Freq();
APB2=HAL_RCC_GetPCLK2Freq();
}
}
仿真:
HCLK=168MHZ; APB1=42MHZ ; APB2=84MHZ。 仿真的结果和我们设置的相同。
设置调压器输出电压级别
__HAL_RCC_PWR_CLK_ENABLE(); /* 使能PWR时钟 */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* 设置调压器输出电压级别,以便在器件未以最大频率工作 */
也可以不用写这个:
FLASH的等待周期:
ret=HAL_RCC_ClockConfig(&RCC_ClkInit,FLASH_LATENCY_5);
#define FLASH_LATENCY_0 FLASH_ACR_LATENCY_0WS /*!< FLASH Zero Latency cycle */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_1WS /*!< FLASH One Latency cycle */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_2WS /*!< FLASH Two Latency cycles */
#define FLASH_LATENCY_3 FLASH_ACR_LATENCY_3WS /*!< FLASH Three Latency cycles */
#define FLASH_LATENCY_4 FLASH_ACR_LATENCY_4WS /*!< FLASH Four Latency cycles */
#define FLASH_LATENCY_5 FLASH_ACR_LATENCY_5WS /*!< FLASH Five Latency cycles */
#define FLASH_LATENCY_6 FLASH_ACR_LATENCY_6WS /*!< FLASH Six Latency cycles */
#define FLASH_LATENCY_7 FLASH_ACR_LATENCY_7WS /*!< FLASH Seven Latency cycles */
六:HAL设置
仿真设置
在图 中,选择:Use Simulator,即使用软件仿真。选择:Run to main(),即跳过汇编代码,直接跳转到 main 函数开始仿真。设置下方的:Dialog DLL分别为:DARMSTM.DLL和 TARMSTM.DLL,Parameter 均为:-pSTM32F103C8,用于设置支持 STM32F103C8 的软硬件仿真(即可以通过 Peripherals 选择对应外设的对话框观察仿真结果)。最后点击 OK,完成设
配置好的图:
开始我尝试使用了软件仿真,但是一直不能显示出来,(如果有大佬的话,可以指点一下),我们最后选择了硬件仿真。
注意:硬件仿真,需要我们连接上我们的板子,并把程序下载进去。
本文参考:STM32F10xxx参考手册书写详细文章,请转至参考手册
链接:https://pan.baidu.com/s/1HrL5dzuFoZGTopzMTuQMxQ?pwd=5j2p
提取码:5j2p
--来自百度网盘超级会员V2的分享