STM32进阶笔记——复位、时钟与滴答定时器

news2024/11/15 21:37:26

  本专栏争取每周三更新直到更新完成,期待大家的订阅关注,欢迎互相学习交流。

封面图

目录

  • 一、复位
    • 1.1 软件复位
    • 1.2 低功耗管理复位
  • 二、时钟
    • 2.1 系统时钟(SYSCLK)选择
    • 2.2 系统时钟初始化
  • 三、滴答定时器(Systick)
    • 3.1 SysTick部分寄存器
    • 3.2 SysTick相关函数
      • 3.2.1 SysTick时钟源配置函数
      • 3.2.2 SysTick初始化函数

一、复位

  STM32F10系列单片机的复位方式有三种,分别是系统复位、上电复位和备份区复位,这里只介绍系统复位,另外两种如果又想了解的友友可以参考芯片手册,这里就不再介绍了。

  STM32的系统复位将复位所有寄存器至它们的复位状态,以下几种情况会触发系统复位

  • NRST引脚上的低电平(外部复位),这实际也就是我们复位按键利用的复位方式。
  • 窗口看门狗计数终止(WWDG复位)
  • 独立看门狗计数终止(IWDG复位)
  • 软件复位(SW复位)
  • 低功耗管理复位

可通过查看RCC_CSR控制状态寄存器中的复位状态标志位识别复位事件来源。

疑问:复位标志位怎么清除,如果发生了复位,重启后能否看到复位标志位

1.1 软件复位

  通过将Cortex™-M3中断应用和复位控制寄存器中的SYSRESETREQ位置’1’,可实现软件复位。STM32的库文件中提供了软件复位函数

/**
 * @brief  Initiate a system reset request.
 *
 * Initiate a system reset request to reset the MCU
 */
static __INLINE void NVIC_SystemReset(void)
{
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      | 
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | 
                 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
  __DSB();                                                     /* Ensure completion of memory access */              
  while(1);                                                    /* wait until reset */
}

  需要注意的是,从SYSRESETREQ 被置为有效,到复位发生器执行复位命令,往往会有一个延时。在此延时期间,处理器仍然可以响应中断请求。因此我们在软件复位前,需要关闭全部中断,同时在程序最开始的时候开启全部中断。STM32库文件中也提供了一个关闭全部中断和开启全部中断的函数

//关闭所有中断
void INTX_DISABLE(void)
{		  
	__ASM volatile("cpsid i");
}
//开启所有中断
void INTX_ENABLE(void)
{
	__ASM volatile("cpsie i");		  
}

关于其他开启和关闭全局中断的方法大家可以自行搜索一下,这里就不再赘述了。

  下面我们来简单尝试以下系统的软件复位,每次进入系统前都输出一串字符串用来提示进入系统,设置延时一段时间后软件复位系统,查看一下现象

现象

  通过串口的信息我们可以看到,软件复位生效了。这里的main函数比较简单,贴一下,仅供参考

int main(void)
{	
	delay_init();   //延时函数初始化	 
	uart_init(115200);   // 串口初始化
	
	printf ("Enter System!\r\n");
	
	while(1)
	{
		// 延时
		delay_ms(1000);
		
		// 软件复位
		INTX_DISABLE();
		NVIC_SystemReset();
	}
}

1.2 低功耗管理复位

  在以下两种情况下可产生低功耗管理复位

  • 在进入待机模式时产生低功耗管理复位
    通过将用户选择字节中的nRST_STDBY位置’1’将使能该复位。这时,即使执行了进入待机模式的过程,系统将被复位而不是进入待机模式。
  • 在进入停止模式时产生低功耗管理复位
    通过将用户选择字节中的nRST_STOP位置’1’将使能该复位。这时,即使执行了进入停机
    模式的过程,系统将被复位而不是进入停机模式。

二、时钟

  在介绍STM32F10系列的时钟之前,先贴一下时钟树,可以对照时钟数来看下面的内容

