configuración de PLL para STM32F103RC

0

Estaba haciendo la configuración PLL para ejecutar mi STM32F103RCT6 a 72MHz. Estoy usando la biblioteca CMSIS y, por lo tanto, tomé la ayuda de la biblioteca periférica estándar para escribir este código. Tengo algunas dudas que me gustaría obtener en el formulario de respuesta.

Primero que todo mi código.

/* Project: PLL Configuration (72 MHz)
 * Author : Devjeet Mandal   
 * Date   : 13/2/2018       20:27
 * 
 */


 #include "stm32f10x.h"

 #define HPRE_RESET_MASK        ((uint32_t)0xFFFFFF0F)
 #define PPRE2_RESET_MASK       ((uint32_t)0xFFFFC7FF)
 #define PPRE1_RESET_MASK       ((uint32_t)0xFFFFF8FF)
 #define PLLCLK_CONFIG_RESET_MASK   ((uint32_t)0xFFC0FFFF)
 #define SW_RESET_MASK          ((uint32_t)0xFFFFFFFC)


 #define LED_PORT_EN()      ( RCC->APB2ENR |= RCC_APB2ENR_IOPDEN )
 #define LED_PORT           GPIOD

 #define LED_MODE_BIT1          8
 #define LED_MODE_BIT2          9
 #define LED_CNF_BIT1           10
 #define LED_CNF_BIT2           11


 #define CNF_SET_PORTD(BIT1,BIT2)   (   LED_PORT->CRL &= ~((1<<BIT1) | (1<<BIT2)) )                 //General purpose output push-pull
 #define MODE_SET_PORTD(BIT1,BIT2)  ( LED_PORT->CRL |=  (1<<BIT1) | (1<<BIT2) )                     //Output mode, max speed 50 MHz.

 #define SET_GPIO_BIT_PORTD(BIT)    ( LED_PORT->BSRR =  (1 << BIT) )                                            //For setting the Bit   
 #define RESET_GPIO_BIT_PORTD(BIT)  ( LED_PORT->BSRR =  ( (1 << BIT) << 16 )    )                       //For Resseting Bit




 void PLL_Config(void);
 void Clock_Reset(void);
 void HCLK_Config(uint32_t RCC_SYSCLK);
 void PCLK2_Config(uint32_t RCC_HCLK);
 void PCLK1_Config(uint32_t RCC_HCLK);
 void PLLCLK_Config(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul); 
 void SYSCLK_Config(uint32_t RCC_SYSCLKSource);
 void Delay(int ms);
 void Led_Init(void);
 void Blink_Led(int ms);



 int main(void)
 {
     PLL_Config();
     Led_Init();
     while(1)
     {
         Blink_Led(1000);
     }
 }


 /** @breif: For wait and doing nothing i.e for delay
     * @param: delaya time
     * @retVal: None
   */


    void Delay(int ms)
    {
        int i,j; 
        for (i = 0; i < ms; ++i) {
            for (j = 0; j < 1000; ++j);
            }
    }


 /** @breif: Initalize GPIO For Led
     * @param: None
     * @retVal: None
   */


    void Led_Init()
    {
        LED_PORT_EN();          //Enable RCC for Led Port
        CNF_SET_PORTD(LED_CNF_BIT1,LED_CNF_BIT2);   //SET CNF       General purpose output push-pull
        MODE_SET_PORTD(LED_MODE_BIT1,LED_MODE_BIT2); //SET MODE  Output mode, max speed 50 MHz. 
    }


 /** @breif: Blink Led Placed in PORT D Pin 2
     * @param: Delay for each state(ON/OFF)
     * @retVal: None
   */


    void Blink_Led(int ms)
    {
        RESET_GPIO_BIT_PORTD(2);            //Make Led High
        Delay(ms);                          //wait
        SET_GPIO_BIT_PORTD(2);              //Make Led Low
        Delay(ms);                          //wait
    }

 /** @breif: Configure PLL 72 MHz
     * @param: None
     * @retVal: None
   */

 void PLL_Config(void)
 {
     Clock_Reset();                     //RESET Clock
     RCC->CR    |=  RCC_CR_HSEON;       //ENABLE HSE

     /* wait till HSE Ready */
     while ( !( RCC->CR & RCC_CR_HSERDY ));

     /* Doubt: Enable Prefetch Buffer */
   /* Doubt: Flash 2 wait state     */   

     HCLK_Config(RCC_CFGR_HPRE_DIV1);   //configure HCLK  AHB clock
     PCLK2_Config(RCC_CFGR_PPRE2_DIV1); //cofigure PCLK2  APB2 clock
     PCLK1_Config(RCC_CFGR_PPRE1_DIV2); //configure PCLK1 APB1 clock
     PLLCLK_Config(RCC_CFGR_PLLSRC, RCC_CFGR_PLLMULL9); //configure PLLCLK 72MHz

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

     /* Wait till PLL is Ready */
     while (!(RCC->CR & RCC_CR_PLLRDY));

     SYSCLK_Config(RCC_CFGR_SW_PLL);

     /* wait till PLL is used as system clock */
     while (!(RCC->CFGR & RCC_CFGR_SWS_PLL));

 }


 /** @breif: Select PLL as system clock source
     * @param: RCC_CFGR_SW_PLL = ((uint32_t)0x00000002)
     * @retVal: None
   */

 void SYSCLK_Config(uint32_t RCC_SYSCLKSource)
 {
        uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear SW[1:0] bits */
        tmpreg &= SW_RESET_MASK;
        /* Set SW[1:0] bits according to RCC_SYSCLKSource value */
        tmpreg |= RCC_SYSCLKSource;
        /* Store the new value */
        RCC->CFGR = tmpreg;
 }



 /** @breif: Set PCLK1 = HCLK/2
   *         HCLK divided by 2
     * @param: RCC_CFGR_PLLSRC = ((uint32_t)0x00010000)
   * @param: RCC_CFGR_PLLMULL9 = ((uint32_t)0x001C0000)
     * @retVal: None
   */
 void PLLCLK_Config(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul)
 {
      uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
        tmpreg &= PLLCLK_CONFIG_RESET_MASK;
        /* Set the PLL configuration bits */
        tmpreg |= RCC_PLLSource | RCC_PLLMul;
        /* Store the new value */
        RCC->CFGR = tmpreg;
 }


 /** @breif: Set PCLK1 = HCLK/2
   *         HCLK divided by 2
     * @param: RCC_CFGR_PPRE1_DIV2 = ((uint32_t)0x00000400)
     * @retVal: None
   */ 

 void PCLK1_Config(uint32_t RCC_HCLK)
 {
   uint32_t tmpreg = 0;

   tmpreg = RCC->CFGR;
   /* Clear PPRE1[2:0] bits */
   tmpreg &= PPRE1_RESET_MASK;
   /* Set PPRE1[2:0] bits according to RCC_HCLK value */
   tmpreg |= RCC_HCLK;
   /* Store the new value */
   RCC->CFGR = tmpreg;
 }




 /** @breif: Set PCLK2 = HCLK
   *         HCLK not divided
     * @param: RCC_CFGR_PPRE2_DIV1 = ((uint32_t)0x00000000)
     * @retVal: None
   */ 

 void PCLK2_Config(uint32_t RCC_HCLK)
 {
   uint32_t tmpreg = 0;

   tmpreg = RCC->CFGR;
   /* Clear PPRE2[2:0] bits */
   tmpreg &= PPRE2_RESET_MASK;
   /* Set PPRE2[2:0] bits according to RCC_HCLK value */
   tmpreg |= RCC_HCLK;
   /* Store the new value */
   RCC->CFGR = tmpreg;
 }


 /** @breif: Set HCLK = SYSCLK
   *         SYSCLK not divided
     * @param: RCC_CFGR_HPRE_DIV1 = ((uint32_t)0x00000000)
     * @retVal: None
   */

  void HCLK_Config(uint32_t RCC_SYSCLK)
    {
        uint32_t tmpreg = 0;

        tmpreg = RCC->CFGR;
        /* Clear HPRE[3:0] bits */
        tmpreg &= HPRE_RESET_MASK;
        /* Set HPRE[3:0] bits according to RCC_SYSCLK value */
        tmpreg |= RCC_SYSCLK;
        /* Store the new value */
        RCC->CFGR = tmpreg;
    }



 /** @breif: Resets the Clock
     * @param: None
     * @retVal: None
   */
 void Clock_Reset(void)
 {
   /* Set HSION bit */
   RCC->CR |= (uint32_t)0x00000001;

   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
   RCC->CFGR &= (uint32_t)0xF0FF0000;  

   /* Reset HSEON, CSSON and PLLON bits */
   RCC->CR &= (uint32_t)0xFEF6FFFF;

   /* Reset HSEBYP bit */
   RCC->CR &= (uint32_t)0xFFFBFFFF;

   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
   RCC->CFGR &= (uint32_t)0xFF80FFFF;

   /* Disable all interrupts and clear pending bits  */
   RCC->CIR = 0x009F0000;
 }

