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

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

封面图

目录

  • 一、复位
    • 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_CLRCC->CFGR &= (uint32_t)0xF8FF0000;
#elseRCC->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_ExtSRAMSystemInit_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_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 
}

关于系统时钟配置函数的内容,大家可以自行对照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.mzph.cn/news/716629.shtml

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

相关文章

部署bpmn项目实现activiti流程图的在线绘制

本教程基于centos7.6环境中完成 github开源项目: https://github.com/Yiuman/bpmn-vue-activiti软件&#xff1a;git、docker 1. 下载源代码 git clone https://github.com/Yiuman/bpmn-vue-activiti.git2. 修改Dockerfile文件 声明基础镜像&#xff0c;将项目打包&#xff…

EasyRecovery数据恢复软件有什么优势呢?

EasyRecovery数据恢复软件具有以下优势&#xff1a; 强大的恢复能力&#xff1a;EasyRecovery采用先进的扫描和恢复技术&#xff0c;能够深度扫描存储设备&#xff0c;寻找并恢复因各种原因丢失的数据。无论是误删除、格式化、分区损坏还是病毒感染&#xff0c;它都能提供有效…

设计模式(十一)策略模式

请直接看原文:设计模式&#xff08;十一&#xff09;策略模式_某移动支付系统在实现账户资金转入和转出时需要进行身份验证,该系统为用户提供了-CSDN博客 ----------------------------------------------------------------------------------------------------------------…

SpringMVC 学习(十一)之数据校验

目录 1 数据校验介绍 2 普通校验 3 分组校验 4 参考文档 1 数据校验介绍 在实际的项目中&#xff0c;一般会有两种校验数据的方式&#xff1a;客户端校验和服务端校验 客户端校验&#xff1a;这种校验一般是在前端页面使用 JS 代码进行校验&#xff0c;主要是验证输入数据…

文物预防性保护系统方案的需求分析

没有文物保存环境监测&#xff0c;就不能实施有效的文物预防性保护。因此要建立文物预防性保护体系&#xff0c;一定要先有良好的文物状态监测制度,进而进行科学有效的文物保护管理。所以,导入文物预防性保护监测与调控系统,首先就是要针对文物进行全年温度、湿度、光照等关键参…

使用Zint库生成一维码/条形码

下面代码是是使用 Zint 库生成 Code 128 类型的条形码&#xff0c;并将生成的条形码保存为 output.bmp 文件。下面是对代码的详细解释&#xff1a; #include 和 #include <zint.h>&#xff1a;这两行代码包含了所需的头文件&#xff0c;分别是标准输入输出流的头文件和 Z…

LeetCode---【链表的操作】

目录 206反转链表【链表结构基础】21合并两个有序链表【递归】我的答案【错误】自己修改【超出时间限制】在官方那里学到的【然后自己复写,错误】对照官方【自己修改】 160相交链表【未理解题目目的】在b站up那里学到的【然后自己复写,错误】【超出时间限制】对照官方【自己修改…

(C语言)qsort函数模拟实现

前言 我们需先了解qsort函数 qsort函数详解&#xff1a;http://t.csdnimg.cn/rTNv9 qsort函数可以排序多种数据类型&#xff0c;很是神奇&#xff0c;这是为什么&#xff0c;我们在里模拟实现这样的功能 目录 1. qsort函数模拟实现 2. 我们使用bubble_sort函数排序整形数…

Sunshine v0.21.0 安装卡住,闪退的问题解决

上期博客讲了如何利用 Sunshine 和 Moonlight 实现 iPad 当作 Windows 副屏&#xff0c;用官方 Windows installer 安装 Sunshine 过程中&#xff0c;遇到了安装卡住&#xff08;这个是因为需要国外网络环境&#xff09;&#xff0c;安装后运行闪退的问题。 Sunshine 下载地址…

OpenCV 4基础篇| OpenCV图像的裁切

目录 1. Numpy切片1.1 注意事项1.2 代码示例 2. cv2.selectROI()2.1 语法结构2.2 注意事项2.3 代码示例 3. Pillow.crop3.1 语法结构3.2 注意事项3.3 代码示例 4. 扩展示例&#xff1a;单张大图裁切成多张小图5. 总结 1. Numpy切片 语法结构&#xff1a; retval img[y:yh, x…

