01:HAL库---时钟

一:前言

我们使用的是STM32F103CT86的型号

1:介绍

        时钟在在我们的单片机中非常重要,相当于我们的人类的心脏;简单来说,时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波;

三种不同的时钟源可被用来驱动系统时钟 (SYSCLK)
        ● HSI 振荡器时钟
        ● HSE 振荡器时钟
        ● PLL 时钟
这些设备有以下 2 种二级时钟源:
        ● 40kHz 低速内部 RC ,可以用于驱动独立看门狗和通过程序选择驱动 RTC RTC 用于从停机 /
待机模式下自动唤醒系统。
        ● 32.768kHz 低速外部晶体也可用来通过程序选择驱动 RTC(RTCCLK)
当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)

2:默认时钟

启动文件 SystemInit函数 时钟默认配置使用内部8M HSI
#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函数)

二:SystemInit

        HSI时钟信号由内部8MHz RC 振荡器产生,可直接作为系统时钟或在 2 分频后作为 PLL 输入。
      HSI RC振荡器能够在不需要任何外部器件的条件下提供系统时钟。它的启动时间比 HSE 晶体振
荡器短。然而,即使在校准之后它的时钟频率精度仍较差。

        我们研究源码看看在复位向量第一个调用的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)
时钟控制寄存器 (RCC_CR) 或上0x00000001U,其他位不变把最低位置1;就是开启 内部 8MHz 振荡器

B:时钟配置寄存器(RCC_CFGR)

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)RCC->CFGR &= 0xF8FF0000U;
#elseRCC->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)

时钟的选择由时钟配置寄存器 (RCC_CFGR) 中的 MCO[2:0] 位控制。就是位1:0,把单刀三制拨到

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;
#elseRCC->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_ExtSRAMSystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */
#endif #ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

三:HSL

目的:得到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_STATUS_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);}

        频率越高,系统会越来越稳定;所以一般情况下我们选择使用内部的HSE,通过PLL可以转变为72HZ; 除非在外部晶振坏了或者考虑成本的情况下才会不会使用内部的晶振。

四:HSE

外部高速时钟

*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_MUL9ret=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);}		}

   HAL_StatusTypeDef 是一个在STM32 HAL (硬件抽象层) 库中定义的类型,用于表示函数调用的状态。这个类型通常用于返回函数执行的结果,以指示操作是否成功或出现了错误。

   HAL_StatusTypeDef 通常定义为一个枚举,其中包含几个可能的值,如 HAL_OKHAL_ERRORHAL_TIMEOUT 等。这些值用于表示函数调用的不同结果。例如,如果函数成功执行,它可能会返回 HAL_OK;如果发生错误,它可能会返回 HAL_ERROR

        在STM32 HAL库中,许多函数都使用 HAL_StatusTypeDef 作为其返回类型。这使得调用者可以轻松地检查函数调用是否成功,并根据需要采取适当的操作。

        关于您提到的具体函数(如 HAL_CAN_ActivateNotificationHAL_CAN_StartHAL_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库提供的功能和优势。

本文参考:STM32F10xxx参考手册书写详细文章,请转至参考手册

链接:https://pan.baidu.com/s/1HrL5dzuFoZGTopzMTuQMxQ?pwd=5j2p 
提取码:5j2p 
--来自百度网盘超级会员V2的分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/513550.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UE5 UE4 开发常用工具AssetDeveTool

AssetDeveTool工具,支持UE5 5.0-.5.3 UE4 4.26/4.27 下载链接: 面包多 https://mbd.pub/o/bread/ZZubkphu 工坊: https://gf.bilibili.com/item/detail/1104960041 包含功能: 自动化批量展UV功能 快速选择功能 自动化批量减面功能…

Docker容器化解决方案

什么是Docker? Docker是一个构建在LXC之上,基于进程容器的轻量级VM解决方案,实现了一种应用程序级别的资源隔离及配额。Docker起源于PaaS提供商dotCloud 基于go语言开发,遵从Apache2.0开源协议。 Docker 自开源后受到广泛的关注和…

07 系统的线性时不变特性

各位看官,大家好!本讲为《数字信号处理理论篇》07 系统的线性时不变特性。(特别提示:课程内容为由浅入深的特性,而且前后对照,不要跳跃观看,请按照文章或视频顺序进行观看。 从本讲开始开始为大…

python | Python 中检查一个数字是否是三态数

本文来源公众号“python”,仅用于学术分享,侵权删,干货满满。 原文链接:Python 中检查一个数字是否是三态数 在数学中,三态数(Triangular Number)是一种特殊的数列,它是由自然数按…

O2O:Online Decision Transformer(ODT)

ICML 2022 paper Introduction 利用Transformer对强化学习进行序列建模在离线强化学习中展露头角,但是无法避免的是这种方法受限于离线数据的质量,因此本文将其结合到online的在线微调过程,进而形成本文ODT。为了解决从offline到online过程…

Pandas基础介绍

文章目录 Pandas简介什么是Pandas?Pandas数据结构Pandas 应用 Pandas简介 什么是Pandas? Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处…

android开发者工具,最新整理

一 Java相关 1.重载函数的签名(区别是否是重载函数) 答:方法名参数类型参数顺序(返回值不是) 2.finalize的工作原理 答:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中&#…

Hololens 2应用开发系列(3)——MRTK基础知识及配置文件配置(中)

Hololens 2应用开发系列(3)——MRTK基础知识及配置文件配置(中) 一、前言二、输入系统2.1 MRTK输入系统介绍2.2 输入数据提供者(Input Data Providers)2.3 输入动作(Input Actions)2…

做分析用什么工具

做分析用什么工具 导读 数据分析是数据辅助决策的最后一公里,是最终的数据可视化展示与探索分析的部分,选择使用最适合的数据展示方式,可以帮助分析人员大大提升分析效率。 问题: ● 纠结选择哪个工具 ● 纠结从哪里学起&#x…

Vue.js的双向绑定原理

Vue的双向绑定 vue双向绑定是其最重要的核心亮点,其原理也很简单,这里做个简单总结 vue2的双向绑定是利用的Object.definePropertyvue3的双向绑定是利用的 ES6Porxy中的defineProperty(target, propKey, propDesc 其作用类似于Object.defineProperty …

tomcat下载安装配置教程

tomcat下载安装配置教程 我是使用tomcat下载安装及配置教程_tomcat安装-CSDN博客 此贴来进行安装配置,原文21年已经有些许不同。 下载tomcat 官网:http://tomcat.apache.org/ 我们老师让安装8.5以上,所以我直接选择版本9 点击9页面之后…

GEE入门篇|图像分类(一):监督分类

在遥感中,图像分类是尝试将图像中的所有像素分类为有限数量的标记土地覆盖和/或土地利用类别。 生成的分类图像是从原始图像导出的简化专题图(图 1), 土地覆盖和土地利用信息对于许多环境和社会经济应用至关重要,包括自…