STM32自学笔记——RCC(1)复位(独立看门狗,窗口看门狗,软件复位)
目录
RCC-reset
1. System Reset
2. Power Reset
3. Backup Domain Reset
1.WWDG
2.IWDG
3.软件复位
RCC-reset
1. System Reset
软件复位:重置SYSRESETREQ 位可以通过软件发出复位请求。
低功耗模式复位(Low-power management reset):通过两种方式生成:一种是在进入待机模式时触发,另一种是在进入停止模式时触发。这些复位操作是通过用户选项字节中的相应位(
nRST_STDBY
和nRST_STOP
)来控制的。当设备成功进入待机或停止模式时,如果相应的位被重置,系统会执行复位
2. Power Reset
外部复位流程图:
NRST引脚通过一个上拉电阻(R_PU)连接到电源(VDD/VDA),在没有外部复位信号的情况下,NRST保持高电平,保证系统正常运行。当接收到低电平信号时,NRST引脚被拉低,经过滤波后触发系统复位。当外部复位信号结束后,NRST引脚通过上拉电阻恢复到高电平,复位过程结束,系统又开始正常工作。
其余几种复位则是通过一个脉冲生成器,产生至少20微秒的复位脉冲,通过滤波后产生复位。
3. Backup Domain Reset
1.WWDG
窗口看门狗流程大致如下:
PLCK1最大频率为36Mhz,如果设置预分频器为8,根据手册公式计算
超时时间为58.25毫秒
触发复位的流程有两条,一条是红线通过比较器触发,当计数值大于窗口值时,比较器输出1,此时如果刷新计数值与门就会输出1,最后通过一个或门然后触发复位(省略了一部分步骤在图10有)
第二条是蓝线触发,当计数器的值为0x40时,如果还没刷新计数值就会减1变为0x3f,T6位为0时通过非门和或门触发复位,计数器重置
也就是说刷新计数值要在窗口值>计数值>0x3F时刷新计数值,系统才不会复位
代码验证
void WWDG_Init(void) { RCC->APB1ENR |= RCC_APB1ENR_WWDGEN; WWDG->CFR &= ~WWDG_CFR_WDGTB; WWDG->CFR |= WWDG_CFR_WDGTB; WWDG->CFR &= ~(WWDG_CR_T); WWDG->CFR |= 0x50; WWDG->CR |= WWDG_CR_WDGA | WWDG_CR_T; }
void Refresh_WWDG(void) { if ((WWDG->CR & WWDG_CR_T) < 0x50) { WWDG_SetCounter(WWDG_CR_T); } }
int main(void) { WWDG_Init(); USART1_Init(); uint16_t counter = 0; char buffer[50]; while (1) { Refresh_WWDG(); counter++; sprintf(buffer, "Counter: %u\r\n", counter); USART1_SendString(buffer); } }
通过串口打印一个自增计数器counter,正确喂狗时,程序正常运行,计数器会保持自增,未正确喂狗时,计数器会随着系统复位一直重置
2.IWDG
独立看门狗大致流程:
在计数器达到重装载值前重置计数器(喂狗)就能避免复位了
超时时间计算公式:
示例计算:
和表96计算得一致
代码验证:
void IWDG_Init(void) { IWDG->KR |= IWDG_WriteAccess_Enable; IWDG->PR |= 0x03; IWDG->RLR |= 1000; IWDG->KR |= 0xAAAA; IWDG->KR = 0xCCCC; }
void Refresh_IWDG(void) { IWDG->KR = 0xAAAA; }
int main(void) { IWDG_Init(); USART1_Init(); uint16_t counter = 0; char buffer[50]; while (1) { Refresh_IWDG(); counter++; sprintf(buffer, "Counter: %u\r\n", counter); USART1_SendString(buffer); } }
通过串口打印一个自增计数器,喂狗如果失败,counter会一直复位重新计数
3.软件复位
代码验证:
void SoftwareReset(void) { SCB->AIRCR = ((uint32_t)0x05FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk; while (1) ; } int main(void) { USART1_Init(); uint16_t counter = 0; char buffer[50]; while (1) { counter++; sprintf(buffer, "Counter: %u\r\n", counter); USART1_SendString(buffer); if (counter > 200) { SoftwareReset(); } } }
作者:重案组之虎达文西