0

我为 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);
}
4

1 回答 1

2

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 复位,那么它要么已在启动或引导加载程序中的软件中启用,要么已在Option Bytes中启用。您可以通过读取FLASH_OBR(地址 0x4002201C)来检查吗?它的默认值为 0x03FF FFFC - 如果在您的情况下是其他值,则选项字节(这是 0x1FFFF800 - 0x1FFFF80F 的闪存的特殊区域)已被修改。具体而言,如果FLASH_OBR位 2(0x04 掩码)为零,则 IWDG 将从复位运行,无需软件专门设置。选项字节在通用 STM32F102 用户手册UM0008中没有描述,而是在闪存编程手册PM0075中描述。

一个简单的测试来证明它是一个看门狗复位是简单地将看门狗保持在繁忙循环中:

while(1)
{
    IWDG_ReloadCounter() ;
}

您还可以使用ST-Link Utility设置/重置选项字节。

IWDG 从 40KHz(标称但变化很大)RC 振荡器或 OSC_32KHz 引脚上的外部振荡器/晶体运行。对于准确的 RTC,这通常是 32768Hz。无论如何,默认预分频器是 /4,默认重载是 0x0FFF (4096)。因此,对于 32768Hz 时钟,默认 IWDG 值将导致恰好 500 毫秒 (4096/(32768/4)) 的超时,这是您观察到的。RC 振荡器的频率范围可以从 30KHz 到 60KHz,默认 IWDG 范围为 273ms 到 546ms。

于 2020-05-25T20:25:50.830 回答