STM32的三种复位类型和区分方法

控制/MCU

1876人已加入

描述

最近在项目的时候需要判别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("低功耗复位rn");
    }
    else if(0 != (RCC- >CSR & 0x40000000))//窗口看门狗复位标志
    {
        printf("窗口看门狗复位rn");
    }
    else if(0 != (RCC- >CSR & 0x20000000))//独立看门狗复位标志
    {
        printf("独立看门狗复位rn");
    }

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

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

使用标准库的代码:

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

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

    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("跳转rn");
    }

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

    delay_ms(3000);
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分