DÍA 093 DE 365

Fase 2: Fundamentos de Hardware y Electrónica

📖 Teoría a Estudiar

El Árbol de Relojes y el Módulo RCC

A diferencia de un Arduino que corre ciegamente a 16MHz porque tiene un cristal soldado fijo en la placa, un microcontrolador industrial ARM Cortex-M tiene un Árbol de Reloj (Clock Tree) completamente programable. El módulo encargado de gobernar esto es el RCC (Reset and Clock Control).

Al encender (Power-on Reset), el STM32 arranca usando un oscilador de silicio muy básico dentro del chip llamado HSI (High-Speed Internal) que oscila a 16MHz. Es lento pero seguro. Si queremos exprimir los 84MHz que el procesador es capaz de alcanzar, necesitamos activar un bloque de hardware mágico llamado PLL (Phase-Locked Loop).

El Multiplicador PLL

El PLL es un circuito analógico/digital que toma una frecuencia de entrada y la multiplica. Funciona a través de divisores (prescalers) matemáticos: M, N y P. La fórmula para nuestra arquitectura es:

SYSCLK = (Entrada / M) * N / P

Además de acelerar el procesador (SYSCLK), el RCC divide esta frecuencia troncal en ramas secundarias para no quemar periféricos lentos. Estas ramas son los buses AHB (para memoria), APB1 (para UARTs y Timers lentos) y APB2 (para SPI de alta velocidad).

ARQUITECTURA DEL ÁRBOL DE RELOJ (STM32F4) HSI (16 MHz) HSE (8 MHz) MUX Multiplicador PLL / M * N / P fVCO = (In / 16) * 336 / 4 = 84MHz SYS AHB 84 MHz SYSCLK APB2 SPI/UART (84MHz) APB1 I2C (Max 42MHz) /2 Div

Latencia de la Memoria Flash (Wait States)

Hay un gran obstáculo físico: el CPU puede correr a 84MHz, pero la memoria Flash interna (donde vive tu código) solo puede entregar datos a un máximo aproximado de 24MHz a 30MHz (dependiendo del voltaje). Si el CPU exige instrucciones a 84MHz, leerá basura. Para evitarlo, debemos configurar Wait States (Latencia) en el módulo FLASH antes de acelerar, ordenándole al procesador que espere un par de ciclos de reloj al leer la memoria.

⚙️ Ejercicios Prácticos

Ejercicio 1: Crea la función maestra configurar_reloj_84MHz(). Usaremos el cristal interno HSI (16MHz) para no depender de componentes externos. Lo pasaremos por el PLL para alcanzar la velocidad de operación industrial exigida por nuestro Despachador.


#include "stm32f401xe.h"

void configurar_reloj_84MHz(void) {
    
    // 1. LATENCIA DE FLASH (Wait States)
    // Para 84MHz a 3.3V, el datasheet exige 2 Wait States (Latencia = 2)
    FLASH->ACR &= ~FLASH_ACR_LATENCY;      // Limpiamos los bits de latencia
    FLASH->ACR |= FLASH_ACR_LATENCY_2WS;   // Seteamos a 2 Wait States
    
    // 2. CONFIGURAR EL PLL
    // Desactivamos el PLL primero para poder modificar sus multiplicadores
    RCC->CR &= ~RCC_CR_PLLON;
    while(RCC->CR & RCC_CR_PLLRDY); // Esperamos a que se apague completamente
    
    // Fórmula: fSYSCLK = (fHSI / PLLM) * PLLN / PLLP
    // Queremos: (16MHz / 16) * 336 / 4 = 84MHz
    
    // Limpiamos los bits M, N, P y la fuente del PLL
    RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLSRC);
    
    // Configuramos: Fuente = HSI, M = 16, N = 336, P = 4 (P se codifica como '01' para valor 4)
    RCC->PLLCFGR |= (16 << RCC_PLLCFGR_PLLM_Pos) | 
                    (336 << RCC_PLLCFGR_PLLN_Pos) | 
                    (1 << RCC_PLLCFGR_PLLP_Pos);
                    
    // 3. ENCENDER EL PLL Y ESPERAR ESTABILIDAD (Lock)
    RCC->CR |= RCC_CR_PLLON;
    while(!(RCC->CR & RCC_CR_PLLRDY)); // El hardware avisa cuando la fase está sincronizada
    
    // 4. CONFIGURAR PRESCALERS DE BUSES (AHB y APB)
    // El bus APB1 (lento) soporta máximo 42MHz, lo dividimos entre 2
    RCC->CFGR &= ~(RCC_CFGR_PPRE1);
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
    
    // 5. CONMUTAR SYSCLK AL PLL
    // Le decimos al multiplexor maestro que cambie del HSI lento al PLL rápido
    RCC->CFGR &= ~RCC_CFGR_SW;
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    
    // 6. VALIDAR CONMUTACIÓN
    // Esperamos que el hardware confirme el cambio de fuente de reloj
    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}

int main(void) {
    
    // Despertamos como un Arduino a 16MHz...
    // Invocamos el acelerador Bare-Metal:
    configurar_reloj_84MHz();
    
    // ¡A partir de esta línea, estamos corriendo a 84 millones de ciclos por segundo!
    
    while(1) {
        // Lógica metrológica 
    }
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Sincronización Temporal de Alto Rendimiento.

Para controlar un flujo industrial, el tiempo lo es todo. Tu Despachador utiliza el protocolo Modbus RTU para enviar los litros vendidos por el RS485 que ruteamos en días anteriores. Modbus RTU es implacable con el tiempo: si el procesador se retrasa 1.5 caracteres de tiempo (unos pocos microsegundos) el paquete completo es descartado por ruido.

Al dominar el registro RCC->PLLCFGR y forzar a tu CPU a correr a unos vertiginosos 84MHz mediante el Oscilador Interno (HSI), aseguras que tus interrupciones y cálculos de PID térmico se ejecuten de manera instantánea, sin depender de un frágil cristal externo de cuarzo que podría romperse con las vibraciones de la bomba mecánica del camión repartidor. Esta es la arquitectura de un sistema de alta fiabilidad.

📝 Resumen del Día