0

我最近购买了一块 NUCLEO-F446RE 板(STM32F4 产品),我在启用 PWR 寄存器中的位时遇到了重大问题。

我的目标是使用计时器使 LED 闪烁,并且我正在尝试将 HSI 时钟配置为 180 MHz 的最大系统频率。

我已按照参考手册中的说明设置为“T”。以下是说明的屏幕截图:参考手册的屏幕截图

IDE:Keil v5

该板正在运行最新的固件。

这是我的代码:

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"

/* Private function prototypes -----------------------------------------------*/
static void sysClockConfig(void);
static void tim3Config(void);

/**
  ******************************************************************************
  * @brief  Main program.
  * @note   None
  * @param  None
  * @retval None
  ******************************************************************************
  */
int main(void) {

    sysClockConfig();
    tim3Config();

    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;                //Enable GPIOA CLK
    GPIOA->MODER |= GPIO_MODER_MODE5_0;                 //GPIOA pin5 selected as output
    GPIOA->ODR   |= GPIO_ODR_OD5;                       //GPIOA pin5 set high
    volatile int i;

    while(1) {

        GPIOA->ODR |= GPIO_ODR_OD5;
        for(i=0; i<1000000; i++);
        GPIOA->ODR &= ~GPIO_ODR_OD5;
        for(i=0; i<1000000; i++);
    }

}

/**
  ******************************************************************************
  * @brief  Configures sysmtem clock and main PLL.
  *         Initializes voltage regulator scaling and overdrive mode.
  *         Initializes flash memory.
  * @note   CLK  SRC  = HSI -> PLL
  #         SYS  CLK  = 180 MHz
  *         AHB  CLK  = 180 MHz
  *         APB1 CLK  =  45 MHz
  *         APB2 CLK  =  90 MHz
  *         Change latency depending on freq and voltage (see table 5, pg.63)
  *         Look at pg.94 for CLK config sequence
  * @param  None
  * @retval None
  ******************************************************************************
  */
static void sysClockConfig(void) {

    RCC->CR |=  RCC_CR_HSION;                           //Enables HSI clock
    while( !(RCC->CR & RCC_CR_HSIRDY) );                //Waits until HSI is stable
    RCC->CFGR |= RCC_CFGR_SW_HSI;                       //Select HSI is SYS CLK
    while( RCC->CFGR & RCC_CFGR_SWS_HSI );              //Wait until HSI is SYS CLK
    RCC->CR &= ~RCC_CR_PLLON;                            //Disables PLL

    //-----> ISSUE #1 <-----
    PWR->CR |= PWR_CR_VOS;                              //Voltage reg = scale 3
    while( !(PWR->CSR & PWR_CSR_VOSRDY) );              //Waits until scaling is ready

    /** PLL config: I2S/SAI/SPDIF = VCO / R  
      *                  USB/SDIO = VCO / Q
      *                   SYS CLK = VCO / P
      *                       VCO = HSI * (N/M)  
      */
    RCC->PLLCFGR |= (  8u                   |           //PLL_M   =   8
                    (180u <<  6)            |           //PLL_N   = 180
                    (  0u << 16)            |           //PLL_P   =   2
                    (RCC_PLLCFGR_PLLSRC_HSI)|           //PLL SRC = HSI 
                    (  8u << 24)            |           //PLL_Q   =   8
                    (  4u << 28)             );         //PLL_R   =   4

    RCC->CR |= RCC_CR_PLLON;                            //Enable PLL

    //-----> ISSUE #2 <-----
    PWR->CR |= PWR_CR_ODEN;                             //Enables Overdrive mode
    while( !(PWR->CSR & PWR_CSR_ODRDY) );               //Waits until OD is ready
    PWR->CR |= PWR_CR_ODSWEN;                           //Swites Overdrive mode   
    while( !(PWR->CSR & PWR_CSR_ODSWRDY) );             //Waits until OD switch is ready

    FLASH->ACR |= (FLASH_ACR_PRFTEN     |               //Prefetch enable
                   FLASH_ACR_ICEN       |               //Intruction cache enable
                   FLASH_ACR_DCEN       |               //Data cache enable
                   FLASH_ACR_LATENCY_5WS );             //FLASH 5 wait states          

    while( !(RCC->CR & RCC_CR_PLLRDY) );                //Waits until PLL is locked

    RCC->CFGR |= (RCC_CFGR_HPRE_DIV1    |               //AHB  = Sys CLK DIV_1
                  RCC_CFGR_PPRE1_DIV4   |               //APB1 = AHB CLK DIV_4
                  RCC_CFGR_PPRE2_DIV2   |               //APB2 = AHB CLK DIV_2
                  RCC_CFGR_SW_PLL        );             //Select PLL as SYS CLK
    while( !(RCC->CFGR & RCC_CFGR_SWS_PLL) );           //Waits until PLL is SYS CLK
}

/**
  ******************************************************************************
  * @brief  Configures TIM3.
  * @note   None
  * @param  None
  * @retval None
  ******************************************************************************
  */
static void tim3Config(void) {

}

我还没有完成定时器的设置,所以我只是使用 CPU 浪费循环来闪烁 LED。

有 2 个问题(1 个次要问题和 1 个主要问题):

1.

PWR->CR |= PWR_CR_VOS;
while( !(PWR->CSR & PWR_CSR_VOSRDY) );

当我执行上面的代码时,它陷入了无限循环。考虑到默认情况下启用该值,这并不是什么大问题。虽然我想知道为什么会这样。我一直在评论这个块来执行下面的代码块。

2.

PWR->CR |= PWR_CR_ODEN;
while( !(PWR->CSR & PWR_CSR_ODRDY) );
PWR->CR |= PWR_CR_ODSWEN;
while( !(PWR->CSR & PWR_CSR_ODSWRDY) );

上面的代码是最麻烦的。当我调试我的代码时,PWR_CR_ODEN 没有启用并最终陷入第二行的无限循环。我还尝试使用以下方法启用该位:

PWR->CR |= (1 << 16);

但它仍然卡在第二行代码上。

参考手册没有说明配置该寄存器的任何特殊之处。我完全迷失在这里。

奇怪的是,如果我完全省略了 2 块代码,程序将执行并闪烁 LED。但是,我想解决上面显示的问题并了解为什么会发生这种情况。

任何帮助是极大的赞赏。对不起,很长的帖子。

4

1 回答 1

2

在 STM32 中使用(几乎)任何外设 - 包括PWR- 您必须首先在RCC模块中启用它的时钟。见APB1ENR寄存器中第 28 位的描述RCC。如果没有这一步,任何对禁用外设寄存器的写入都将被忽略,任何读取都会给你 0。

于 2017-03-27T09:56:33.073 回答