超子物联网 HAL库学习 汇总入口:

超子物联网HAL库笔记:[汇总]

写作不易,如果您觉得写的不错,欢迎给博主来一波点赞、收藏~让博主更有动力吧!

1. 汇编启动文件调用SystemInit对时钟的配置内容

汇编的启动文件(.s结尾的那个)在每次复位时,都是先调用SystemInit函数去配置时钟。 默认的最终时钟是 使用的是内部的HSI 内部高速时钟 8MHZ

  • SystemInit首先会设置CR寄存器(时钟控制寄存器)把位0置1(使用内部高速时钟)。
  • 然后会去设置CFGR寄存器,主要是设置路径,以及倍频之类的东西

2. HAL库输出内部时钟HSI

我们可以调用HAL_RCC_MCOConfig 来把时钟输出8MHZ的方波到默认的PA8上验证一下。

在使用HAL库前要用HAL_Init()初始化一下。

main.c

    HAL_Init();//初始化HAL库
    HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);//PA8引脚输出、系统时钟、不分频

所以仅仅需要这两行就可以输出时钟了。示波器验证正确。

3. 使用内部HSI时钟通过PLL倍频到64MHZ

注意

  • APB1最大时钟为36MHZ
  • APB2最大时钟为72MHZ

需要设置的。和路线,其实就是在函数中一步步设置。

代码如下

main.c

#include "stm32f1xx_hal.h"

#include "rcc.h"
/*函 数 名:hal库rcc输出内部8Mhz方波
 *参    数:
 *返 回 值:
 *注意事项:
 */
 
uint32_t HCLKFreq  = 0;//显示时钟树三处频率
uint32_t PCLK1Freq = 0;
uint32_t PCLK2Freq = 0;
 
int main (void)
{
    HAL_Init();//初始化HAL库
    RCC_ClockInit();//配置时钟树初始化
    
    HAL_RCC_MCOConfig(RCC_MCO1,RCC_MCO1SOURCE_SYSCLK,RCC_MCODIV_1);//PA8引脚输出、系统时钟、不分频

    HCLKFreq  = HAL_RCC_GetHCLKFreq();
    PCLK1Freq = HAL_RCC_GetPCLK1Freq();
    PCLK2Freq = HAL_RCC_GetPCLK2Freq();
    
    while(1)
    {
    
    
    }

}

rcc.c

#include "stm32f1xx_hal.h"
#include "rcc.h"

void RCC_ClockInit()
{
    RCC_OscInitTypeDef RCC_OsInitStructure; //设置内外部时钟源配置结构体
    RCC_ClkInitTypeDef RCC_ClkInitStructure;//设置总线时钟结构体
    
    RCC_OsInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI;    //选择震荡电路为内部高速
    RCC_OsInitStructure.HSIState = RCC_HSI_ON;  //打开时钟
    RCC_OsInitStructure.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;   //设置微调值 默认
    RCC_OsInitStructure.PLL.PLLState = RCC_PLL_ON;  //设置PLL为打开
    RCC_OsInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; //选择PLL输入为内部高速时钟
    RCC_OsInitStructure.PLL.PLLMUL = RCC_PLL_MUL16;          //设置16倍频
    HAL_RCC_OscConfig(&RCC_OsInitStructure);    //传给话务员..
    
    RCC_ClkInitStructure.ClockType = RCC_CLOCKTYPE_HCLK  | RCC_CLOCKTYPE_PCLK1 |RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_SYSCLK;//需要配置的时钟
    RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //SYSCLK系统时钟输入源 PLL作为系统时钟
    RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1;   //AHB预分频 1分频
    RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV2;    //APB1预分频 2分频
    RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV1;    //APB2预分频 1分频
    HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2);//传给话务员,并且根据频率设置FLASH等待周期为2
    
    //话务员相关配置可以在API函数中找到。结构体相关配置在结构体和成员中可找到
}

结果如下(转换成10进制):分别为 64M 32M 64M

4. 使用外部HSE时钟通过PLL倍频到72MHZ

流程如下

只修改了rcc.c的文件

rcc.c

#include "stm32f1xx_hal.h"
#include "rcc.h"

void RCC_ClockInit()
{
    RCC_OscInitTypeDef RCC_OsInitStructure; //设置内外部时钟源配置结构体
    RCC_ClkInitTypeDef RCC_ClkInitStructure;//设置总线时钟结构体
    
    RCC_OsInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;    //选择震荡电路为外部高速
    RCC_OsInitStructure.HSEState = RCC_HSE_ON;  //打开HSE时钟
    RCC_OsInitStructure.HSEPredivValue = RCC_HSE_PREDIV_DIV1;   //不分频
    RCC_OsInitStructure.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;   //设置微调值 默认
    RCC_OsInitStructure.PLL.PLLState = RCC_PLL_ON;  //设置PLL为打开
    RCC_OsInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE; //选择PLL输入为外部高速时钟
    RCC_OsInitStructure.PLL.PLLMUL = RCC_PLL_MUL9;          //设置9倍频
    HAL_RCC_OscConfig(&RCC_OsInitStructure);    //传给话务员..
    
    RCC_ClkInitStructure.ClockType = RCC_CLOCKTYPE_HCLK  | RCC_CLOCKTYPE_PCLK1 |RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_SYSCLK;//需要配置的时钟
    RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; //SYSCLK系统时钟输入源 PLL作为系统时钟
    RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1;   //AHB预分频 1分频
    RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV2;    //APB1预分频 2分频
    RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV1;    //APB2预分频 1分频
    HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2);//传给话务员,并且根据频率设置FLASH等待周期为2
    
    //话务员相关配置可以在API函数中找到。结构体相关配置在结构体和成员中可找到
}

结果:

5. HAL_Init库函数源码分析及Systick时基

HAL_Init 是 HAL库要求我们调用的第一个函数。

下面是HAL_Init调用时 做的工作:

  1. 把指令预取功能打开
  2. 设置中断分组
  3. 将Systick作为时间基准,配置为1ms的中断
  4. 初始化底层硬件
  5. 返回 HAL_OK

标准库和HAL库的很大的一个区别:Systick

  • 每次进入Systick中断时 对32位全局变量uwTick累加1
  • 提供了HAL_GetTick 获取uwTick全局变量

Systick时基最常用的地方就是各个外设采用阻塞轮训处理数据时,做超时判断、阻塞延时、

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