Los microcontroladores modernos tienen una etapa de poder interna (PWR). Dentro de ella habita el PVD, un comparador analógico de hardware conectado directamente a la línea de alimentación principal (VDD). Cuando el suministro eléctrico normal (ej. 3.3V) empieza a caer debido a un apagón, no desaparece instantáneamente a 0V; desciende gradualmente como una resbaladilla mientras los capacitores de la placa se descargan.
El PVD nos permite establecer un umbral (por ejemplo, 2.8V). Si VDD cruza ese umbral hacia abajo, el PVD levanta inmediatamente una bandera interna que está cableada de fábrica a la línea EXTI16 (Interrupción Externa 16).
Para escribir en la memoria EEPROM SPI, necesitamos unos 5 milisegundos. Si detectamos la caída de voltaje a los 2.8V, y el procesador muere cuando el voltaje llega a 2.0V, necesitamos que el voltaje tarde por lo menos 5ms en caer de 2.8V a 2.0V. ¿Cómo logramos esto? Diseñando la PCB de tu Despachador con un Capacitor Bulk (Capacitor Electrolítico masivo) en la entrada de energía. Este capacitor actuará como un "tinaco de agua" que mantendrá el chip vivo los milisegundos suficientes para que ejecute su "última voluntad".
Ejercicio 1: El PVD pertenece al bloque de Power Control (PWR). Primero debes habilitar su reloj. Luego configuraremos el umbral en 2.8V (Nivel 5 o PLS=101) y habilitaremos su línea en el bloque EXTI. En la interrupción, llamaremos a la rutina de escritura SPI desarrollada en el Día 120.
/**
* @file pvd_safety.c
* @brief Configuración del Detector de Voltaje y Guardado de Emergencia
*/
#include "stm32f401xe.h"
// Dependencia del Día 120 (SPI EEPROM)
extern void guardar_respaldo_antiapagones(void);
void inicializar_pvd_emergencia(void) {
// 1. HABILITAR RELOJ DE POTENCIA (PWR)
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// 2. CONFIGURAR UMBRAL DE VOLTAJE DEL PVD
// El registro CR del bloque PWR tiene los bits PLS (PVD Level Selection)
// Para STM32F4: PLS = 101 (Valor 5) corresponde a un umbral Falling ~2.8V
PWR->CR &= ~PWR_CR_PLS;
PWR->CR |= (5 << PWR_CR_PLS_Pos);
// 3. HABILITAR EL SENSOR PVD
PWR->CR |= PWR_CR_PVDE;
// ====================================================
// 4. CONFIGURAR LA INTERRUPCIÓN (EXTI16)
// ====================================================
// El hardware del PVD está cableado internamente a la Línea EXTI 16.
// Desenmascarar la línea 16 para permitir la interrupción.
EXTI->IMR |= EXTI_IMR_MR16;
// Habilitar la detección de Flanco de Subida (Rising Edge) del PVD.
// OJO: Cuando el voltaje CAE por debajo del umbral, la señal lógica
// del PVD SUBE a 1. Por lo tanto, necesitamos Rising Edge.
EXTI->RTSR |= EXTI_RTSR_TR16;
// 5. CONFIGURAR PRIORIDAD MÁXIMA EN EL NVIC
// Esta es una interrupción de vida o muerte. Debe interrumpir todo lo demás.
// Le asignamos la Prioridad 0 (La más alta posible).
NVIC_SetPriority(PVD_IRQn, 0);
NVIC_EnableIRQ(PVD_IRQn);
}
// --- VECTOR DE INTERRUPCIÓN DE VIDA O MUERTE ---
void PVD_IRQHandler(void) {
// 1. Verificar si la línea EXTI16 disparó la alarma
if (EXTI->PR & EXTI_PR_PR16) {
// 2. ¡EL VOLTAJE ESTÁ CAYENDO CRÍTICAMENTE!
// Ejecutamos la "Última Voluntad": Guardar la transacción en la EEPROM.
// Como configuramos el SPI a 5 Megabits, enviar los comandos tomará
// unos pocos microsegundos, y la EEPROM tardará ~5ms en quemar los datos.
guardar_respaldo_antiapagones();
// 3. (Opcional) Forzar el apagado de válvulas para evitar que se
// queden atascadas en una zona lineal indeseada durante la caída de VDD.
// VALVULA_OFF();
// 4. Limpiar la bandera para no entrar en un bucle mientras el procesador muere
EXTI->PR |= EXTI_PR_PR16;
}
}
int main(void) {
// 1. Inicializar periféricos base (Relojes, SPI, Válvulas, EXTI)
// inicializar_spi1();
// 2. Activar la vigilancia de energía
inicializar_pvd_emergencia();
while(1) {
// Ejecutar las tareas de telemetría y metrología.
// Ya no necesitas guardar en EEPROM a cada segundo y desgastar la memoria.
// Los datos viven libres en la RAM, y solo se queman en silicio
// cuando el apocalipsis eléctrico es detectado.
}
return 0;
}
Objetivo del día: Preservación de Vida Útil de Memoria y Tolerancia a Fallos de Red.
Un ingeniero novato actualizaría la EEPROM tras despachar cada litro para asegurarse de no perder la venta. Pero con un Write Endurance de 100,000 ciclos, una estación de gas muy concurrida destruiría la memoria del chip en menos de 8 meses, requiriendo un cambio de tarjeta madre y causando pérdidas enormes a la empresa.
Al implementar el **PVD (Programmable Voltage Detector)** en tu Tesis, acabas de multiplicar la vida útil de tu memoria al infinito. La venta de gas evoluciona exclusivamente en la memoria RAM. Si alguien corta los cables del poste de luz a la mitad del despacho, el voltaje bajará de 3.3V a 2.8V. En ese nanosegundo, la línea `EXTI16` grita, el núcleo ARM Cortex-M pausa el main(), escupe la estructura de venta por el puerto SPI hacia la EEPROM, y muere tranquilo. Tu electrónica y código han colaborado para salvar a la empresa de una pérdida económica sin desgastar el hardware.