Dudas:

  1. Al configurar el PLL, vi que había dos líneas "Habilitar búfer de captación previa" y "Estado de espera de Flash 2" que estaba allí en la biblioteca de periféricos estándar. ¿Qué significa esta línea y por qué necesito hacer esto? ¿Cómo afectarán estas líneas a mi configuración de PLL?

  2. Si no configuro el PLL, mi sistema funcionará en 8MHz, es decir, en el cristal provisto a bordo, ¿verdad?

  3. Aquí parpadeo un LED después de configurar PLL. Pero mientras configuramos el LED, necesitamos configurar el MODO, que es "Modo de salida, velocidad máxima de 50 MHz". Según el manual del usuario. Entonces, ¿cómo está afectando mi configuración de PLL el parpadeo del LED? ¿Funciona mi Led a 72MHz o 50MHz?

  4. ¿Este código establece el reloj del sistema en 72MHz? ¿Hay alguna forma fácil de saber a qué frecuencia funciona mi sistema?

Haré Timers y USART después de esto y creo que para eso se requiere la configuración de PLL. Cualquier sugerencia será realmente útil.

Gracias de antemano

    
pregunta Devjeet Mandal

1 respuesta

0

1) El flash no es tan rápido como el procesador, por lo que necesita insertar 'estados de espera' al leerlo. El número requerido depende de qué tan rápido esté ejecutando el procesador. El número que necesita se describe en la sección 3.3.3 Memoria Flash incorporada (página 57) de manual de referencia . El búfer de captación previa es similar a un caché, y captura de antemano algunos flashes para que esté disponible para la CPU sin bloquear para una lectura flash.

