En el corazón de la ALU de un procesador Cortex-M o MC9S08, el valor 15450 es simplemente una cadena de bits. Si ese valor representa litros con tres cifras de precisión (escala de 1000), el punto decimal es solo un requerimiento visual de la Interfaz Humano-Máquina (HMI). Matemáticamente, podemos separar este número en dos componentes enteros utilizando divisiones y residuos.
Dado un valor total $V$ y una escala decimal base $10^n$, podemos fragmentar la cifra sin tocar la memoria dinámica:
A partir de aquí, solo debemos armar el Arreglo de Caracteres en reversa, inyectando el símbolo '.' exactamente después de iterar la parte fraccionaria.
Ejercicio 1: Crea la función formatear_punto_fijo, capaz de tomar un número entero en bruto y convertirlo a un arreglo de caracteres (String) insertando el punto decimal según el nivel de precisión requerido (ej. 3 decimales para Litros, 2 para Moneda).
#include <stdint.h>
// --- 1. FUNCIÓN AUXILIAR DE INVERSIÓN (Del Día 20) ---
void reverse_string(char* str, uint8_t length) {
uint8_t start = 0;
uint8_t end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
// --- 2. EL MOTOR DE PUNTO FIJO A TEXTO ---
void formatear_punto_fijo(uint32_t valor_crudo, uint8_t num_decimales, char* buffer) {
uint8_t i = 0;
uint32_t divisor = 1;
// Calcular el divisor base 10 (ej. 3 decimales -> divisor = 1000)
for(uint8_t d = 0; d < num_decimales; d++) {
divisor *= 10;
}
// Fragmentación del número
uint32_t parte_entera = valor_crudo / divisor;
uint32_t parte_frac = valor_crudo % divisor;
// A) Procesar la parte fraccionaria extrayendo dígitos inversamente
for(uint8_t d = 0; d < num_decimales; d++) {
buffer[i++] = (parte_frac % 10) + '0';
parte_frac /= 10;
}
// B) INYECCIÓN DEL PUNTO COSMÉTICO
if(num_decimales > 0) {
buffer[i++] = '.';
}
// C) Procesar la parte entera
if (parte_entera == 0) {
buffer[i++] = '0';
} else {
while (parte_entera > 0) {
buffer[i++] = (parte_entera % 10) + '0';
parte_entera /= 10;
}
}
// D) Sellado con Terminador Nulo
buffer[i] = '\0';
// E) Rotar el arreglo a la posición humana legible
reverse_string(buffer, i);
}
// --- SIMULACIÓN DEL SÚPER BUCLE ---
int main(void) {
char buffer_display[16];
// Volumen: 15.450 Litros
uint32_t volumen_sensor = 15450;
formatear_punto_fijo(volumen_sensor, 3, buffer_display);
// Dinero: $290.45 Pesos
uint32_t costo_calculado = 29045;
formatear_punto_fijo(costo_calculado, 2, buffer_display);
return 0;
}
Objetivo del día: HMI Determinista y Ligera.
Al erradicar la función sprintf y construir tu propia lógica de formateo, has recuperado incontables ciclos de reloj en tu microcontrolador y ahorrado Kilobytes en la memoria Flash. El despachador de grado industrial requiere actualizar la pantalla LCD y emitir tramas por UART hacia el módulo telemetría constantemente. Con esta arquitectura, la conversión de los datos de metrología es tan rápida que no afectará tus tiempos de sondeo de los sensores de presión críticos.
/) y módulos (%) permite desfragmentar un entero de 32 bits de manera eficiente.1. ¿Qué ocurriría si intentamos formatear un valor de dinero de 29005 centavos con 2 decimales usando este algoritmo?
Respuesta: El algoritmo funciona a la perfección. La parte fraccionaria es 5. En el primer ciclo del bucle fraccionario extrae '5'. Luego 5 / 10 = 0. En el segundo ciclo extrae 0 % 10 = 0, por lo que inserta '0'. Inyecta el punto. Luego procesa 290 de la parte entera. Al invertirse todo, el buffer dice correctamente 290.05, demostrando que los ceros a la izquierda de la fracción se respetan.