时钟树
  STM32有5个时钟源,分别是HSI、HSE、PLL、LSI和LSE。

  • HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。
  • HSE是高速外部时钟,可以接石英石/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz~16MHz
  • PLL实际是一个锁相环,也可以理解为倍频器,它的时钟源可以选择为 H S I 2 \frac{HSI}{2} 2HSI、HSE或者 H S E 2 \frac{HSE}{2} 2HSE,倍频可以选择x2~x16,但是它的输出最大不可超过72MHz
  • LSI是低速内部时钟,RC振荡器,频率为40KHz,提供独立看门狗时钟等。
  • LSE是低速外部时钟,可以接频率为32.768KHz的石英晶体,提供RTC时钟。

  STM32的系统时钟SYSCLK可以来源于三个时钟源,分别是HSI、HSE和PLL时钟。STM32也可以输出时钟信号,可以选择一个时钟信号出书到PA8引脚上,可选PLL输出的二分频、HSI、HSE或者系统时钟作为时钟源。

2.1 系统时钟(SYSCLK)选择

  系统复位后,HSI振荡器被选为系统时钟。我们可以通过设置时钟配置寄存器(RCC_CFGR)来切换系统时钟,在切换系统时钟时,需要等待目标时钟源准备就绪,当被选择的时钟没有就绪时,系统时钟不会发生切换。直至目标时钟源准备就绪,才会发生切换。我们可以通过在时钟控制寄存器(RCC_CR)里的状态位指示哪个时钟已经准备好了,哪个时钟目前被用作系统时钟。

在从停止或待机模式中返回时或直接或间接作为系统时钟的HSE出现故障时,由硬件强制选择HSI作为系统时钟(如果时钟安全系统已经启动),关于时钟安全系统(CSS)这就不再赘述。

2.2 系统时钟初始化

  STM32的库函数中提供了系统时钟初始化函数

/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface, the PLL and update the 
  *         SystemCoreClock variable.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL
  /* Reset PLL2ON and PLL3ON bits */
  RCC->CR &= (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();

#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 
}

关于系统时钟配置函数的内容,大家可以自行对照STM32中文参考手册来查看具体每一行代码的含义,当然也有英文注释可参考,这里就不再赘述了。

  不知道大家是否好奇,我们在编程时并未特地调用过时钟初始化函数SystemInit(),我们是在什么时候配置的系统时钟呢?实际在STM32的启动文件中已经调用过该函数,配置完了系统时钟

配置系统时钟

  关于STM32启动文件的详细注释,大家可以移步至该帖查看,这里也不再贴出来了,STM32启动文件详解。

三、滴答定时器(Systick)

  SysTick定时器被捆绑在NVIC中,它通常用来做延时或者实时系统的心跳,使用SysTick可以节省一个定时器资源。

  SysTick定时器也可以叫做系统滴答定时器,它是一个24位的倒计数计时器,当它计数到0时,将从RELOAD寄存器中自动重装载定时器初值。只要我们不把它在SysTick控制及状态寄存器中的使能位清除,滴答定时器就一直在工作,即使在睡眠模式下也不会停止。SysTick有自己的中断,中断优先级可以设置。

3.1 SysTick部分寄存器

  接下来我们来看一下SysTick的一些寄存器。

  • SysTick控制及状态寄存器(CTRL)
    SysTick控制及状态寄存器
  • SysTick重装载数值寄存器(LOAD)
    SysTick重装载数值寄存器
  • SysTick当前数值寄存器(VAL)
    SysTick当前数值寄存器

3.2 SysTick相关函数

  STM32库函数给出了SysTick的一些配置函数,这里我们简单介绍一下,在看下面的函数时,大家可以对照上面的寄存器来分析一下每一行代码的作用和含义。

3.2.1 SysTick时钟源配置函数

/**
  * @brief  Configures the SysTick clock source.
  * @param  SysTick_CLKSource: specifies the SysTick clock source.
  *   This parameter can be one of the following values:
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
  * @retval None
  */
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}

  下面是一些相关的宏定义

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))

  对照上面对于SysTick控制及状态寄存器的介绍我们可以知道,当SysTick时钟源配置函数的输入值为1时,选择外部时钟作为时钟源,当输入值为0时,选择内部时钟作为时钟源。

3.2.2 SysTick初始化函数

/**
 * @brief  Initialize and start the SysTick counter and its interrupt.
 *
 * @param   ticks   number of ticks between two interrupts
 * @return  1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
  return (0);                                                  /* Function successful */
}

  下面是一些相关的宏定义

