【STM32学习笔记】技巧2 - STM32的复位类型及区别

最近在项目的时候需要判别STM32的复位类型,网上这部分资料也有许多大神进行总结。但是感觉不是特别深入,因此,小编参考参考了STM32的参考手册进行详细总结了一下。

1、STM32的三种复位类型

分别为系统复位、电源复位和备份域复位。每一种型号的STM32都包含有这三种复位类型!

1.1、系统复位

除了时钟控制寄存器 CSR 中的复位标志和备份域中的寄存器外,
系统复位会将其它全部寄存器都复位为复位值,只要发生以下事件之一,就会产生系统复位:

  1. NRST 引脚低电平(外部复位)
  2. 窗口看门狗计数结束( WWDG 复位)
  3. 独立看门狗计数结束( IWDG 复位)
  4. 软件复位( SW 复位)
  5. 低功耗管理复位

1.1.1、软件复位

要对器件进行软件复位,必须将 Cortex™-M4F 应用中断和复位控制寄存器中的SYSRESETREQ 位置 1,标准库和HAL库默认都是置1的,软件复位的代码如下:

void NVIC_SystemReset(void)
{
  __DSB();                                                     
                                                                  
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
                 SCB_AIRCR_SYSRESETREQ_Msk);                   
  __DSB();                                                    
  while(1);                                                    
}

1.1.2、低功耗管理复位

引发低功耗管理复位的方式有两种:

  1. 进入待机模式时产生复位:
    此复位的使能方式是清零用户选项字节中的 nRST_STDBY 位。使能后,只要成功执行
    进入待机模式序列,器件就将复位,而非进入待机模式。
  2. 进入停止模式时产生复位:
    此复位的使能方式是清零用户选项字节中的 nRST_STOP 位。使能后,只要成功执行
    进入停止模式序列,器件就将复位,而非进入停止模式。

1.2、电源复位

除备份域内的寄存器以外,电源复位会将其它全部寄存器设置为复位值。只要发生以下事件之一,就会产生电源复位:

  1. 上电/掉电复位( POR/PDR 复位)或欠压 (BOR) 复位
  2. 在退出待机模式时

这些源均作用于 NRST 引脚,该引脚在复位过程中始终保持低电平。 RESET 复位入口向量
在存储器映射中固定在地址 0x0000_0004。
芯片内部的复位信号会在 NRST 引脚上输出。脉冲发生器用于保证最短复位脉冲持续时间,
可确保每个内部复位源的复位脉冲都至少持续 20 μs。 对于外部复位,在 NRST 引脚处于低
电平时产生复位脉冲。

1.3、备份域复位

备份域复位会将所有 RTC 寄存器和 RCC_BDCR 寄存器复位为各自的复位值。只要发生以下事件之一,就会产生备份域复位:

  1. 软件复位,通过将 RCC 备份域控制寄存器 (RCC_BDCR) 中的 BDRST 位置 1 触发。
  2. 在电源 VDD 和 VBAT 都已掉电后,其中任何一个又再上电。

BKPSRAM 不受此复位影响。 BKPSRAM 的唯一复位方式是通过 Flash 接口将 Flash 保护等级从 1 切换到 0。

2、STM32复位类型的区分

在实际项目中需要判断复位的类型,从而进行下一步动作。

判断复位类型的寄存器是RCC_CSR寄存器(RCC 时钟控制和状态寄存器 ),STM32的参考手册如下介绍:
RCC_CSR
由上面的寄存器介绍可以知道,我们直接读取这个寄存器的值就能知道是什么引起的复位。
读取完成后记得要将第24位,即RMVF置1。清除复位的标志。

2.1、STM32区分复位类型的代码实现

直接操作寄存器的代码:

	if(0 != (RCC->CSR & 0x80000000))//低功耗复位标志
	{
		printf("低功耗复位\r\n");
	}
	else if(0 != (RCC->CSR & 0x40000000))//窗口看门狗复位标志
	{
		printf("窗口看门狗复位\r\n");
	}
	else if(0 != (RCC->CSR & 0x20000000))//独立看门狗复位标志
	{
		printf("独立看门狗复位\r\n");
	}

	else if(0 != (RCC->CSR & 0x10000000))//软件复位标志
	{
		printf("软件复位\r\n");
	}
	else if(0 != (RCC->CSR & 0x08000000))//上电/掉电复位标志
	{
		printf("上电/掉电复位\r\n");
	}
	else if(0 != (RCC->CSR & 0x04000000))//引脚复位标志
	{
		printf("引脚复位\r\n");
	}
	else if(0 != (RCC->CSR & 0x02000000))//BOR 复位标志
	{
		printf("BOR复位\r\n");
	}

	RCC->CSR |= 0x01000000;//清除复位标志

