Una estructura (struct) asigna memoria independiente para cada uno de sus miembros. Si tiene un entero de 4 bytes y un arreglo de 4 bytes, el compilador reserva 8 bytes en total. Una unión (union), por el contrario, hace que todos sus miembros compartan exactamente la misma dirección de memoria física. El tamaño total de la unión será simplemente el tamaño de su miembro más grande.
Al solapar un arreglo de bytes (uint8_t[4]) sobre un entero grande (uint32_t), creamos un traductor instantáneo. Cuando la interrupción del UART recibe un byte, lo guardamos en la posición [0] del arreglo. Cuando llega el segundo, en la [1]. Al finalizar, no requerimos sumar ni desplazar nada; simplemente leemos la variable uint32_t y la CPU nos devolverá el número ensamblado. Es una operación de cero ciclos de sobrecarga.
El Bit-shifting es universal, pero las Uniones revelan cómo el silicio organiza sus datos físicamente. Los procesadores ARM Cortex-M (STM32, NXP) son Little-Endian. Esto significa que almacenan el byte "menos significativo" (LSB) en la dirección de memoria más baja (el índice [0]). Si el ESP32 transmite los datos en formato Big-Endian, tu unión leerá el precio al revés. Es imperativo que transmisor y receptor acuerden el orden de los bytes.
Ejercicio 1: Crea una unión que superponga un arreglo de 4 bytes con un entero de 32 bits. Simularemos la llegada de una actualización de precios por UART (1 byte a la vez) y leeremos el resultado final instantáneamente.
#include <stdint.h>
#include <stdbool.h>
// --- 1. DEFINICIÓN DE LA UNIÓN BARE-METAL ---
typedef union {
uint32_t precio_actualizado; // Vista A: Un solo bloque de 32 bits
uint8_t buffer_uart[4]; // Vista B: Cuatro bloques de 8 bits
} Conversor_Trama_t;
// Variable global que almacena el precio operativo del gas (en centavos)
volatile uint32_t precio_gas_lp = 1850; // $18.50 por defecto
// Instancia de nuestra unión
Conversor_Trama_t rx_payload;
uint8_t bytes_recibidos = 0;
// --- 2. SIMULADOR DE INTERRUPCIÓN UART (Recepción byte por byte) ---
// En el hardware real, esta función es disparada por el periférico USART
// cada vez que un byte nuevo entra al pin RX.
void USART_Rx_Callback(uint8_t byte_entrante) {
// Guardamos el byte directamente en el arreglo interno de la unión.
// Asumimos que el ESP32 envía los datos en formato Little-Endian
// (primero envía el LSB, luego los demás).
if (bytes_recibidos < 4) {
rx_payload.buffer_uart[bytes_recibidos] = byte_entrante;
bytes_recibidos++;
}
// Cuando llegan exactamente 4 bytes, el paquete está completo
if (bytes_recibidos == 4) {
// ¡LA MAGIA DE LA UNIÓN!
// No hay que hacer desplazamientos (<<) ni operaciones OR (|).
// Simplemente leemos la otra "cara" de la unión.
// La memoria RAM ya está ensamblada.
precio_gas_lp = rx_payload.precio_actualizado;
// Reiniciamos el contador para la próxima trama
bytes_recibidos = 0;
}
}
// --- 3. SÚPER BUCLE ---
int main(void) {
// Simulación de los bytes llegando desde el ESP32 (Little-Endian)
// Queremos configurar el precio a 1999 centavos ($19.99).
// 1999 en hexadecimal es 0x000007CF.
// En Little Endian se envía al revés: CF, 07, 00, 00
USART_Rx_Callback(0xCF); // Byte 0
USART_Rx_Callback(0x07); // Byte 1
USART_Rx_Callback(0x00); // Byte 2
USART_Rx_Callback(0x00); // Byte 3
// A partir de esta línea, 'precio_gas_lp' vale matemáticamente 1999.
// La CPU no gastó ciclos convirtiéndolo.
while(1) {
// Lógica metrológica operando con el nuevo precio...
}
return 0;
}
Objetivo del día: Recepción y parseo de configuraciones sin penalización de CPU.
Cuando diseñas un sistema industrial, el procesador (STM32 o Kinetis) debe estar 100% concentrado en contar los pulsos del caudalímetro y vigilar el paro de emergencia. Si la interrupción del puerto serial detiene el procesador para hacer matemáticas complejas de reconstrucción cada vez que el ESP32 envía una actualización, arriesgas la precisión metrológica (Jitter). Al usar una union, delegas el trabajo de ensamblaje a la propia arquitectura del silicio. Es literal e instantáneo.
structs (cuyo tamaño es la suma de sus partes), el tamaño de una unión lo define su miembro más grande.