/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */

#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */

#define SysTick_CTRL_TICKINT_Pos            1                                             /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)              /*!< SysTick CTRL: TICKINT Mask */

#define SysTick_CTRL_ENABLE_Pos             0                                             /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)               /*!< SysTick CTRL: ENABLE Mask */

  该函数的功能是使能SysTick,开启中断,函数的输入参数ticks是设置两次中断间的间隔,也就是设置两次中断之间有多少个SysTick时钟周期。我们如下配置就可以设置SysTick中断时间间隔为1ms。

    SysTick_Config(SystemCoreClock / 1000);   // 设置SysTick中断时间间隔为1ms

  这里介绍一下为什么按照上面的设置,SysTick两次中断之间的时间间隔为1ms。比如系统频率为72MHz,我们设置的是每72K个SysTick周期进入一次中断,也就是说进入中断的时间间隔为72K / 72M,也就是1ms。

  其实我们用到的延时函数也是利用滴答定时器来实现的延时,这里我们就不再详细介绍,大家有兴趣的可以自行分析学习一下。

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

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

相关文章

docker中hyperf项目配置虚拟域名

在使用hyperf框架时&#xff0c;直接用了docker环境进行开发 下载镜像运行容器 docker run --name hyperf -v /data/project:/data/project -p 9501:9501 -itd -w /data/project --privileged -u root --entrypoint /bin/sh 镜像ID配置docker-compose.yml version: "3.…

python-产品篇-图形验证码

文章目录 准备代码效果 准备 代码 from tkinter import * from tkinter.messagebox import * import time import os root Tk() import random dirall[] randima []def call():global image1global image2global image3global image4global image5global seloneglobal …

sawForceDimensionSDK安装,sigma7+ros

force dimension的sdk中没有关于ros&#xff0c;借助开源的sawForceDimensionSDK实现对于数据的封装和可视化&#xff0c;方便后续使用 链接&#xff1a; GitHub - jhu-saw/sawForceDimensionSDK 具体步骤&#xff1a; 安装qt和ros&#xff0c;官网下载Force Dimension SDK …

Win10系统如何关闭边缘滑动功能?Win10关闭边缘滑动功能方法

Win10系统如何关闭边缘滑动功能&#xff1f;Win10系统支持电脑端和平板等移动设备&#xff0c;所以具有触控操作的功能&#xff0c;较为常见的就是边缘滑动手势功能&#xff0c;但有小伙伴想了解是否可以设置关闭&#xff0c;具体该如何设置呢&#xff1f; 设置方法 1、首先&…

idea2023新UI风格不见了怎么办?

用了一段时间idea2023,有一天不知道点了什么&#xff0c;整个UI又变成了2022的风格 如果想换成2023的UI风格怎么办&#xff1f; 点击file->setting->new UI->勾选Enable new UI&#xff0c;restart就可以回到最新版本的UI了 新风格

groovy:XmlParser 读 Freeplane.mm文件,生成测试案例.csv文件

Freeplane 是一款基于 Java 的开源软件&#xff0c;继承 Freemind 的思维导图工具软件&#xff0c;它扩展了知识管理功能&#xff0c;在 Freemind 上增加了一些额外的功能&#xff0c;比如数学公式、节点属性面板等。 强大的节点功能&#xff0c;不仅仅节点的种类很多&#xff…

Python爬虫项目实战案例-批量下载网易云榜单音乐保存至本地

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…

数学学习与研究杂志社《数学学习与研究》杂志社编辑部2023年第29期目录

考试研究 提高高三数学二轮复习质量的思考与实践 佘淮青; 2-4 提升高三数学复习质量的策略探究 王飞; 5-7 核心素养背景下的高中数学命题策略研究 陈明发; 8-10 提升中考数学复习课的有效性研讨 韩兴宏; 11-13 中学教学方法《数学学习与研究》投稿&#xff1a;…

React入门之React_渲染基础用法和class实例写法

渲染元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>04元素渲染</title><script src&…

迟到的VNCTF2024逆向题WP

这次比赛因为有事外出&#xff0c;只做了前两题&#xff0c;最近有空才把另外3题也做出来&#xff0c;总体来说比以往的VNCTF逆向题目要难一些。当然也有可能是我水平退步了&#xff0c;就算有时间参加比赛&#xff0c;应该也做不完这5题。VN的小伙伴越来越厉害了&#xff0c;出…

