STM32/GD32芯片 单片机复位功能详解【极力推荐!】
摘要:本文详细讲解了单片机的三种复位类型(系统复位、电源复位和备份域复位),重点分析了系统复位的五种触发条件及实现原理。其中详细介绍了NRST引脚外部复位的电路设计要点,包括上电复位和手动复位实现方式,并阐述了复位后的硬件行为流程,包括寄存器初始化、启动介质选择和复位向量执行等关键步骤。文章还简要提及了通过软件触发复位的操作方法,并指出所有复位类型均可通过RCC_CSR寄存器进行状态查询。
1.前言
单片机的复位功能,重要性毋庸置疑。今天,我们根据芯片datasheet和用户手册来梳理下单片机的复位功能。
芯片有三种类型的复位,分别是系统复位、电源复位和备份域复位。
下面详细讲解一下这三种复位。
2.系统复位
只要发生以下五种实践,就会产生系统复位:
1.NRST 引脚低电平(外部复位)
2. 窗口看门狗计数结束(WWDG 复位)
3. 独立看门狗计数结束(IWDG 复位)
4. 软件复位(SW 复位)
5. 低功耗管理复位
而系统复位发生时,除了时钟控制寄存器 CSR 中的复位标志和备份域中的寄存器外,系统复位会将其它全部寄存器都复位为复位值。

2.1 NRST 引脚低电平(外部复位)
NRST在芯片上是一个复位引脚,当该引脚接受到低电平信号时,就会产生系统复位。
这个低电平信号是有电压以及持续时间的要求的。
电压得不高于0.8V,持续时间最好能大于100ns。
在外围电路设计上,推荐的设计如下图所示。
我们看下面A和B两个复位电路图设计,我们只讲解A,B不进行讲解,读者自行分析B电路图是否能用。
A:
电源VCC和GND之间,串联了电路R和电容C。刚开始供电时,电容C正极还没有电压,NRST与GND连通,低电平。当过了1个时间常数后,电容C充电完成,C正极电压大于0.8V后,NRST退出复位状态。

实际设计中,常常会增加一个手动复位的按钮。只需要在AB电路的电容两端并联一个按键,当按键按下时,NRST为低电平,MCU复位。
当复位按钮被按下时,U11开关闭合,NRST和GND连通,感受到低电平信号。
1.上电的瞬间,电容C48两端电压为0V,NRST为低电平,stm32处于复位状态,VCC3.3通过电阻R50给电容充电,当电容C48的电压升高到0.8V以上,stm32退出复位状态进入运行状态。
2.当上电持续一段时间后,C48完成了充电。当我们需要手动复位的时候只需要按下按钮,此时U11开关闭合,C48与GND连通,电容迅速放电,NRST为低电平。松手后,U11开关断开,电容C48会继续充电,当电容C48的电压升高到0.8V以上,STM32退出复位状态进入运行状态。

2.2 窗口看门狗计数结束(WWDG 复位)
本章节后续补充。
2.3 独立看门狗计数结束(IWDG 复位)
本章节后续补充。
2.4 软件复位(SW 复位)
当软件复位发生时,RCC 时钟控制和状态寄存器 (RCC_CSR) 中的复位标志位SFTRSTF会由硬件置1。当我们获知SFTRSTF位置1是,即确定发生软件复位。
要对器件进行软件复位,必须将 NVIC(嵌套向量中断控制器) 的 AIRCR(Application Interrupt and Reset Control Register) 寄存器SYSRESETREQ 位置 1
RCC 时钟控制和状态寄存器 (RCC_CSR)
上文讲到的所有类型的复位,我们都可以通过RCC 时钟控制和状态寄存器中的相应位获知,是否有相应类型的复位发生。

