STM32时钟系统

news2025/2/28 4:21:23

时钟

时钟是具有周期性的脉冲信号,最常用的是占空比50%的方波。
时钟是单片机的脉搏。

时钟树

  • HSE:高速外部振荡器,4~16MHz,(晶体,陶瓷)
  • LSE:低速外部振荡器,32.768KHz,(晶体,陶瓷)
  • HSI:高速内部振荡器,8MHz,(RC)
  • LSI:低速内部振荡器,40KHz,(RC)
    在这里插入图片描述
    外部高速振荡器
    在这里插入图片描述
    外部低速振荡器
  • 外部振荡器需要外部接晶振(成本高),内部振荡器不需要。
  • 外部振荡器准确性要高一些,所以有外部的时候一般选择外部。

STM32时钟树简图
在这里插入图片描述
MCO:对外部输出时钟的通道
在这里插入图片描述

配置系统时钟步骤

在这里插入图片描述

外设时钟使能和失能

我们要使用某个外设,必须先使能该外设时钟!!!
比如:__HAL_RCC_GPIOA_CLK_ENABLE();

禁止:__HAL_RCC_GPIOA_CLK_DISABLE();

HAL库RCC

HAL库中的RCC(Reset and Clock Control)模块是用来控制各种时钟源和时钟分频器的模块,它提供了控制系统时钟频率和各种外设时钟的功能。

在HAL库中,RCC模块可以通过以下几个函数进行控制:

  1. void HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct): 这个函数用来配置系统时钟源和时钟分频器。通过指定不同的参数,我们可以选择使用内部晶振、外部晶振或其他时钟源,并设置相应的时钟分频。

  2. void HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency): 这个函数用来配置各个外设的时钟源和分频。我们可以通过指定不同的参数,为不同的外设配置相应的时钟源和分频。

  3. void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv): 这个函数用来配置MCU的主时钟输出(MCO)。我们可以通过指定不同的参数,选择输出不同的时钟源(例如系统时钟源、外部时钟源等)和相应的分频。

在使用RCC模块进行时钟控制时,需要特别注意一些细节,比如时钟分频的设置、时钟源与时钟分频的兼容性等等。因此,我们需要仔细研究数据手册和HAL库的API文档,才能正确地使用RCC模块进行时钟控制。

HAL_RCC_OscConfig()函数

HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
typedef struct
{
  uint32_t OscillatorType;       /*!< The oscillators to be configured.
                                       This parameter can be a value of @ref RCC_Oscillator_Type */

#if defined(STM32F105xC) || defined(STM32F107xC)
  uint32_t Prediv1Source;       /*!<  The Prediv1 source value.
                                       This parameter can be a value of @ref RCCEx_Prediv1_Source */
#endif /* STM32F105xC || STM32F107xC */

  uint32_t HSEState;              /*!< The new state of the HSE.
                                       This parameter can be a value of @ref RCC_HSE_Config */

  uint32_t HSEPredivValue;       /*!<  The Prediv1 factor value (named PREDIV1 or PLLXTPRE in RM)
                                       This parameter can be a value of @ref RCCEx_Prediv1_Factor */

  uint32_t LSEState;              /*!<  The new state of the LSE.
                                        This parameter can be a value of @ref RCC_LSE_Config */

  uint32_t HSIState;              /*!< The new state of the HSI.
                                       This parameter can be a value of @ref RCC_HSI_Config */

  uint32_t HSICalibrationValue;   /*!< The HSI calibration trimming value (default is RCC_HSICALIBRATION_DEFAULT).
                                       This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x1F */

  uint32_t LSIState;              /*!<  The new state of the LSI.
                                        This parameter can be a value of @ref RCC_LSI_Config */

  RCC_PLLInitTypeDef PLL;         /*!< PLL structure parameters */

#if defined(STM32F105xC) || defined(STM32F107xC)
  RCC_PLL2InitTypeDef PLL2;         /*!< PLL2 structure parameters */
#endif /* STM32F105xC || STM32F107xC */
} RCC_OscInitTypeDef;
  • OscillatorType:需要配置的振荡器
  • HSIState:高速内部振荡器的状态
  • HSICalibrationValue:HSI校准值
  • PLL:PLL结构体
/**
  * @brief  RCC PLL configuration structure definition
  */
typedef struct
{
  uint32_t PLLState;      /*!< PLLState: The new state of the PLL.
                              This parameter can be a value of @ref RCC_PLL_Config */

  uint32_t PLLSource;     /*!< PLLSource: PLL entry clock source.
                              This parameter must be a value of @ref RCC_PLL_Clock_Source */

  uint32_t PLLMUL;        /*!< PLLMUL: Multiplication factor for PLL VCO input clock
                              This parameter must be a value of @ref RCCEx_PLL_Multiplication_Factor */
} RCC_PLLInitTypeDef;
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) of the device. */