Python + Google AI 自动修复 Sonar Bug 实践

前言 在工作中总会遇到种种不期而至的需求&#xff0c;比如前段时间突然要修复所有 Sonar Bug&#xff0c;涉及各种琐碎的代码风格问题&#xff0c;包括但不限于语法不规范、废弃注释等问题。这些项目都已经持续开发几年了&#xff0c;Sonar 上的问题层出不穷&#xff0c;各种…

汽车三元催化器的废品项目详解,三元催化再生项目的回收技术教学

一、教程描述 这是一个收废品项目&#xff0c;就收那些别人不懂的&#xff0c;三元催化器的附加值高&#xff0c;只要掌握技术&#xff0c;怎么玩都行的&#xff0c;只是要放得下你的面子。三元催化器&#xff0c;是安装在汽车排气系统中最重要的机外净化装置&#xff0c;它可…

Python 神经概率语言模型代码实现和详解,NPLM代码实现和详解;NPLM代码模板讲解,最简单的NLP预测模型

1.神经概率语言模型&#xff1a;NPLM NPLM&#xff08;Neural Probabilistic Language Model&#xff09;是一种经典的神经概率语言模型&#xff0c;被用于自然语言处理任务中。它使用神经网络来学习词汇之间的关系&#xff0c;通过计算词汇序列的概率分布来预测下一个词汇。N…

论文设计任务书学习文档|基于Web的个性化简历职位推荐系统的设计与实现

文章目录 论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现1、论文(设计)的主要任务及目标2、论文(设计)的主要内容3、论文(设计)的基本要求4、进度安排论文(设计)题目:基于Web的个性化简历职位推荐系统的设计与实现 1、论文(设计)的主要任务及目标…

log4j 基础使用入门教程

一、Log4j介绍 在项目中&#xff0c;不管是开发人员写代码还是测试人员写的测试代码一般都需要做一些日志来记录项目的行为&#xff0c;以便更好的跟踪项目中的一些交互和问题。 Log4j ( Logger For Java ) , Java 日志的记录包。 官方网站 。Log4j 是 Apache 的一个开源项目…

理解C转汇编后代码分析

题目 . - 力扣&#xff08;LeetCode&#xff09; 解题代码 #include <stdio.h> #include "stdbool.h"typedef struct {int score;int index;int count; } Record; Record records[26] {0};int totalScore(char *w) {int total 0;for (int i 0; i < st…

程序员的金三银四/金九银十求职宝典

目录 金三银四&#xff0c;金九银十 方向一&#xff1a;面试技巧分享 方向二&#xff1a;面试题解析 方向三&#xff1a;公司文化解读 方向四&#xff1a;职业规划建议 方向五&#xff1a;成功案例展示 方向六&#xff1a;行业趋势分析 金三银四&#xff0c;金九银十 “金…

Docker制作lamp镜像并在其他机器上部署

为了方便将自己的LAMP运行环境和项目在其他机器上部署或发布&#xff0c;可以用基于Dockerhub 里的mattrayner/lamp镜像打包自己需要的镜像。 1、先选择合适的镜像文件 镜像mattrayner/lamp有多个版本&#xff0c;根据自己需要选择下载 2、镜像在首次运行时会自动下载&#x…

vue3 图片/视频 加载失败重试

vue3 图片/视频 加载失败重试 需求背景 用户手机上传图片走oss &#xff0c;在pc端在线客服连接socket 需要实时推送消息&#xff0c;接受到消息后&#xff0c;由于oss还回没有回调成功&#xff0c;所以图片/视频不能及时展示&#xff0c;所以做了一个失败重试的功能 效果图 技…

QQ录屏会录到外界声音吗?这篇文章告诉你答案

在现代网络科技快速发展的今天&#xff0c;屏幕录制已成为人们日常办公、学习、娱乐的重要工具。qq作为国内最受欢迎的社交软件之一&#xff0c;其内置的屏幕录制功能受到很多人的青睐。可是使用的过程中&#xff0c;很多人会有疑问&#xff1a;qq录屏会录到外界声音吗&#xf…