En el lenguaje C, el tamaño de una variable int no está definido estrictamente; depende de la arquitectura del procesador. Si migras un proyecto de firmware desde una arquitectura de 8 bits (como los microcontroladores Freescale/NXP de la familia S08 o HCS08) hacia un ARM Cortex-M, te enfrentarás a un choque tectónico. En 8 bits, un int suele ocupar 16 bits (límite de 32,767). En tu STM32 de 32 bits, un int ocupa 32 bits (límite de ~2.14 mil millones). Esta discrepancia destroza la portabilidad y causa desbordamientos (*overflows*) silenciosos y letales en los cálculos de facturación.
Para aplicaciones de grado metrológico, imponemos el estándar C99 utilizando <stdint.h>. Eliminamos los tipos primitivos y exigimos precisión absoluta en la asignación de memoria:
| Tipo Estricto | Tamaño | Rango (Sin Signo) | Uso Recomendado en el STM32 |
|---|---|---|---|
| uint8_t | 1 Byte | 0 a 255 | Banderas de estado (Flags), comunicación UART con el ESP32, lectura de botones. |
| uint16_t | 2 Bytes | 0 a 65,535 | Lecturas crudas del ADC (conversor analógico a digital de 12 bits del STM32). |
| uint32_t | 4 Bytes | 0 a 4,294,967,295 | Variables de metrología, temporizadores del RTOS y volumen de gas. Al coincidir con el bus físico del ARM, se procesa en 1 solo ciclo de reloj. |
El despachador maneja dinero ($) y volumen (L). Intuitivamente pensarías en usar float o double (ej. $15.50). Esto está estrictamente prohibido en metrología embebida. Los números de punto flotante en binario sufren de errores de precisión por redondeo IEEE 754 (ej. 15.50 a menudo se almacena como 15.499999). Si tu núcleo Cortex-M3/M4 no tiene FPU (Unidad de Punto Flotante por hardware), el compilador GCC inyectará pesadas librerías de emulación matemática. Esto bloquea la CPU durante cientos de ciclos, destruyendo el determinismo de nuestro RTOS.
La solución es la Matemática de Punto Fijo (Fixed-Point). Representamos todo con enteros puros referenciando a la unidad mínima posible (ej. centavos para dinero y mililitros para volumen).
A nivel físico (PCB), el bus de datos interno del STM32 consta de 32 pistas de silicio. Cuando defines una variable uint32_t, estás utilizando la anchura completa y natural del microcontrolador. Al diseñar tus esquemáticos en KiCad para los conectores del flujómetro (sensor de caudal de gas), debes considerar el ruido. Si un pico de EMI induce un falso pulso, nuestra matemática perfecta facturará ese pulso fantasma. Asegúrate de rutear pistas cortas, incluir un circuito de filtrado RC a la entrada del GPIO y usar aislamiento óptico (optoacopladores) si el sensor está lejos de la placa base.
Ejercicio 1: Crea la base de metrología del main.c. Define las variables globales necesarias utilizando los tipos estrictos de stdint.h y aplica la matemática de punto fijo para evitar los flotantes.
#include <stdint.h>
// --- VARIABLES SEGURAS DE METROLOGÍA ---
// Volatile: Advierte al compilador GCC que esta variable puede ser
// modificada abruptamente por el hardware (una interrupción del Timer/Flujómetro)
// y jamás debe ser omitida en la optimización.
volatile uint32_t pulsos_totales_flujometro = 0;
// Punto Fijo: Multiplicamos los valores reales por un factor de escala.
// Ejemplo: El precio de $11.55 MXN por litro se representa como 1155 centavos.
const uint32_t PRECIO_POR_LITRO_CENTAVOS = 1155;
// Factor K: Cuánto volumen físico representa cada pulso del sensor magnético.
// Ejemplo: 5 mililitros (ml) por pulso.
const uint32_t MILILITROS_POR_PULSO = 5;
/**
* @brief Calcula el costo en tiempo real sin usar punto flotante.
* @return uint32_t Total a cobrar en centavos.
*/
uint32_t metrologia_calcular_cobro_actual(void) {
// 1. Calculamos el volumen extraído usando enteros limpios
uint32_t volumen_actual_ml = pulsos_totales_flujometro * MILILITROS_POR_PULSO;
// 2. Matemática comercial
// Realizamos un 'Cast' temporal a uint64_t internamente para la multiplicación.
// Esto previene un desbordamiento catastrófico si se despacha muchísimo gas,
// lo cual rebasaría el límite de 32 bits antes de la división.
uint64_t subtotal_temporal = (uint64_t)volumen_actual_ml * PRECIO_POR_LITRO_CENTAVOS;
// 3. Normalización: (ml * centavos/L) / 1000 ml = Total en centavos.
uint32_t total_a_pagar_centavos = (uint32_t)(subtotal_temporal / 1000);
// Cuando el ESP32 solicite el total vía UART para enviarlo a la nube IoT,
// le enviaremos 'total_a_pagar_centavos'. El ESP32 simplemente insertará
// el punto decimal por software (ej. 1550 -> "15.50") antes de mostrarlo en la App.
return total_a_pagar_centavos;
}
Hito Logrado: Lógica de Facturación Criptográfica y Determinista.
Al erradicar los flotantes y estandarizar la memoria con stdint.h, garantizas que la placa del despachador facturará hasta el último centavo sin latencia, sin errores de redondeo de silicio, y sin importar si el microcontrolador lleva encendido 5 minutos o 5 años. En auditorías comerciales, la Profeco (o equivalente metrológico) exige precisión perfecta. Hoy has blindado tu firmware contra multas económicas utilizando técnicas puras de ingeniería de software a bajo nivel.
int. Declara #include <stdint.h> como la primera línea de tu código.uint32_t es el tipo de dato de procesamiento más eficiente; no gasta ciclos de instrucción en aplicar "máscaras" de recorte como lo haría al procesar un uint8_t en la ALU.volatile solo en variables modificadas por Interrupciones (ISR) o DMA.float. Implementa siempre Fixed-Point Math manejando la unidad de medida más pequeña necesaria (mililitros, miligramos, centavos).1. Si un operario despacha gas continuamente hasta que la variable `pulsos_totales_flujometro` (si erróneamente la declaramos como `uint16_t`) llega a su máximo valor (65,535), ¿qué sucederá en el pulso 65,536?
Respuesta: Ocurrirá un Desbordamiento (Overflow). Al carecer de más bits físicos, la variable volverá abruptamente a 0. Si esto sucede a la mitad del despacho, el cobro del cliente se reseteará, resultando en pérdidas masivas. Por eso elegimos uint32_t, que permite registrar más de 4,294 millones de pulsos antes de colapsar, dando un inmenso margen de seguridad comercial.