Configuração do Sistema de Relógio RCC no STM32

A configuração do sistema de relógio (RCC - Reset and Clock Control) é uma etapa fundamental no desenvolvimento com microcontroladores STM32. Este guia aborda os passos e considerações para configurar o sistema utilizando os osciladores HSI (High-Speed Internal) e HSE (High-Speed External) como fontes para o PLL (Phase-Locked Loop).

Passos Gerais para Configuração do Relógio

  1. Resetar o controlador RCC para o estado padrão.
  2. Habilitar o oscilador desejado (HSE ou HSI) e aguardar sua estabilização.
  3. Configurar a latência de acesso à memória Flash.
  4. Configurar os divisores dos barramentos AHB e APB.
  5. Configurar a fonte e o fator multiplicador do PLL.
  6. Habilitar o PLL e aguardar sua estabilização.
  7. Comutar a fonte do sistema de relógio (SYSCLK) para a saída do PLL.

Pontos Críticos na Configuração

  • Sequência Obrigatória: A configuração dos parâmetros do PLL (PLLSRC, PLLMUL) deve ser concluída antes de habilitar o PLL. Uma vez que o PLL está habilitado, esses bits não podem ser alterados.
  • Preparação para Alta Velocidade: A configuração da latência da Flash e dos divisores de barramento deve ocorrer antes de comutar para uma fonte de relógio de alta frequência. Isto é crítico porque a Flash pode ter tempos de acesso mais lentos que o ciclo do CPU, e os bararmentos APB possuem limites de frequência (ex.: APB1 máximo de 36 MHz).
  • Estabilidade do PLL: A comutação do SYSCLK para o PLL deve ocorrer apenas após o PLL ter atingido a estabilidade, verificando o sinalizador PLLRDY. Comutar antes pode causar mau funcionamento do sistema.

Exemplo de Configuração Utilizando o HSE (8 MHz)

O exemplo a seguir configura um sistema de relógio de 72 MHz partindo de um cristal externo de 8 MHz, multiplicando-o por 9 via PLL.


#include "stm32f10x.h"

void ConfigurarRelogioHSE(uint32_t fator_multiplicacao)
{
    volatile uint32_t contador_inicializacao = 0;
    volatile uint32_t status_hse = 0;

    // Reinicializa o controlador de relógio
    RCC_DeInit();

    // Habilita o oscilador externo
    RCC_HSEConfig(RCC_HSE_ON);

    // Aguarda o HSE estabilizar ou até o timeout
    status_hse = RCC_WaitForHSEStartUp();

    if (status_hse == SUCCESS)
    {
        // Configura latência da Flash para 2 ciclos de espera (para SYSCLK até 72 MHz)
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        FLASH_SetLatency(FLASH_Latency_2);

        // Configura os divisores de barramento
        RCC_HCLKConfig(RCC_SYSCLK_Div1);   // HCLK = SYSCLK
        RCC_PCLK2Config(RCC_HCLK_Div1);    // PCLK2 = HCLK
        RCC_PCLK1Config(RCC_HCLK_Div2);    // PCLK1 = HCLK / 2 (máx. 36 MHz)

        // Configura o PLL: Fonte = HSE, Fator = fator_multiplicacao
        // Relógio PLL = 8 MHz * fator_multiplicacao (ex: 9 = 72 MHz)
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, fator_multiplicacao);

        // Habilita o PLL
        RCC_PLLCmd(ENABLE);

        // Aguarda até que o PLL esteja travado e estável
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {
            // Espera ativa
        }

        // Comuta a fonte do SYSCLK para o PLL
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        // Verifica se a comutação foi bem-sucedida
        while (RCC_GetSYSCLKSource() != 0x08)
        {
            // Espera ativa
        }
    }
    else
    {
        // Tratamento de erro: HSE não estabilizou.
        // O sistema pode recorrer automaticamente ao HSI como fallback.
        while (1)
        {
            // Trava a execução em caso de falha crítica.
        }
    }
}

Exemplo de Configuração Utilizando o HSI (8 MHz)

A lógica é análoga, mas utiliza o oscilador interno. Note que o HSI de 8 MHz é dividido por 2 internamente antes de entrar no PLL, resultando em uma frequência de referência de 4 MHz.


#include "stm32f10x.h"

void ConfigurarRelogioHSI(uint32_t fator_multiplicacao)
{
    volatile uint32_t status_hsi = 0;

    RCC_DeInit();

    // Habilita o oscilador interno
    RCC_HSICmd(ENABLE);

    // Aguarda a estabilização do HSI
    while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET)
    {
        // Espera ativa
    }
    status_hsi = RCC->CR & RCC_CR_HSIRDY;

    if (status_hsi == RCC_CR_HSIRDY)
    {
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        FLASH_SetLatency(FLASH_Latency_2);

        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        RCC_PCLK1Config(RCC_HCLK_Div2);

        // Configura o PLL: Fonte = HSI / 2, Fator = fator_multiplicacao
        // Relógio PLL = (8 MHz / 2) * fator_multiplicacao (ex: 18 = 72 MHz)
        RCC_PLLConfig(RCC_PLLSource_HSI_Div2, fator_multiplicacao);

        RCC_PLLCmd(ENABLE);

        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {
            // Espera ativa
        }

        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

        while (RCC_GetSYSCLKSource() != 0x08)
        {
            // Espera ativa
        }
    }
    else
    {
        // Tratamento de erro: HSI falhou.
        while (1)
        {
            // Trava a execução.
        }
    }
}

Tags: STM32 RCC Cortex-M HSE HSI

Publicado em 8-2 00:41