DÍA 034 DE 365

Fase 1: Fundamentos de C y Lógica de Software

📖 Teoría Explícita: Anatomía de un Hardware Timer

Un temporizador (Timer) es esencialmente un contador digital alimentado por el reloj del sistema. Para evitar que cuente a la asombrosa velocidad de decenas de millones de veces por segundo, utilizamos un Prescaler (PSC), que divide la frecuencia del reloj principal, y un Auto-Reload Register (ARR), que define el límite al que debe llegar el contador antes de reiniciarse y generar una interrupción.

Cálculo Matemático

La frecuencia con la que un Timer genera una interrupción (Update Event) está dada por la siguiente fórmula:

$$ f_{update} = \frac{f_{clk}}{(PSC + 1) \times (ARR + 1)} $$

Ejemplo Práctico: Supongamos que nuestro microcontrolador corre a $f_{clk} = 84 \text{ MHz}$ y queremos una interrupción exacta cada 1 milisegundo ($f_{update} = 1000 \text{ Hz}$).

  1. Despejamos el denominador: $(PSC + 1) \times (ARR + 1) = \frac{84,000,000}{1000} = 84,000$.
  2. Elegimos un valor arbitrario para el prescaler que nos facilite la vida. Si hacemos $PSC = 83$, entonces $(PSC + 1) = 84$.
  3. Calculamos el ARR: $84 \times (ARR + 1) = 84,000 \implies ARR + 1 = 1000 \implies ARR = 999$.

Al programar el Timer con un `Prescaler = 83` y un `Period (ARR) = 999`, el microcontrolador invocará nuestro código exactamente cada 1 milisegundo, sin importar qué tan saturado esté el bucle principal.

FLUJO DEL HARDWARE TIMER (1 ms INTERRUPT) SYSCLK 84 MHz PRESCALER PSC = 83 (Divide entre 84) 1 MHz COUNTER (CNT) ARR = 999 0 a 999 TIM_IRQ 1 kHz (1ms)

⚡ Asignación en el Hardware

Este temporizador es 100% interno; no requiere componentes externos. Sin embargo, su precisión es fundamental para orquestar la lectura de periféricos y generar retroalimentación (como emitir un beep en un buzzer).

Periférico (MCU) Configuración de Registros Función Principal
TIM2 (Timer Interno 32-bit) PSC = 83, ARR = 999 Base de tiempo (Tick) determinista de 1 milisegundo.
NVIC (Controlador de Interrupciones) Prioridad Media (Ej. Preemption = 2) Atender la ISR de TIM2 sin bloquear el flujómetro (EXTI).

⚙️ Código C: Configuración e Interrupción del Timer

A continuación se muestra el esqueleto de inicialización (basado en la abstracción HAL de STM32) y la rutina de interrupción (ISR) que actuará como nuestro "metrónomo" del sistema.


#include <stdint.h>
#include <stdbool.h>

// --- 1. VARIABLES GLOBALES DE TIEMPO ---
volatile uint32_t sistema_ms = 0;
volatile bool flag_scan_teclado = false;

// --- 2. CONFIGURACIÓN DEL TIMER (Concepto basado en HAL STM32) ---
void TIM2_Configuracion_1ms(void) {
    /* 
     * Asumiendo un reloj principal (SystemCoreClock) de 84 MHz.
     * F_Update = 84,000,000 / ((PSC + 1) * (ARR + 1))
     * F_Update = 84,000,000 / (84 * 1000) = 1,000 Hz = 1 ms
     */
     
    // htim2.Instance = TIM2;
    // htim2.Init.Prescaler = 84 - 1;       // PSC = 83
    // htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    // htim2.Init.Period = 1000 - 1;        // ARR = 999
    // htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    // htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    
    // HAL_TIM_Base_Init(&htim2);
    // HAL_TIM_Base_Start_IT(&htim2); // Iniciar timer con interrupciones
}

// --- 3. RUTINA DE INTERRUPCIÓN (ISR) DE HARDWARE ---
/**
 * @brief  Esta función es llamada por el hardware exactamente cada 1 ms.
 *         IMPORTANTE: El código aquí debe ser extremadamente rápido y no usar retardos.
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {
        sistema_ms++; // Incrementa nuestro propio Tick confiable
        
        // Cada 10 milisegundos, levantamos una bandera para escanear hardware externo
        if (sistema_ms % 10 == 0) {
            flag_scan_teclado = true;
        }
    }
}

// --- 4. BUCLE PRINCIPAL ---
int main(void) {
    // Inicialización del Hardware y Relojes
    TIM2_Configuracion_1ms();
    
    while(1) {
        // Ejecución condicional basada en el tiempo preciso del Hardware Timer
        if (flag_scan_teclado) {
            flag_scan_teclado = false; // Bajar bandera
            
            // Llamar rutina I2C para consultar periféricos
            // (Ej: HMI / Teclado)
        }
        
        // Resto de la Máquina de Estados...
    }
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Sincronización Determinista del HMI.

El uso de un Hardware Timer cambia por completo la confiabilidad de tu Despachador. Ahora tienes una base de tiempo de 1 ms inquebrantable. Esta precisión es exactamente lo que necesitas para interactuar con la placa del teclado 4x4 capacitivo que diseñaste en KiCad. Al establecer un flag cada 10 milisegundos dentro de la interrupción del Timer, garantizas que las líneas I2C del teclado se escaneen a un ritmo perfecto y predecible, evaluando los umbrales de tacto (touch) en la placa de circuito impreso sin bloquear ni afectar en lo absoluto el conteo de los pulsos del flujómetro ni las matemáticas del sistema.

📝 Resumen del Día

❓ Cuestionario de Autoevaluación

1. Si la frecuencia de tu reloj principal cambia a 72 MHz (como en un STM32F103) y mantienes el ARR en 999 para generar interrupciones de 1 ms, ¿cuál debe ser el nuevo valor del Prescaler (PSC)?
Respuesta: El nuevo divisor total debe ser 72,000 para llegar a 1,000 Hz. Dado que $ (PSC+1) \times 1000 = 72,000 $, entonces $ PSC+1 = 72 $. El valor a programar en el registro del Prescaler será 71.