C STM32F103芯片大约每500毫秒复位一次

C STM32F103芯片大约每500毫秒复位一次,c,embedded,stm32,stm32f1,C,Embedded,Stm32,Stm32f1,我为stm32f103rbt6芯片编写了一个简单的闪烁程序,但过了一会儿,我注意到MCU不断地复位。当我检查RCC-CSR寄存器时,PINRSTF标志为高。 但我没有将任何外部连接到NRST引脚。 有人知道为什么会这样吗?这种情况是否有可能是内部原因造成的 这是我为调试而编写的程序。结果是,每次LED都想打开,但很快就会关闭 #include "stm32f10x.h" #include "stm32f10x_rcc.h" #include "stm32f10x_gpio.h" #include

我为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( 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_状态值

如果这很可能是IWDG重置,则在启动或引导加载程序中已在软件中启用,或者在选项字节中启用。您可以通过读取闪存OBR来检查(地址0x4002201C)? 它的默认值是0x03FF FFFC-如果在您的情况下它是其他值,那么选项字节(在0x1FFF800-0x1FFF80F处是闪存的一个特殊区域)已被修改。具体而言,如果
FLASH_OBR
位2(0x04掩码)为零,则IWDG将从复位运行,无需软件专门设置。选项字节未在通用STM32F102用户手册中描述,而是在闪存编程手册中描述

为了证明它是看门狗复位,一个简单的测试就是将看门狗保持在忙碌的循环中:

while(1)
{
    IWDG_ReloadCounter() ;
}
您还可以使用设置/重置选项字节


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

您的
RCC_GetFlagStatus()
中检查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_状态值

如果这很可能是IWDG重置,则在启动或引导加载程序中已在软件中启用,或者在选项字节中启用。您可以通过读取闪存OBR来检查(地址0x4002201C)? 它的默认值是0x03FF FFFC-如果在您的情况下它是其他值,那么选项字节(在0x1FFF800-0x1FFF80F处是闪存的一个特殊区域)已被修改。具体而言,如果
FLASH_OBR
位2(0x04掩码)为零,则IWDG将从复位运行,无需软件专门设置。选项字节未在通用STM32F102用户手册中描述,而是在闪存编程手册中描述

为了证明它是看门狗复位,一个简单的测试就是将看门狗保持在忙碌的循环中:

while(1)
{
    IWDG_ReloadCounter() ;
}
您还可以使用设置/重置选项字节


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

这不是一个真正的答案,但太多了,无法评论。更多关于如何更有效地调查问题中使用的调试方法。将更新以响应注释或问题更新@aygin(如果即将出现)。我尝试了调试模式。这似乎是看门狗的问题。但问题是我从来没有启用过独立的看门狗,我也不知道如何禁用它。RCC_CSR值为:10 0100 0000 0010。这意味着标志PINRSTF和IWDGRSTF为高。@aygin OK,用选项字节的信息更新。@aygin:当您在问题中声明没有任何东西连接到NRST引脚时,您的ST链接连接了吗?因为那是连接到NRST的。@aygin:的确-我是在内存中工作,没有访问API。根本不需要
IWDG_setrelad()
,它已被设置或处于默认状态。但是,您确实应该弄清楚如何禁用它。请注意,启用看门狗时,选项位为零-这可能违反直觉。这不是一个真正的答案,但对于注释来说太多了。更多关于如何更有效地调查问题中使用的调试方法。将更新以响应注释或问题更新@aygin(如果即将出现)。我尝试了调试模式。这似乎是看门狗的问题。但问题是我从来没有启用过独立的看门狗,我也不知道如何禁用它。RCC_CSR值为:10 0100 0000 0010。这意味着标志PINRSTF和IWDGRSTF为高。@aygin OK,已更新选项字节的信息。@aygin:W