Un array es un bloque contiguo y fijo de memoria. En lugar de declarar Ticket_t t1, t2, t3;, declaras Ticket_t historial[5];. El compilador reserva inmediatamente el espacio exacto para 5 estructuras apiladas una tras otra. El acceso se hace mediante un índice, sabiendo que en el lenguaje C el primer elemento siempre es el índice 0.
En lenguajes de alto nivel (como Python), si intentas guardar un sexto ticket en un historial de 5, el programa lanza una excepción y se detiene. En C Bare-Metal, el procesador obedecerá ciegamente. Escribirá el sexto ticket en el índice [5], sobrescribiendo variables críticas que estén al lado en la memoria (corrupción de memoria RAM), provocando un Hard Fault catastrófico.
Como nuestro despachador operará las 24 horas, generará miles de tickets. Usaremos una técnica llamada Búfer Circular (Ring Buffer). Cuando el índice llega al final del arreglo, utilizamos aritmética modular para que el siguiente ticket sobrescriba al más antiguo (el índice 0). Matemáticamente, el índice se calcula así: $Indice = (Indice + 1) \pmod{MAX}$.
Ejercicio 1: Historial de Tickets. Implementaremos un arreglo global estático para almacenar las últimas 5 transacciones de la máquina. Utilizaremos aritmética modular para proteger el índice.
#include <stdint.h>
#define MAX_TICKETS 5
// 1. DEFINICIÓN DEL MOLDE DE DATOS (STRUCT)
typedef struct {
uint32_t id_transaccion;
uint32_t volumen_ml; // Volumen en punto fijo
uint32_t cobro_c; // Cobro en centavos
} Ticket_t;
// 2. DECLARACIÓN DEL ARREGLO ESTÁTICO Y EL ÍNDICE
// Al usar 'static', encapsulamos este arreglo para que solo este archivo pueda tocarlo.
// El compilador reserva sizeof(Ticket_t) * 5 bytes inmediatamente en la SRAM (.BSS).
static Ticket_t historial_tickets[MAX_TICKETS];
// El índice que nos dirá dónde guardar el próximo ticket
static uint8_t indice_actual = 0;
static uint32_t contador_global_transacciones = 0;
/**
* @brief Guarda un nuevo ticket de despacho en el Búfer Circular.
* @param volumen Volumen final despachado.
* @param cobro Cobro total calculado.
*/
void Guardar_Ticket_Historial(uint32_t volumen, uint32_t cobro) {
// 1. Acceso seguro al índice actual mediante los corchetes [ ]
historial_tickets[indice_actual].id_transaccion = ++contador_global_transacciones;
historial_tickets[indice_actual].volumen_ml = volumen;
historial_tickets[indice_actual].cobro_c = cobro;
// 2. ARITMÉTICA MODULAR (Protección de Memoria)
// El operador módulo (%) devuelve el residuo de una división.
// Ej: 0%5=0, 1%5=1, 2%5=2, 3%5=3, 4%5=4.
// ¡Pero 5%5 = 0! Automáticamente nos devuelve al inicio del arreglo.
indice_actual = (indice_actual + 1) % MAX_TICKETS;
}
/**
* @brief Lee un ticket del historial (Paso por referencia para eficiencia).
* @param posicion La posición deseada (0 a 4).
* @param ptr_destino Puntero a la estructura donde se copiarán los datos.
*/
void Extraer_Ticket(uint8_t posicion, Ticket_t *ptr_destino) {
// 1. Validación estricta para evitar Out-of-Bounds si nos mandan una posición > 4
if (posicion >= MAX_TICKETS || ptr_destino == 0x00) {
return; // Abortar
}
// 2. Copiamos los datos de nuestro arreglo al puntero de destino
ptr_destino->id_transaccion = historial_tickets[posicion].id_transaccion;
ptr_destino->volumen_ml = historial_tickets[posicion].volumen_ml;
ptr_destino->cobro_c = historial_tickets[posicion].cobro_c;
}
Hito Logrado: Implementación de Búfer Circular sin memoria dinámica.
Tu máquina ahora puede recordar el pasado. En un entorno de gasolinera o planta despachadora, si el módulo Wi-Fi (ESP32) pierde conexión a internet durante una venta, el despacho no se pierde. Queda enclavado en este Búfer Circular. Al regresar el internet, el módulo ESP32 puede hacer un *Polling* de los últimos 5 tickets y enviarlos en bloque. Y lo más importante: lo lograste usando cero bytes de memoria dinámica, garantizando que el despachador pueda correr durante años sin requerir reinicios por agotamiento de RAM.
0 y terminan en MAX - 1.%). Ideal para colas de telemetría (FIFO) o históricos cíclicos.