stm32复位(Reset)
嵌入式老杨 2026-01-14

STM32 复位至关重要,有系统、电源和备份域复位三种类型。本文详解其分类、工作原理,还给出外部复位、看门狗复位等实验步骤,以及复位后寄存器值变化。


01

单片机复位简介


单片机复位是指将系统恢复到初始化状态,确保程序从已知状态开始执行。

stm32共有三种类型的复位,分别为系统复位、电源复位和备份域复位。

常见的应用场景为:

1.上电复位确保硬件(时钟、外设)和软件(变量、堆栈)处于默认状态,避免随机值导致异常。

2.程序跑飞,看门狗复位,恢复系统运行。

3.设备卡死,NRST外部复位实现硬件重启。

4.设备因异常(如电压波动、程序跑飞)导致RTC或备份寄存器配置损坏(例如时钟源错误、写保护异常),通过BDRST复位备份域控制寄存器,恢复RTC默认配置。

NRST 引脚低电平触发的是 系统复位(System Reset),而非 电源复位(Power Reset)。


02

复位的分类


系统复位
除了时钟控制寄存器 CSR 中的复位标志和备份域中的寄存器外,系统复位会将其它全部寄存器都复位为复位值。
只要发生以下事件之一,就会产生系统复位:
1. NRST 引脚低电平(外部复位)。
2.  窗口看门狗计数结束(WWDG 复位)。
3.  独立看门狗计数结束(IWDG 复位)。
4.  软件复位(SW 复位)(请参见 软件复位 )。
5.  低功耗管理复位(请参见 低功耗管理复位 )。

电源复位
只要发生以下事件之一,就会产生电源复位:
1. 上电/掉电复位(POR/PDR 复位)或欠压 (BOR) 复位。
2.  在退出待机模式时。



备份域复位
备份域复位会将所有 RTC 寄存器和 RCC_BDCR 寄存器复位为各自的复位值。BKPSRAM 不受此复位影响。BKPSRAM 的唯一复位方式是通过 Flash 接口将 Flash 保护等级从 1 切换到 0。
只要发生以下事件之一,就会产生备份域复位:
1. 软件复位,通过将 RCC  备份域控制寄存器 (RCC_BDCR) 中的 BDRST 位置 1 触发。
2.  在电源 V DD 和 V BAT 都已掉电后,其中任何一个又再上电。


03

复位的工作原理


复位从触发到系统初始化的完整流程可分为四个阶段:

1. 复位信号生成阶段

任意复位源(如 POR、NRST 引脚)触发后,复位控制器根据优先级生成统一复位信号。

信号经过延时电路确保脉冲宽度足够(如 POR 需等待电压稳定)。

2. 系统模块复位阶段

CPU 暂停当前指令,清除寄存器状态并从复位向量地址(0x08000004)读取启动地址。

系统总线将复位信号传播至所有外设,各模块寄存器恢复默认值(如 GPIO 设为输入模式)。

3. 复位状态记录阶段

RCC_CSR 寄存器记录最近一次复位类型,标志位包括:
PORF(上电 / 掉电复位)、PINRF(NRST 引脚复位)、IWDGRF(独立看门狗复位)等。

软件可通过读取标志位判断复位原因(如程序异常重启时定位问题)。

4. 系统初始化与启动阶段

CPU 从复位向量地址获取 PC 初始值,执行启动代码(如配置栈指针、中断向量表)。

初始化系统时钟(HSI/HSE/PLL)、外设(如 USART、ADC)及全局变量。

跳转到main()函数,应用程序开始正常运行。


04

复位的实现方法


系统复位实验步骤:

1. NRST 引脚低电平(外部复位)

void main(void){ char ch;   /* 初始化HAL库;它必须是主程序中执行的第一条指令 */ HAL_Init();  /* 系统时钟初始化成168MHz */ SystemClock_Config();  /* LED 端口初始化 */ LED_GPIO_Config();  /* 初始化串口1 */ DEBUG_USART_Config();  /* 打印指令输入提示信息 */ Show_Message();  /* 控制LED灯 */ while (1) { ch=getchar(); printf("接收到字符:%c\n",ch);  /* 根据字符指令控制RGB彩灯颜色 */ switch(ch) { case '1': LED_RED; break; case '2': LED_GREEN; break; case '3': LED_BLUE; break; case '4': LED_YELLOW; break; case '5': LED_PURPLE; break; case '6': LED_CYAN; break; case '7': LED_WHITE; break; case '8': LED_RGBOFF; break; default: /* 如果不是指定指令字符,打印提示信息 */ Show_Message(); break;  } }}


2.  窗口看门狗计数结束(WWDG 复位)