使用标准库的代码:

	if(1 == RCC_GetFlagStatus(RCC_FLAG_LPWRRST))//低功耗复位标志
	{
		printf("低功耗复位\r\n");
	}
	else if(1 == RCC_GetFlagStatus(RCC_FLAG_WWDGRST))//窗口看门狗复位标志
	{
		printf("窗口看门狗复位\r\n");
	}
	else if(1 == RCC_GetFlagStatus(RCC_FLAG_IWDGRST))//独立看门狗复位标志
	{
		printf("独立看门狗复位\r\n");
	}

	else if(1 == RCC_GetFlagStatus(RCC_FLAG_SFTRST))//软件复位标志
	{
		printf("软件复位\r\n");
	}
	else if(1 == RCC_GetFlagStatus(RCC_FLAG_PORRST))//上电/掉电复位标志
	{
		printf("上电/掉电复位\r\n");
	}
	else if(1 == RCC_GetFlagStatus(RCC_FLAG_PINRST))//引脚复位标志
	{
		printf("引脚复位\r\n");
	}
	else if(1 == RCC_GetFlagStatus(RCC_FLAG_BORRST))//BOR 复位标志
	{
		printf("BOR复位\r\n");
	}

	RCC_ClearFlag();//清除复位标志

3、复位和iap_load_app的区别

  1. 发生复位,系统会记录一些标志信息。
  2. 但是使用iap_load_app跳转到0x8000000的位置,系统会一直默认在执行。不会有复位的标志返回。

如果在代码中使用iap_load_app来代替复位是可行的,即将复位函数NVIC_SystemReset();替换成iap_load_app(FLASH_BASE);即可。
此时RCC->CSR寄存器为0。

	if(0 == RCC->CSR)
	{
		printf("跳转\r\n");
	}

	RCC_ClearFlag();//清除复位标志
	
	delay_ms(3000);
	iap_load_app(FLASH_BASE);

结束

欢迎大家关注我的微信号:redeemer奇
一起交流!一起努力!

软件下载 | 学习视频 | 嵌入式书籍 | 项目资料 |公众号中持续更新…

redeemer奇

  • 6
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32是一款非常流行的嵌入式微控制器系列,它具有强大的性能和丰富的外设资源。在学习STM32时,掌握如何进行Flash读写是非常重要的。 Flash是一种非易失性存储器,可以用来存储程序代码和数据。在STM32中,Flash存储器通常用来存储应用程序代码。下面是一个简单的Flash读写程序的示例: 1.首先,我们需要包含适用于所使用的STM32型号的头文件。例如,对于STM32F4系列,我们需要包含"stm32f4xx.h"。 2.然后,我们需要定义一个指向Flash存储器的指针变量。例如,可以使用如下代码:`uint32_t* flash_address = (uint32_t*)0x08000000;`其中0x08000000是Flash存储器的起始地址。 3.要读取Flash存储器中的数据,我们可以通过以下代码实现:`data = *flash_address;`其中data是一个变量,用于存储读取到的数据。 4.要写入数据到Flash存储器中,我们可以通过以下代码实现:`*flash_address = data;`其中data是要写入的数据。 需要注意的是,STM32的Flash存储器是有写保护机制的,因此在写入数据之前,我们需要禁用写保护。可以使用以下代码禁用写保护:`FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB;`然后才能进行数据写入。 另外,为了确保数据的完整性,我们可以使用CRC校验来验证Flash存储器中的程序代码的正确性。可以使用库函数来计算校验和,然后将其与预期的校验和进行比较以进行验证。 综上所述,掌握STM32的Flash读写操作对于嵌入式系统的开发非常重要。上述示例代码可以帮助我们快速进行Flash读写操作,同时注意写保护和数据校验可以提高数据的安全性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

redeemer奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值