#if defined(FLASH_ACR_LATENCY)
  /* 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;
  }
}

#endif /* FLASH_ACR_LATENCY */
/*-------------------------- 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));
    }

    /* Set the new HCLK clock divider */
    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)
    {
      /* 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;
      }
    }
  }

#if defined(FLASH_ACR_LATENCY)
  /* 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;
  }
}
#endif /* FLASH_ACR_LATENCY */

/*-------------------------- 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) << 3));
  }

  /* 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;
}

typedef struct
{
  uint32_t ClockType;             /*!< The clock to be configured.
                                       This parameter can be a value of @ref RCC_System_Clock_Type */

  uint32_t SYSCLKSource;          /*!< The clock source (SYSCLKS) used as system clock.
                                       This parameter can be a value of @ref RCC_System_Clock_Source */

  uint32_t AHBCLKDivider;         /*!< The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK).
                                       This parameter can be a value of @ref RCC_AHB_Clock_Source */

  uint32_t APB1CLKDivider;        /*!< The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK).
                                       This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */

  uint32_t APB2CLKDivider;        /*!< The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK).
                                       This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */
} RCC_ClkInitTypeDef;
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
#define FLASH_LATENCY_0            0x00000000U               /*!< FLASH Zero Latency cycle FLASH 0个等待周期 */
#define FLASH_LATENCY_1            FLASH_ACR_LATENCY_0       /*!< FLASH One Latency cycle */
#define FLASH_LATENCY_2            FLASH_ACR_LATENCY_1       /*!< FLASH Two Latency cycles */

LATENCY:时延
SYSCLK周期与闪存访问时间的比例

  • 000:零等待状态,当0<SYSCLK≤24MHz
  • 001:一个等待状态,当24MHz<SYSCLK≤48MHz
  • 010:两个等待状态,当48MHz<SYSCLK≤72MHz

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ADC0808/ADC0809引脚图及功能和工作原理介绍

ADC0808芯片有28条引脚&#xff0c;采用双列直插式封装。如图所示&#xff1a; . . . 各引脚功能如下&#xff1a; 1-5和26-28&#xff08;IN0-IN7&#xff09;&#xff1a;8路模拟量输入端。 8、14、15和17-21&#xff1a;8位数字量输出端。 22&#xff08;ALE&#xff09…

深度学习代码环境配置(编译器, git, anaconda)

内容 编译器 gcc&#xff1a;GNU编译器套装C builderMicrosoft Visual C&#xff08;MSVC&#xff09;&#xff1a;微软的VC编译器MinGW&#xff08;Minimalist GNU on Windows&#xff09;&#xff1a;可自由使用和自由发布的Windows特定头文件和使用GNU工具集导入库的集合&…

【设计模式】面向对象的设计原则

(一) UML 和面向对象设计原则 1. 一种某唱片播放器不仅可以播放唱片&#xff0c;而且可以连接计算机并把计算机中的歌曲刻录到 唱片上&#xff08;同步歌曲&#xff09;。连接计算机的过程中还可自动完成充电。 关于唱片&#xff0c;还有如下描述信息&#xff1a; &#xf…

ChatGPT底层架构Transformer技术及源码实现(一)

