DÍA 097 DE 365

Fase 2: Fundamentos de Hardware y Electrónica

📖 Teoría a Estudiar

El Registro IDR y los Pines Flotantes

Para leer el estado eléctrico de un pin en el STM32, la arquitectura ARM nos proporciona el registro IDR (Input Data Register). Es un registro de solo lectura; refleja instantáneamente si el exterior tiene 3.3V (bit en 1) o 0V (bit en 0). Configurar un pin como entrada es tan fácil como escribir 00 en su registro MODER.

Sin embargo, si conectas un botón a un pin de entrada y lo dejas sin presionar, el pin queda desconectado (al aire). En electrónica, un pin al aire se llama Pin Flotante y actúa como una antena de radio miniatura. El ruido electromagnético ambiental hará que el registro IDR lea unos y ceros de manera caótica. Para fijar un estado por defecto, usamos las resistencias internas del registro PUPDR (Pull-Up / Pull-Down).

El Fenómeno del Rebote Mecánico (Bouncing)

Cuando presionas un botón físico de metal, los contactos no se unen mágicamente. Chocan, vibran y rebotan a nivel microscópico durante unos 5 a 20 milisegundos. A 84MHz, el procesador es tan absurdamente rápido que leerá ese rebote como si el usuario hubiera presionado y soltado el botón 50 veces en una fracción de segundo. La solución de ingeniería se llama Anti-Rebote (Debouncing) por Software.

ARQUITECTURA DE ENTRADA: PULL-UP Y REBOTE MECÁNICO STM32 (Hardware Interno) +3.3V Interno ~40 kΩ (PUPDR) IDR Pin Externo GND Físico Señal FÍSICA leída por el registro IDR 3.3V (1) 0V (0) ~10ms (Ruido) Baja estable (Botón Presionado)

⚙️ Ejercicios Prácticos

Ejercicio 1: Escribe una función de lectura Bare-Metal para el Botón de Paro de Emergencia de tu sistema. El botón está conectado al pin PA0 hacia GND (Active LOW). Activa el Pull-Up interno y programa un Debounce por software utilizando retardos bloqueantes básicos para confirmar la pulsación.


/**
 * @file main.c
 * @brief Lectura de Botonera (GPIO Input & Debounce)
 */

#include "stm32f401xe.h"
#include <stdbool.h>

#define BTN_EMERGENCIA_PIN  0   // Pin PA0

void inicializar_boton_entrada(void) {
    // 1. Habilitar reloj para GPIOA
    RCC->AHB1ENR |= (1 << 0);
    
    // 2. Configurar PA0 como ENTRADA DIGITAL (MODER = 00)
    // Limpiamos los bits [1:0] para asegurarnos de que quede en '00'
    GPIOA->MODER &= ~(3 << (BTN_EMERGENCIA_PIN * 2));
    
    // 3. Activar Resistencia Interna PULL-UP (PUPDR = 01)
    // Evita que el pin flote. Al no apretar el botón, leeremos un '1'.
    GPIOA->PUPDR &= ~(3 << (BTN_EMERGENCIA_PIN * 2)); // Limpiar
    GPIOA->PUPDR |=  (1 << (BTN_EMERGENCIA_PIN * 2)); // Setear a '01'
}

// Retardo de software bloqueante (Aprox milisegundos a 84MHz)
void delay_ms(uint32_t ms) {
    for (volatile uint32_t i = 0; i < (ms * 14000); i++);
}

// Función para leer el botón filtrando el rebote mecánico
bool leer_boton_emergencia_seguro(void) {
    
    // 1. Leer el registro IDR. Como usamos Pull-Up y el botón va a GND, 
    // la lógica está invertida (Active LOW). Si el bit es 0, está presionado.
    if ((GPIOA->IDR & (1 << BTN_EMERGENCIA_PIN)) == 0) {
        
        // 2. Retardo Anti-Rebote (Debounce)
        // Pausamos el CPU durante 20ms para dejar que los contactos de metal
        // terminen de vibrar físicamente.
        delay_ms(20);
        
        // 3. Confirmación
        // Volvemos a leer. Si después de 20ms SIGUE en estado bajo, 
        // fue una pulsación real y no un pico de ruido.
        if ((GPIOA->IDR & (1 << BTN_EMERGENCIA_PIN)) == 0) {
            return true; // ¡Emergencia confirmada!
        }
    }
    
    return false; // No hay pulsación
}

int main(void) {
    
    inicializar_boton_entrada();
    
    while (1) {
        
        if (leer_boton_emergencia_seguro() == true) {
            // Entrar en secuencia de corte de válvulas de gas
            // fsm_estado_emergencia();
            
            // Atrapamos al código para evitar múltiples activaciones
            while((GPIOA->IDR & (1 << BTN_EMERGENCIA_PIN)) == 0);
            delay_ms(20); // Anti-rebote al soltar el botón
        }
        
    }
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Interfaz Humano-Máquina (HMI) con tolerancia a fallos.

El Paro de Emergencia ("Seto" rojo) de tu máquina expendedora es el componente de seguridad de vida principal de tu diseño. Al configurarlo en modo Active LOW con Pull-Up interno, logramos un principio de seguridad industrial llamado Fail-Safe (Fallo Seguro): si por accidente se rompe el cable mecánico entre el botón de la carcasa y tu placa de circuito impreso, el procesador detectará un estado alto continuo ('1'). Para activarlo se requiere cerrar deliberadamente el circuito hacia Tierra ('0').

Además, al incorporar la subrutina de Debounce por software (con ese retardo matemático de 20ms), aseguras que la vibración natural de los motores de la planta no genere falsos positivos en el registro IDR de tu chip. Tu código C acaba de sobreponerse a las limitaciones mecánicas del hardware metálico.

📝 Resumen del Día