Конфигурация часов stm32f4 не включает биты в регистре PWR

Я недавно купил плату NUCLEO-F446RE (продукт STM32F4), и у меня серьезные проблемы с включением битов в регистре PWR.

Моя цель - мигать светодиодом с помощью таймера, и я пытаюсь настроить тактовую частоту HSI на максимальную системную частоту 180 МГц.

Я выполнил инструкции в справочном руководстве на букву «Т». Ниже приведен снимок экрана с инструкциями: Снимок экрана к справочному руководству

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) {

}

Я не закончил настройку таймера, поэтому я просто использую цикл потери ресурсов процессора, чтобы мигать светодиодом.

Есть 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 блока кода, программа выполнится и замигает светодиодом. Однако я хотел бы решить проблемы, показанные выше, и понять, почему это происходит.

Любая помощь приветствуется. И извините за длинный пост.


person wait_wut    schedule 27.03.2017    source источник


Ответы (1)


В STM32 для использования (почти) любого периферийного устройства, включая PWR, вы должны сначала включить его часы в модуле RCC. См. Описание бита 28 в регистре APB1ENR в RCC. Без этого шага любая запись в регистр отключенного периферийного устройства будет проигнорирована, и любое чтение даст вам 0.

person Freddie Chopin    schedule 27.03.2017
comment
Ух ты! Я, должно быть, пропустил это на блок-схеме. Работал как шарм. Большое тебе спасибо. - person wait_wut; 27.03.2017