ChatGPT底层架构Transformer技术及源码实现 Language Model底层的数学原理之最大似然估计MLE及最大后验概率MAP内部机制详解 Gavin大咖微信:NLP_Matrix_Space 传统人工智能算法的真相(The Truth Under Traditional AI Algorithms),传统人工智能算法是相对于贝叶斯(Bayesia…

【软件设计师暴击考点】程序设计语言-高频考点暴击系列

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件…

碳中和城市建筑能源系统(4):储能篇(龙惟定)2022

碳中和城市建筑能源系统(4):储能篇 摘要 本文是碳中和城市建筑能源系统系列文章的第四篇。在碳中和语境下&#xff0c;无论是增加可再生能源应用的渗透率&#xff0c;还是平抑负荷、提高电网的灵活性&#xff0c;都离不开储能。本文介绍了当今储能技术的主要类型&#xff0c;…

【新星计划·2023】Centos 7安装教程(一步一图)

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、下载VMware 二、下载镜像的方式 三、安装Linux ’前言 本文将讲解下载VMware和下载镜像的方式&#xff0c;以及安装centos 7的教…

webpack编译打包从入门到放弃

写在前面的话&#xff1a;推荐学习vite。当然&#xff0c;我更推荐你直接上手体验webpack_demo与vite_demo 看看他们的编译、打包、热更新速度等差距。你也可以直接通过vite开发lib库&#xff0c;一句话就是比webpack快&#xff0c;它有的vite都有&#xff0c;并且更好&#x…

NCI-NFCEE

10.5 NFCEE 状态 NFCC 使用此控制消息向 DH 通知启用的 NFCEE 状态的变化。 NFCC 发送 NFCEE_STATUS_NTF 来报告启用的 NFCEE 状态的变化。 对于任何禁用或无响应的 NFCEE&#xff0c;NFCC 不应发送 NFCEE_STATUS_NTF。 当启用 NFCEE 并且 NFCC 检测到与该 NFCEE 通信时存在不…

C++布隆过滤器

目录 布隆过滤器介绍实现哈希函数布隆过滤器删除 小结使用——题目 布隆过滤器 介绍 在许多场景下&#xff0c;如设置昵称时&#xff0c;往往要求唯一性。这时就需要高效判断该昵称是否被使用过。 使用红黑树的kv模型或者哈希表来组织昵称集合&#xff0c;可以&#xff0c;但缺…

Qt中的日期和时间

目录 QDate 示例&#xff08;打印年月日&#xff09;&#xff1a; QTime 示例&#xff08;显示时分秒&#xff09;&#xff1a; QDateTime 示例&#xff08;显示当前日期和时间&#xff09;&#xff1a; 示例&#xff08;分别取出 年 月 日 时 分 秒&#xff09;&#xff…

牛客网专项练习——C语言错题集(8)

文章目录 字符串拼接和拷贝while 与 fortypedef 和 define浮点类型的组成部分 字符串拼接和拷贝 这题并没有难度&#xff0c;但不知为什么我把该题空着。 strcpy 用于拷贝字符串&#xff0c;strcat 用于拼接字符串。 while 与 for 假如 i 0&#xff0c;while 循环里 s1 被执…

【AI机器学习入门与实战】机器学习算法都有哪些分类?

&#x1f44d;【AI机器学习入门与实战】目录 &#x1f36d;基础篇 &#x1f525; 第一篇&#xff1a;【AI机器学习入门与实战】AI 人工智能介绍 &#x1f525; 第二篇&#xff1a;【AI机器学习入门与实战】机器学习核心概念理解 &#x1f525; 第三篇&#xff1a;【AI机器学习入…

Z变换方程转化为差分方程

将Z变换方程转换为差分方程的过程称为反Z变换。反Z变换是将信号从复频域转换为时间域的过程。如果我们已知一个系统的传递函数&#xff0c;即Z变换方程&#xff1a; H ( z ) Y ( z ) X ( z ) b n b n − 1 z − 1 ⋯ b 0 z − n 1 a n a n − 1 z − 1 ⋯ a 0 z − n 0…

AVL 树

目录 AVL树的概念AVL树节点的定义AVL树的插入AVL树的旋转左单旋(parent->_bf 2 && cur->_bf 1)a,b,c当高度为0a,b,c当高度为1a,b,c当高度为2a,b,c当高度为...... 右单旋(parent->_bf -2 && cur->_bf -1)a,b,c当高度为0a,b,c当高度为1a,b,c当高…

强化学习从基础到进阶-案例与实践[4]:深度Q网络-DQN、double DQN、经验回放、rainbow、分布式DQN

【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧&#xff08;调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍&#xff1a;【强化学习原理项目专栏】必看系列&#xff1a;单智能体、多智能体算法原理项目实战、相关技巧…

Azkaban初认识

Azkaban初认识 文章目录 Azkaban初认识Azkaban是什么&#xff1f;为什么需要工作流调度系统&#xff1f;常见的工作流调度系统Azkaban 与 Oozie的对比 Azkaban是什么&#xff1f; Azkaban是一个开源的分布式工作流管理器&#xff0c;在LinkedIn实施&#xff0c;以解决Hadoop作业…

RT-Thread-03-栈空间分配

栈空间分配 线程状态转换图&#xff1a; 系统滴答时钟 每个操作系统都存在一个系统时钟&#xff0c;是操作系统中最小的时钟单位。这个时钟负责系统和时间相关的一些操作。这个时钟由硬件定时器的定时中断产生。 系统时钟的频率需要根据芯片的处理能力来决定&#xff0c; 频…

【MySQL基础 | 第一篇】数据处理之基本查询

前言 查询语句属于DML&#xff08;Data Manipulation Language&#xff09;数据操作语言的其中一种&#xff0c;用于从数据库中提取所需的数据。通过灵活的条件和组合&#xff0c;查询语句帮助用户有效地获取、过滤和排序数据&#xff0c;满足各种信息需求。 文章目录 前言1️⃣…

团体程序设计天梯赛-练习集L1篇⑨

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…