2) No necesariamente, se ejecutará en el reloj que lo configuró para ejecutarse en el bloque RCC, el valor predeterminado es un oscilador interno de alta velocidad (creo que 8 MHz en esa parte), para usar un cristal externo que necesite para habilitarlo y esperar a que se estabilice, esto es administrado por el "periférico" del RCC en el IC y se describe en el manual de referencia mencionado anteriormente en la sección del RCC.

3) El 50MHz allí se refiere a la velocidad de conmutación del pin, no al PLL o la velocidad del reloj del sistema. El periférico GPIO se ejecuta desde un reloj separado al procesador, el APB2 clock, que en última instancia se deriva del reloj del sistema y puede funcionar hasta 72 MHz.

4) No he pasado por la configuración de tu PLL muy de cerca, pero hay una discrepancia entre los comentarios y el código en las líneas

PCLK2_Config(RCC_CFGR_PPRE2_DIV1); //cofigure PCLK2  APB2 clock
PCLK2_Config(RCC_CFGR_PPRE1_DIV2); //configure PCLK1 APB1 clock

Ambos están configurando el reloj APB2 , en lugar de configurar APB1 y APB2 .

La forma más fácil de confirmar qué tan rápido está ejecutando es configurar MCO , main clock out para que sea sysclk , y verlo con un osciloscopio.

El manual de referencia es bastante grande y desalentador, pero vale la pena estudiarlo, la mayoría de las preguntas sobre el procesador se pueden responder con él.

    
respondido por el Colin

Lea otras preguntas en las etiquetas