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。