DÍA 045 DE 365

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

📖 Teoría Explícita: Integridad de Datos y CRC

1. La Insuficiencia del Parity Bit y Sum Checksum

Históricamente, los sistemas usaban un "Bit de Paridad" que contaba si había una cantidad par o impar de unos en el byte. Si el ruido industrial voltea dos bits simultáneamente, la paridad falla silenciosamente. Luego se inventó el Sum Checksum (sumar todos los bytes), pero si un byte suma +2 y otro -2 por la interferencia, el total es el mismo y el error pasa inadvertido.

2. El Poder del CRC (Cyclic Redundancy Check)

El estándar industrial absoluto es el CRC. En lugar de sumar, trata todo el paquete de datos como un número binario gigante y lo divide entre un divisor fijo llamado Polinomio Generador. El residuo de esa división (módulo 2, mediante operaciones XOR y Shifts) es el CRC. Para un CRC-8, el polinomio típico matemático se expresa como $P(x) = x^8 + x^2 + x + 1$ (representado en hexadecimal como 0x07). Este método detecta el 100% de los errores de ráfaga comunes en entornos electromecánicos ruidosos.

3. Arquitectura del Comando con Firma

Para aplicar esto a nuestra UART, el remitente (ESP32) calcula el CRC de la cadena y lo anexa al final como una firma hexadecimal. El receptor (STM32) calcula el CRC del mismo payload; si su cálculo coincide con la firma, el dato es perfecto. Si no, se descarta todo y se solicita retransmisión.

ARQUITECTURA DE VALIDACIÓN CRC-8 REMITENTE (Módulo Wi-Fi) "AT+PRECIO=1150" Motor CRC-8 "AT+PRECIO=1150*A3" EMI / RUIDO RECEPTOR (STM32) Recibe Trama Calcular CRC A3 == A3? OK

⚙️ Ejercicios Prácticos: C Puro Sin Librerías

Ejercicio 1: Programa una función ultra-optimizada en C que reciba un puntero a una cadena y su longitud, y devuelva el checksum CRC-8. Utilizaremos el polinomio 0x07, ejecutando el algoritmo bit a bit utilizando operadores lógicos exclusivos (XOR) y desplazamientos (Bit-Shifting).


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

// --- 1. MOTOR MATEMÁTICO CRC-8 (Polinomio 0x07) ---
/**
 * @brief Calcula el Cyclic Redundancy Check de un buffer de datos.
 * @param datos Puntero al inicio del payload.
 * @param longitud Cantidad de bytes a evaluar.
 * @return El byte único de firma (CRC-8).
 */
uint8_t Calcular_CRC8(const uint8_t *datos, uint16_t longitud) {
    uint8_t crc = 0x00; // Valor inicial estándar
    
    // Iteramos por cada byte del buffer
    for (uint16_t i = 0; i < longitud; i++) {
        
        // El nuevo byte hace XOR con el residuo actual
        crc ^= datos[i];
        
        // Procesamos el byte bit por bit (8 iteraciones)
        for (uint8_t bit = 0; bit < 8; bit++) {
            
            // Si el bit más significativo (MSB) es 1
            if (crc & 0x80) {
                // Desplazamos a la izquierda y hacemos XOR con el Polinomio (0x07)
                crc = (crc << 1) ^ 0x07;
            } else {
                // Solo desplazamos a la izquierda
                crc = (crc << 1);
            }
        }
    }
    
    return crc;
}

// --- 2. APLICACIÓN EN EL PARSER DEL DESPACHADOR ---
// Simulación de un buffer recibido: "AT+PRECIO=1150*5A\0"
// Donde '*' es el separador, y '5A' es el CRC hexadecimal que calculó el ESP32.

extern uint8_t Convertir_HexASCII_a_Byte(char char_alto, char char_bajo); // Helper hipotético

bool Validar_Trama_Segura(char* buffer_uart) {
    uint16_t len = 0;
    
    // Encontrar el separador de firma '*'
    while(buffer_uart[len] != '*' && buffer_uart[len] != '\0') {
        len++;
    }
    
    // Si no hay firma, rechazamos el paquete por seguridad industrial
    if (buffer_uart[len] != '*') {
        return false; 
    }
    
    // Calcular el CRC localmente SOLO del payload (antes del '*')
    // Ojo al cast: Pasamos el buffer de char a uint8_t para matemática binaria.
    uint8_t crc_calculado = Calcular_CRC8((const uint8_t *)buffer_uart, len);
    
    // Extraemos el CRC que dice haber enviado el ESP32 (los dos bytes tras el '*')
    uint8_t crc_recibido = Convertir_HexASCII_a_Byte(buffer_uart[len+1], buffer_uart[len+2]);
    
    // Veredicto final:
    return (crc_calculado == crc_recibido);
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Inmunidad Electromagnética en Comunicaciones.

El estándar de metrología exige que la placa base sea inmune a la interferencia. Si la bomba de 220V arranca, el campo magnético puede alterar las señales 3.3V del cable UART. Si recibes la orden remota AT+CIERRE_VALVULA, pero llega como AT+CIERRE_XALVULA, tu parser (Día 42) no la reconocerá y la bomba seguirá encendida. Al forzar que el ESP32 anexe un CRC-8 a cada orden, tu STM32 detectará el bit volteado en una fracción de milisegundo mediante Calcular_CRC8(), descartará la orden corrupta y pedirá un reintento a la velocidad de la luz. Estás elevando tu firmware al Nivel Industrial (SIL - Safety Integrity Level).

📝 Resumen del Día

❓ Cuestionario de Autoevaluación

1. ¿Por qué usamos el operador XOR (^) en lugar de una suma normal (+) al combinar los bytes en el algoritmo CRC?
Respuesta: La suma tradicional genera "acarreo" (carry) que se propaga a los bits superiores, lo que destruiría la naturaleza cíclica del algoritmo en campos finitos. La compuerta XOR es la base de la aritmética de Galois (GF(2)), equivalente a una suma sin acarreo, que garantiza una dispersión perfecta de los errores sin desbordar el tamaño de la variable de 8 bits.