DÍA 019 DE 365

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

📖 Teoría Explícita: El Overhead de sprintf

La familia de funciones printf/sprintf de la librería estándar de C (stdio.h) es sumamente compleja. Debe ser capaz de procesar múltiples argumentos variables (va_list), buscar patrones de texto especiales (como %d, %f, %s) en tiempo de ejecución, y a menudo enlaza soporte para números flotantes en el ejecutable, incluso si solo estás imprimiendo enteros.

ANÁLISIS DE OVERHEAD: SPRINTF vs CUSTOM ITOA sprintf() 12,500 Bytes (Flash) + Alto Riesgo de Stack Overflow Custom itoa() ~150 Bytes (Flash) | Ejecución determinista 0 KB Memoria Consumida

⚡ Interfaz UART al ESP32

En el circuito, el STM32 se comunica con el ESP32 a través del puerto serie (UART). Ambos operan a 3.3V, por lo que puedes conectar TX a RX de manera directa sin conversores de nivel. El despachador debe enviarle al módulo de IoT las tramas de los totales para la nube. Haremos esto empaquetando bytes manualmente.

⚙️ Ejercicios Prácticos: Conversión a ASCII

Vamos a construir una función simple que tome el total en centavos que calculamos ayer y lo convierta a una cadena de caracteres legible sin sprintf.


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

// --- Prototipo de envío UART simulado ---
void UART_Transmit(const char* data);

/**
 * @brief Convierte un entero (centavos) a cadena de texto con formato monetario.
 *        Evita el uso de sprintf para ahorrar ciclos de CPU y Flash.
 * @param centavos El total a convertir (ej. 21008 = $210.08)
 * @param buffer Arreglo donde se guardará el resultado (mínimo 16 bytes)
 */
void formatear_precio_ascii(uint32_t centavos, char* buffer) {
    char temp[16];
    int i = 0;
    
    // Si el valor es cero, manejarlo directamente
    if (centavos == 0) {
        buffer[0] = '$'; buffer[1] = '0'; buffer[2] = '.';
        buffer[3] = '0'; buffer[4] = '0'; buffer[5] = '\0';
        return;
    }
    
    // 1. Extraer los dígitos de derecha a izquierda (módulo 10)
    // El dígito ASCII se obtiene sumando '0' (0x30 en hexadecimal)
    while (centavos > 0) {
        temp[i++] = (centavos % 10) + '0';
        centavos /= 10;
        
        // Agregar el punto decimal al tener 2 dígitos extraídos (centavos)
        if (i == 2) {
            temp[i++] = '.';
        }
    }
    
    // Si el valor era menor a 1 peso (ej. 8 centavos -> .08)
    if (i == 2) { temp[i++] = '.'; temp[i++] = '0'; }
    if (i == 3 && temp[2] == '.') { temp[i++] = '0'; }
    
    // 2. Invertir la cadena y añadir el prefijo de moneda
    int j = 0;
    buffer[j++] = '$';
    
    while (i > 0) {
        buffer[j++] = temp[--i];
    }
    
    // Null-terminator obligatorio en C
    buffer[j] = '\0'; 
}

// Integración con el cálculo de ayer
void enviar_venta_esp32(uint32_t importe_centavos) {
    char tx_buffer[20];
    formatear_precio_ascii(importe_centavos, tx_buffer);
    
    // Envío por hardware directo
    UART_Transmit(tx_buffer); 
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Al desterrar `sprintf` de tu firmware, has asegurado que la memoria RAM disponible para FreeRTOS sea abundante y predecible. Ahora, cada tarea (como la de las válvulas y el botón de emergencia) tiene su propio stack libre de amenazas. Tu código es más rápido y cumple con principios de arquitectura Bare-Metal industrial.

📝 Resumen del Día