STM32F103芯片大约每500ms保持复位一次
STM32F103 chip keeps resetting about every 500ms
我为stm32f103rbt6芯片写了一个简单的闪烁程序,但过了一会儿我发现MCU在不断地复位。当我检查 RCC-CSR 寄存器时,PINRSTF 标志为高。
但我没有将任何外部连接到 NRST 引脚。
有没有人知道为什么会这样?有没有可能是什么内部原因导致了这种情况?
这是我为了调试而写的程序。结果是每次 LED 想要打开但很快关闭。
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "system_stm32f10x.h"
#include "delay.h"
#include "output.h"
int main(void){
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = PIN_52.pin;
GPIO_Init(PIN_52.port, &GPIO_InitStructure);
GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_SET);
if (RCC_GetFlagStatus(RCC_FLAG_SFTRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
} else if (RCC_GetFlagStatus(RCC_FLAG_PORRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
} else if (RCC_GetFlagStatus(RCC_FLAG_PINRST)){
GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
} else if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}else if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}else if (RCC_GetFlagStatus(RCC_FLAG_LPWRRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}else {
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}
RCC_ClearFlag();
while (1);
}
你的 RCC_GetFlagStatus()
检查 if
-else if
链只检测到有序列表中的第一个标志,但这些标志并不互斥,你应该检查 所有重置标志。
if( RCC_GetFlagStatus(RCC_FLAG_SFTRST) )
{
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}
if( RCC_GetFlagStatus(RCC_FLAG_PORRST) )
{
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}
// etc...
既然你有一个 ST-Link 调试器,想必你有一个源代码级调试器?在这种情况下,与其尝试在单个 LED 引脚上进行调试,不如使用源代码级调试器,并在每个状态标志检查主体中放置一个断点。或者更简单,但在一个地方读取整个寄存器:
uint32_t rcc_status = RCC->CSR ;
RCC->CSR |= RCC_CSR_RMVF ;
while(1) ; // breakpoint here
然后在调试器中检查 rcc_status 值。
如果这很可能是 IWDG 重置,那么要么它已在启动软件或引导加载程序中启用,要么在 选项字节 中启用.您可以通过阅读 FLASH_OBR
(地址 0x4002201C)来检查吗?
它的默认值为 0x03FF FFFC - 如果在您的情况下它是其他值,则 选项 bytes (这是闪存的特殊区域 0x1FFFF800 - 0x1FFFF80F)已被修改。具体来说,如果 FLASH_OBR
位 2(0x04 掩码)为零,则 IWDG 将 运行 从复位开始,而无需由软件专门设置。一般STM32F102用户手册中没有描述选项字节UM0008, but rather in the flash programming manual PM0075.
证明它是看门狗复位的简单测试是简单地在忙循环中保持看门狗:
while(1)
{
IWDG_ReloadCounter() ;
}
您还可以 set/reset 使用 ST-Link Utility 选项字节。
IWDG 运行 来自 40KHz(标称但变化很大)RC 振荡器,或 OSC_32KHz 引脚上的外部 oscillator/crystal。对于准确的 RTC,这通常是 32768Hz。无论如何,默认预分频器是 /4,默认重载是 0x0FFF (4096)。因此,对于 32768Hz 时钟,默认的 IWDG 值将在恰好 500 毫秒 (4096/(32768/4)) 时导致超时,这正是您所观察到的。 RC 振荡器的范围可能从 30KHz 到 60KHz,默认 IWDG 范围为 273ms 到 546ms。
我为stm32f103rbt6芯片写了一个简单的闪烁程序,但过了一会儿我发现MCU在不断地复位。当我检查 RCC-CSR 寄存器时,PINRSTF 标志为高。 但我没有将任何外部连接到 NRST 引脚。 有没有人知道为什么会这样?有没有可能是什么内部原因导致了这种情况?
这是我为了调试而写的程序。结果是每次 LED 想要打开但很快关闭。
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "system_stm32f10x.h"
#include "delay.h"
#include "output.h"
int main(void){
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = PIN_52.pin;
GPIO_Init(PIN_52.port, &GPIO_InitStructure);
GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_SET);
if (RCC_GetFlagStatus(RCC_FLAG_SFTRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
} else if (RCC_GetFlagStatus(RCC_FLAG_PORRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
} else if (RCC_GetFlagStatus(RCC_FLAG_PINRST)){
GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
} else if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}else if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}else if (RCC_GetFlagStatus(RCC_FLAG_LPWRRST)){
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}else {
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}
RCC_ClearFlag();
while (1);
}
你的 RCC_GetFlagStatus()
检查 if
-else if
链只检测到有序列表中的第一个标志,但这些标志并不互斥,你应该检查 所有重置标志。
if( RCC_GetFlagStatus(RCC_FLAG_SFTRST) )
{
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}
if( RCC_GetFlagStatus(RCC_FLAG_PORRST) )
{
//GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}
// etc...
既然你有一个 ST-Link 调试器,想必你有一个源代码级调试器?在这种情况下,与其尝试在单个 LED 引脚上进行调试,不如使用源代码级调试器,并在每个状态标志检查主体中放置一个断点。或者更简单,但在一个地方读取整个寄存器:
uint32_t rcc_status = RCC->CSR ;
RCC->CSR |= RCC_CSR_RMVF ;
while(1) ; // breakpoint here
然后在调试器中检查 rcc_status 值。
如果这很可能是 IWDG 重置,那么要么它已在启动软件或引导加载程序中启用,要么在 选项字节 中启用.您可以通过阅读 FLASH_OBR
(地址 0x4002201C)来检查吗?
它的默认值为 0x03FF FFFC - 如果在您的情况下它是其他值,则 选项 bytes (这是闪存的特殊区域 0x1FFFF800 - 0x1FFFF80F)已被修改。具体来说,如果 FLASH_OBR
位 2(0x04 掩码)为零,则 IWDG 将 运行 从复位开始,而无需由软件专门设置。一般STM32F102用户手册中没有描述选项字节UM0008, but rather in the flash programming manual PM0075.
证明它是看门狗复位的简单测试是简单地在忙循环中保持看门狗:
while(1)
{
IWDG_ReloadCounter() ;
}
您还可以 set/reset 使用 ST-Link Utility 选项字节。
IWDG 运行 来自 40KHz(标称但变化很大)RC 振荡器,或 OSC_32KHz 引脚上的外部 oscillator/crystal。对于准确的 RTC,这通常是 32768Hz。无论如何,默认预分频器是 /4,默认重载是 0x0FFF (4096)。因此,对于 32768Hz 时钟,默认的 IWDG 值将在恰好 500 毫秒 (4096/(32768/4)) 时导致超时,这正是您所观察到的。 RC 振荡器的范围可能从 30KHz 到 60KHz,默认 IWDG 范围为 273ms 到 546ms。