int main(void){  // 看门狗复位时,读取寄存器的值 rcc_cr = RCC->CR; rcc_pllcfgr = RCC->PLLCFGR; rcc_csr = RCC->CSR;  /* 初始化HAL库;它必须是主程序中执行的第一条指令 */ HAL_Init();  /* 系统时钟初始化成168MHz */ SystemClock_Config();  /* LED 端口初始化 */ LED_GPIO_Config();  // 读取窗口设置值 wwdg_wr = WWDG->CFR & 0X7F; LED2_OFF;  /* 控制LED灯 */ while (1) { // 读取当前计数值 wwdg_tr = WWDG->CR & 0X7F; if( wwdg_tr == wwdg_wr) { LED2_ON; } }}


3.  独立看门狗计数结束(IWDG 复位)

int main(void){ //1s内不按下按键,IWDG产生复位,读取相关寄存器 rcc_cr = RCC->CR; rcc_pllcfgr = RCC->PLLCFGR; rcc_csr = RCC->CSR;  /* 初始化HAL库;它必须是主程序中执行的第一条指令 */ HAL_Init();  /* 系统时钟初始化成168MHz */ SystemClock_Config();  /* LED 端口初始化 */ LED_GPIO_Config();  /*初始化按键*/ Key_GPIO_Config();   // IWDG,64分频,重装载值为625,超时溢出时间≈1s IWDG_Config(IWDG_PRESCALER_64 ,625);   LED2_OFF; while (1) { if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON ) { // 喂狗,如果不喂狗,系统则会复位,复位后亮红灯,如果在1s // 时间内准时喂狗的话,则会亮绿灯 IWDG_Feed();  //喂狗后亮绿灯 LED2_ON; } }}


4.  软件复位(SW 复位)

int main(void){  /* 初始化HAL库;它必须是主程序中执行的第一条指令 */ HAL_Init();  /* 系统时钟初始化成168MHz */ SystemClock_Config();  /* LED 端口初始化 */ LED_GPIO_Config();  /*初始化按键*/ Key_GPIO_Config();  // 检查复位标志位 if (RCC->CSR & RCC_CSR_SFTRSTF) { // 软件复位成功 RCC->CSR |= RCC_CSR_RMVF; // 清除复位标志 LED2_ON; // 点亮LED2表示复位成功 HAL_Delay(1000); // 延迟1秒 LED2_OFF;  //产生软件复位,读取相关寄存器 rcc_cr = RCC->CR; rcc_pllcfgr = RCC->PLLCFGR; rcc_csr = RCC->CSR;  } while (1) { //按键按下,产生软件复位 if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON  ) { LED2_ON; System_Reset(); } }} void System_Reset(void){ __DSB(); // 数据同步屏障,确保所有内存访问完成 SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |  SCB_AIRCR_SYSRESETREQ_Msk); // 触发系统复位 __DSB(); // 等待复位完成 while(1); // 进入死循环,等待复位发生}


电源复位实验步骤:

void main(void){ rcc_cr = RCC->CR; rcc_pllcfgr = RCC->PLLCFGR; rcc_csr = RCC->CSR;  while (1) { __NOP(); }}


通过硬件操作(完全掉电再上电)触发 POR/PDR(Power-On/Power-Down Reset),并在复位后立即读取 RCC_CR 寄存器,验证其值为 0x0000 XX83。


关键点: 程序上电后 不做任何 RCC 配置,直接读取 RCC->CR 并打印。 使用串口打印,便于观察结果(也可用 LED 闪烁表示,但串口更直观)。

备份域复位实验步骤:

int main(void){  /* 初始化HAL库;它必须是主程序中执行的第一条指令 */ HAL_Init();  /* 系统时钟初始化成168MHz */ SystemClock_Config();  /* LED 端口初始化 */ LED_GPIO_Config();  /*初始化按键*/ Key_GPIO_Config();   rcc_cr = RCC->CR; rcc_pllcfgr = RCC->PLLCFGR; rcc_csr = RCC->CSR; while (1) { //按键按下,产生软件复位 if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON  ) { LED2_ON; BackupDomainReset(); } } /* * 备份域复位函数 */ void BackupDomainReset(void) { /* 使能PWR时钟 */ __HAL_RCC_PWR_CLK_ENABLE();  /* 允许访问备份域 */ HAL_PWR_EnableBkUpAccess();  /* 备份域复位 */ __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); }


05

总结


1.系统复位:复位除备份域和 RCC_CSR 标志位外的所有寄存器。不会重新加载 RCC_CR 的硬件默认值,而是将寄存器清零(0x0000 0000)。

2.电源复位:手册给出的 0x0000 XX83(低字节为 0x83)是芯片从 完全掉电状态(POR/PDR) 上电时的初始值。

位 0 (HSION) = 1 → HSI 振荡器强制开启

位 1 (HSIRDY) = 1 → HSI 已就绪

位 7 (HSICAL[7:0]) = 出厂校准值 → HSI 频率校准

这是芯片在 电源域首次上电 时的状态,由硬件自动加载

3.三种类型复位后寄存器值变化如下表

寄存器类型

电源复位后值

系统复位后值

备份域复位后值

RCC_CSR

复位值(除复位标志位)

复位值(除复位标志位)

不变

备份域

不变

不变

仅RTC 寄存器和 RCC_BDCR 寄存器复位

其它

复位值

复位值

不变


4.备份域寄存器说明如下表

寄存器名称

功能说明

是否属于备份域

RCC_BDCR

备份域控制寄存器(控制LSE、RTC时钟源、BDRST等)

✅ 是

RTC寄存器

RTC_CR、RTC_TR、RTC_DR等所有RTC控制/时间/日期寄存器

✅ 是

RTC备份寄存器

RTC_BKP0~RTC_BKP19(20个32位备份寄存器)

✅ 是

备份SRAM

4KB备份SRAM(如STM32F4xx的BKPSRAM)

✅ 是

LSE振荡器

低速外部32.768kHz晶振(通过RCC_BDCR控制)

✅ 是

VBAT电源域

由VBAT引脚(电池)独立供电的电路(维持备份域在VDD掉电时工作)

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。 微信联系小助理
0
评论
  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
下载排行榜
更多
评测报告
更多
广告