以目标检测和分类任务为例理解One-Hot Code

在目标检测和分类任务中&#xff0c;每一个类别都需要一个编码来表示&#xff0c;同时&#xff0c;这个编码会用来计算网络的loss。比如有猫&#xff0c;狗&#xff0c;猪三种动物&#xff0c;这三种动物相互独立&#xff0c;在分类中&#xff0c;将其中任意一种分类为其他都同…

YOLOv9独家原创改进|使用可改变核卷积AKConv改进RepNCSPELAN4

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、改进点介绍 AKConv是一种具有任意数量的参数和任意采样形状的可变卷积核&#xff0c;对不规则特征有更好的提取效果。 RepNCSPELAN4是YOLOv9中的…

2023年12月CCF-GESP编程能力等级认证Scratch图形化编程四级真题解析

一、单选题(共15题,共30分) 第1题 现代计算机是指电子计算机,它所基于的是( )体系结构。 A:艾伦图灵 B:冯诺依曼 C:阿塔纳索夫 D:埃克特-莫克利 答案:B 第2题 默认小猫角色,执行下列程序,以下说法正确的是? ( ) A:舞台上会出现无数个小猫 B:舞台只会出现…

java spring 02. AbstractApplicationContext

spring创建对象的顺序&#xff0c;先创建beanfactory&#xff0c;再会把xml文件读取到spring。 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, Nullable ApplicationContext parent)throws BeansException {//调用父类的构造方法super(p…

Redis常用指令,jedis与持久化

1.redis常用指令 第一个是key的常用指令&#xff0c;第二个是数据库的常用指令 前面的那些指令都是针对某一个数据类型操作的&#xff0c;现在的都是对所有的操作的 1.key常用指令 key应该设计哪些操作 key是一个字符串&#xff0c;通过key获取redis中保存的数据 对于key…

flink重温笔记(九):Flink 高级 API 开发——flink 四大基石之WaterMark(Time为核心)

Flink学习笔记 前言&#xff1a;今天是学习 flink 的第 9 天啦&#xff01;学习了 flink 四大基石之 Time的应用—> Watermark&#xff08;水印&#xff0c;也称水位线&#xff09;&#xff0c;主要是解决数据由于网络延迟问题&#xff0c;出现数据乱序或者迟到数据现象&…

通过大语言模型理解运维故障:评估和总结

张圣林 南开大学软件学院副教授、博士生导师 第六届CCF国际AIOps挑战赛程序委员会主席 在ATC、WWW、VLDB、KDD、SIGMETRICS等国际会议和JSAC、TC、TSC等国际期刊发表高水平论文50余篇。主持国家自然科学基金项目2项&#xff0c;横向项目13项&#xff08;与华为、字节跳动、腾讯…

Sqli-labs靶场第20关详解[Sqli-labs-less-20]自动化注入-SQLmap工具注入

Sqli-labs-Less-20 通过测试发现&#xff0c;在登录界面没有注入点&#xff0c;通过已知账号密码admin&#xff0c;admin进行登录发现&#xff1a; 登录后会有记录 Cookie 值 设想如果在Cookie尝试加上注入语句&#xff08;报错注入&#xff09;&#xff0c;测试是否会执行…

C++STL之vector

vector 1. vector介绍 vector文档vector其实就是一个顺序表&#xff0c;它表示可变大小数组的序列容器。像数组一样&#xff0c;可以使用下标[] 来访问vector的元素&#xff0c;和数组一样高效&#xff1b;甚至&#xff0c;它的大小是可以动态改变的&#xff0c;其大小由容器自…

软考55-上午题-【数据库】-数据库设计步骤1

一、数据库设计的步骤 新奥尔良法&#xff0c;四个主要阶段&#xff1a; 1、用户需求分析&#xff1a;手机用户需求&#xff0c;确定系统边界&#xff1b; 2、概念设计&#xff08;概念结构设计&#xff09;&#xff1a;是抽象概念模型&#xff0c;较理想的是采用E-R方法。 …