2.5 低功耗管理复位
本章节后续补充。
3.复位后的行为
当发生复位后,系统会做哪些工作?
以NRST 引脚低电平(外部复位)为例,当STM32的NRST引脚被拉低触发外部复位时,系统会执行以下关键操作,并最终调用SystemInit函数完成初始化:
3.1.外部复位时的系统行为
(1) 硬件复位序列
1.寄存器清零:CPU核心寄存器(如PC、SP)和外设寄存器被重置为默认值。 时钟关闭:大部分外设时钟被禁用,仅保留必要的基础时钟。
2. BOOT引脚配置:读取BOOT0和BOOT1引脚电平,确定启动介质(如Flash、SRAM或系统存储器)。
3.向量表定位:根据启动方式,从对应存储介质(如Flash起始地址0x08000000)读取中断向量表。
(2) 复位向量执行
堆栈指针初始化:从向量表的第0个位置(0x08000000)获取初始堆栈指针(MSP)。
复位处理函数跳转:从向量表的第1个位置(0x08000004)获取复位向量,跳转到Reset_Handler函数。
Reset_Handler 是硬件复位后的入口函数,负责初始化堆栈、数据段,并调用 main()。
1.硬件自动加载__initial_sp: __initial_sp的执行是硬件自动完成的,无需软件干预。复位后,Cortex-M内核直接加载__initial_sp到MSP,确保堆栈可用
复位后,内核从中断向量表起始地址0x08000000加载初始堆栈指针到MSP,确保堆栈可用。
2. 硬件自动跳转到Reset_Handler: 内核从向量表的第1个位置(0x08000004)获取复位向量,跳转到Reset_Handler函数。
3. Reset_Handler调用SystemInit: 在Reset_Handler中,通过BLX指令调用SystemInit函数,配置系统时钟和其他硬件资源。
4. 跳转到main函数: Reset_Handler最终通过__main函数跳转到用户编写的main()函数。
下面是中断向量表,
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; /* external interrupts handler */
DCD WWDGT_IRQHandler ; 16:Window Watchdog Timer
DCD LVD_IRQHandler ; 17:LVD through EXTI Line detect
DCD TAMPER_STAMP_IRQHandler ; 18:Tamper and TimeStamp through EXTI Line detect
DCD RTC_WKUP_IRQHandler ; 19:RTC Wakeup through EXTI Line
DCD FMC_IRQHandler ; 20:FMC
DCD RCU_CTC_IRQHandler ; 21:RCU and CTC
DCD EXTI0_IRQHandler ; 22:EXTI Line 0
DCD EXTI1_IRQHandler ; 23:EXTI Line 1
DCD EXTI2_IRQHandler ; 24:EXTI Line 2
DCD EXTI3_IRQHandler ; 25:EXTI Line 3
DCD EXTI4_IRQHandler ; 26:EXTI Line 4
DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel0
DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel1
DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel2
DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel3
DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel4
DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel5
DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel6
DCD ADC_IRQHandler ; 34:ADC
DCD CAN0_TX_IRQHandler ; 35:CAN0 TX
DCD CAN0_RX0_IRQHandler ; 36:CAN0 RX0
DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1
DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMC
DCD EXTI5_9_IRQHandler ; 39:EXTI5 to EXTI9
DCD TIMER0_BRK_TIMER8_IRQHandler ; 40:TIMER0 Break and TIMER8
DCD TIMER0_UP_TIMER9_IRQHandler ; 41:TIMER0 Update and TIMER9
DCD TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
DCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture Compare
DCD TIMER1_IRQHandler ; 44:TIMER1
DCD TIMER2_IRQHandler ; 45:TIMER2
DCD TIMER3_IRQHandler ; 46:TIMER3
DCD I2C0_EV_IRQHandler ; 47:I2C0 Event
DCD I2C0_ER_IRQHandler ; 48:I2C0 Error
DCD I2C1_EV_IRQHandler ; 49:I2C1 Event
DCD I2C1_ER_IRQHandler ; 50:I2C1 Error
DCD SPI0_IRQHandler ; 51:SPI0
DCD SPI1_IRQHandler ; 52:SPI1
DCD USART0_IRQHandler ; 53:USART0
DCD USART1_IRQHandler ; 54:USART1
DCD USART2_IRQHandler ; 55:USART2
DCD EXTI10_15_IRQHandler ; 56:EXTI10 to EXTI15
DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm
DCD USBFS_WKUP_IRQHandler ; 58:USBFS Wakeup
DCD TIMER7_BRK_TIMER11_IRQHandler ; 59:TIMER7 Break and TIMER11
DCD TIMER7_UP_TIMER12_IRQHandler ; 60:TIMER7 Update and TIMER12
DCD TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
DCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Capture Compare
DCD DMA0_Channel7_IRQHandler ; 63:DMA0 Channel7
DCD EXMC_IRQHandler ; 64:EXMC
DCD SDIO_IRQHandler ; 65:SDIO
DCD TIMER4_IRQHandler ; 66:TIMER4
DCD SPI2_IRQHandler ; 67:SPI2
DCD UART3_IRQHandler ; 68:UART3
DCD UART4_IRQHandler ; 69:UART4
DCD TIMER5_DAC_IRQHandler ; 70:TIMER5 and DAC0 DAC1 Underrun error
DCD TIMER6_IRQHandler ; 71:TIMER6
DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0
DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1
DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2
DCD DMA1_Channel3_IRQHandler ; 75:DMA1 Channel3
DCD DMA1_Channel4_IRQHandler ; 76:DMA1 Channel4
DCD ENET_IRQHandler ; 77:Ethernet
DCD ENET_WKUP_IRQHandler ; 78:Ethernet Wakeup through EXTI Line
DCD CAN1_TX_IRQHandler ; 79:CAN1 TX
DCD CAN1_RX0_IRQHandler ; 80:CAN1 RX0
DCD CAN1_RX1_IRQHandler ; 81:CAN1 RX1
DCD CAN1_EWMC_IRQHandler ; 82:CAN1 EWMC
DCD USBFS_IRQHandler ; 83:USBFS
DCD DMA1_Channel5_IRQHandler ; 84:DMA1 Channel5
DCD DMA1_Channel6_IRQHandler ; 85:DMA1 Channel6
DCD DMA1_Channel7_IRQHandler ; 86:DMA1 Channel7
DCD USART5_IRQHandler ; 87:USART5
DCD I2C2_EV_IRQHandler ; 88:I2C2 Event
DCD I2C2_ER_IRQHandler ; 89:I2C2 Error
DCD USBHS_EP1_Out_IRQHandler ; 90:USBHS Endpoint 1 Out
DCD USBHS_EP1_In_IRQHandler ; 91:USBHS Endpoint 1 in
DCD USBHS_WKUP_IRQHandler ; 92:USBHS Wakeup through EXTI Line
DCD USBHS_IRQHandler ; 93:USBHS
DCD DCI_IRQHandler ; 94:DCI
DCD 0 ; 95:Reserved
DCD TRNG_IRQHandler ; 96:TRNG
DCD FPU_IRQHandler ; 97:FPU
__Vectors_End
3.2.复位是否触发中断?
复位与中断的区别:
复位不属于中断,而是一种系统重置。中断需要处理器在正常操作期间响应事件,而复位则是将系统恢复到初始状态。
复位标志:
复位后,可通过检查RCC->CSR寄存器中的SFTRSTF标志位确认是否发生了软件复位。外部复位(如NRST引脚低电平)不会触发中断服务函数,但会清除所有中断标志。
3.3. SystemInit函数的调用路径
(1) 启动文件中的调用
启动文件作用:
启动文件(如startup_stm32f103xb.s)是汇编编写的初始化代码,完成从硬件复位到C环境初始化的过渡。
Reset_Handler函数:
复位向量指向的Reset_Handler是启动流程的第一个执行函数,其核心步骤如下:
;/* reset Handler */
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
(2) SystemInit的执行内容
系统时钟配置:
SystemInit函数(通常位于system_stm32fxxx.c)配置系统时钟(如将HCLK配置为72MHz),并初始化其他硬件资源(如Flash、外设时钟)。
用户覆盖机制:
允许用户通过重定义SystemInit函数来扩展或修改初始化逻辑。
3.4.验证与调试
复位状态寄存器:
通过检查RCC->CSR寄存器中的复位标志位(如PORRSTF、PINRSTF),可以确认复位的类型(如上电复位、外部复位等)。
中断服务函数:
如果复位是由看门狗超时引起的,则会在复位后执行相应的看门狗中断服务函数。但在外部复位的情况下,不会触发中断服务函数。
3.5总结
当NRST引脚低电平触发外部复位时,STM32会执行以下流程:
1.硬件复位:清零寄存器、关闭外设时钟、定位向量表。
2.跳转至Reset_Handler:从向量表获取复位向量,执行启动文件中的Reset_Handler。
3.调用SystemInit:配置系统时钟和其他硬件资源。
4.跳转至main函数:通过C库的__main函数初始化数据段和bss段,最终进入用户main()函数。
这一流程确保了系统在复位后能够稳定地初始化硬件环境,并正确执行用户程序。
本章节内容,读者可以进一步了解:STM32启动文件解析【建议收藏】
参考
1.单片机复位详解
2.STM32 复位电路设计
3.一、STM32F407ZGT6电路图设计(基础系统)
########################################################################
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)