El STM32 no conecta sus pines directamente al árbitro de interrupciones (NVIC). En medio existe un módulo de hardware llamado EXTI. Su trabajo es vigilar los bordes (flancos) de la señal eléctrica. En lugar de preguntar "¿El botón está en 0V?", el EXTI vigila el instante exacto en que la señal cae de 3.3V a 0V (Flanco de Bajada / Falling Edge).
Un STM32F4 tiene decenas de pines, pero el EXTI solo tiene 16 líneas de interrupción principales (EXTI0 a EXTI15). Todas las familias de pines comparten el mismo número. Es decir, PA0, PB0 y PC0 están atados a la línea EXTI0. Para decirle al EXTI cuál de todos los "Ceros" debe vigilar, usamos el multiplexor SYSCFG (System Configuration Controller).
La ruta de la señal de emergencia será: Pin PA0 ➡️ SYSCFG ➡️ EXTI0 (Filtro de Flanco) ➡️ NVIC (Prioridad 0) ➡️ CPU Cortex-M.
Ejercicio 1: El Botón de Emergencia está conectado al pin PA0 con Pull-Up. En estado normal lee 3.3V. Si el usuario lo golpea, el voltaje cae a 0V. Escribe la inicialización Bare-Metal para configurar el EXTI de forma que atrape ese "Flanco de Bajada" (Falling Edge) y dispare la interrupción de prioridad máxima.
/**
* @file main.c
* @brief Configuración EXTI0 para Paro de Emergencia
*/
#include "stm32f401xe.h"
#include "valve_driver.h" // Nuestra macro VALVULA_OFF()
void configurar_emergencia_exti(void) {
// --- 1. CONFIGURAR EL PIN FÍSICO (PA0) ---
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// PA0 como Entrada con Pull-Up
GPIOA->MODER &= ~GPIO_MODER_MODE0;
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD0;
GPIOA->PUPDR |= GPIO_PUPDR_PUPD0_0;
// --- 2. HABILITAR RELOJ DEL MULTIPLEXOR SYSCFG ---
// A diferencia de los GPIO, el SYSCFG vive en el bus rápido APB2
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
// --- 3. CONECTAR PA0 A EXTI0 ---
// Limpiamos los 4 bits correspondientes a EXTI0 en el registro EXTICR1.
// Un valor de 0000 significa "Conectar al Puerto A".
SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR1_EXTI0;
// --- 4. CONFIGURAR EL MÓDULO EXTI ---
// Desenmascarar la línea 0 (Permitir que la señal pase)
EXTI->IMR |= EXTI_IMR_MR0;
// Deshabilitar disparo por flanco de subida (Rising Edge)
EXTI->RTSR &= ~EXTI_RTSR_TR0;
// Habilitar disparo por flanco de bajada (Falling Edge)
// Se activará en el instante exacto que el pin pase de 3.3V a 0V
EXTI->FTSR |= EXTI_FTSR_TR0;
// --- 5. HABILITAR EN EL ÁRBITRO (NVIC) ---
NVIC_SetPriority(EXTI0_IRQn, 0); // Prioridad de vida o muerte
NVIC_EnableIRQ(EXTI0_IRQn);
}
// --- VECTOR DE INTERRUPCIÓN ---
void EXTI0_IRQHandler(void) {
// 1. Verificamos que realmente fue la línea 0 la que disparó la interrupción
if (EXTI->PR & EXTI_PR_PR0) {
// 2. ACCIÓN CRÍTICA INMEDIATA: Cortar energía a la válvula de Gas LP
VALVULA_OFF();
// 3. Limpiar la bandera pendiente.
// (En el EXTI de ST, se limpia irónicamente escribiendo un '1')
EXTI->PR |= EXTI_PR_PR0;
}
}
int main(void) {
Valvula_Init();
configurar_emergencia_exti();
while(1) {
// El CPU está libre para enviar datos RS485 o actualizar pantallas.
// Si el operador presiona el Paro, la válvula se cerrará por hardware
// en menos de 15 nanosegundos, sin importar qué esté haciendo el main().
}
return 0;
}
Objetivo del día: Seguridad Ciberfísica de Latencia Cero.
Este es el momento en que tu Tesis trasciende de un "código que funciona" a un Dispositivo de Grado Industrial. En sistemas embebidos críticos, no podemos confiar en que la función `main()` tendrá tiempo de revisar el botón. Un error matemático o un bucle infinito en tu cálculo de telemetría podría congelar el sistema entero.
Al implementar el EXTI0 para el botón de emergencia conectado a PA0, hemos delegado la seguridad al hardware físico. La señal eléctrica viaja a la velocidad de la luz hacia el NVIC. El procesador abandona su tarea y ejecuta la macro VALVULA_OFF(). No importa si tu código se congeló calculando decimales; la válvula de alta presión de Gas LP será clausurada físicamente.
PA0, PB0, PC0) comparten la misma línea de interrupción (EXTI0). No puedes tener a PA0 y PB0 generando interrupciones EXTI distintas simultáneamente.IRQHandler, es obligatorio limpiar la bandera (Pending Register - PR). Si no lo haces, el hardware creerá que la interrupción sigue activa y entrarás en un bucle infinito colapsando el procesador.