El "Bring-Up" es una fase transitoria. El objetivo de este código no es ser elegante, asíncrono o escalable. El objetivo es que sea estúpido, secuencial e implacable. Si intentas probar el conversor analógico-digital (ADC) dentro de una tarea de FreeRTOS controlada por un temporizador, cuando el valor devuelto sea cero, no sabrás si falló el hardware del sensor, la interrupción del reloj, el mutex del bus, o la asignación de memoria del sistema operativo.
Un ingeniero senior divide la placa (PCBA) y escribe un menú interactivo. Controlarás el STM32 desde el puerto serie de tu computadora portátil (UART CLI - Command Line Interface). Al presionar una tecla, el hardware deberá responder mecánicamente.
printf). A partir de este momento, el microcontrolador "puede hablar".Configuración de Hardware: Asumimos que tienes un adaptador USB-TTL (FTDI) conectado a tu computadora. Conecta el pin TX del adaptador al pin de Depuración UART (ej. PA3/RX) de tu STM32, y el RX del adaptador al PA2/TX. Asegúrate de unificar las tierras (GND).
Escribiremos un Super-Loop. Nada de interrupciones asíncronas complicadas; usaremos HAL_UART_Receive en modo bloqueante con timeout para leer el teclado del ingeniero.
/**
* @file bringup_cli.c
* @brief Interfaz de Línea de Comandos para Diagnóstico de Hardware Cero
*/
#include "stm32f401xe.h"
#include "stm32f4xx_hal.h"
#include <stdio.h>
#include <string.h>
// Manejadores (Handles) inyectados desde la inicialización
extern UART_HandleTypeDef huart2; // UART de Depuración a PC
extern UART_HandleTypeDef huart1; // UART conectado al ESP32
extern ADC_HandleTypeDef hadc1; // ADC del Sensor 4-20mA
// =========================================================================
// RUTINA DE IMPRESIÓN (Redirigir printf a UART2)
// =========================================================================
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE {
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
// =========================================================================
// FUNCIONES DE PRUEBA DE HARDWARE
// =========================================================================
void Test_Relay_Valve(void) {
printf("[*] Activando Relé de la Válvula (Escucha el Click)...\r\n");
// Activa el optoacoplador que diseñamos en el Día 274
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
HAL_Delay(1000); // Mantiene abierto 1 segundo
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
printf("[V] Relé desactivado.\r\n");
}
void Test_ADC_4_20mA(void) {
printf("[*] Leyendo Bucle de Corriente 4-20mA (Día 273)...\r\n");
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
uint32_t adc_value = HAL_ADC_GetValue(&hadc1);
// Conversión rápida a voltaje (Asumiendo VREF=3.3V y 12-bits)
float voltage = ((float)adc_value / 4095.0f) * 3.3f;
// Mapeamos a mA (R_Shunt = 150 Ohms)
float current_mA = (voltage / 150.0f) * 1000.0f;
printf(" - Valor Crudo (12-bit): %lu\r\n", adc_value);
printf(" - Voltaje Calculado: %.2f V\r\n", voltage);
printf(" - Corriente Sensada: %.2f mA\r\n", current_mA);
if(current_mA < 3.5f) {
printf("[!] ADVERTENCIA: < 4mA. Cable Roto o Sensor Desconectado.\r\n");
} else {
printf("[V] Lazo de corriente dentro de rango operativo.\r\n");
}
} else {
printf("[X] ERROR: Fallo de timeout en el hardware ADC.\r\n");
}
HAL_ADC_Stop(&hadc1);
}
void Test_ESP32_Comm(void) {
printf("[*] Enviando comando 'AT' al ESP32 Wi-Fi...\r\n");
uint8_t at_cmd[] = "AT\r\n";
uint8_t rx_buffer[10] = {0};
// Enviar comando al ESP32
HAL_UART_Transmit(&huart1, at_cmd, strlen((char*)at_cmd), 100);
// Esperar respuesta "OK" (Modo bloqueante simple)
HAL_StatusTypeDef status = HAL_UART_Receive(&huart1, rx_buffer, 4, 1000);
if (status == HAL_OK) {
printf("[V] ESP32 Respondió: %s\r\n", rx_buffer);
} else {
printf("[X] ERROR: El ESP32 no responde. Revisa pistas TX/RX.\r\n");
}
}
// =========================================================================
// EL BUCLE PRINCIPAL (SUPER-LOOP DE DIAGNÓSTICO)
// =========================================================================
void BringUp_Menu_Loop(void) {
uint8_t rx_byte;
printf("\r\n======================================\r\n");
printf(" DESPACHADOR GAS LP - BRING-UP MODO \r\n");
printf("======================================\r\n");
printf(" [1] Test Relé (Válvula)\r\n");
printf(" [2] Test Sensor Presión (4-20mA)\r\n");
printf(" [3] Ping ESP32 (UART)\r\n");
printf("======================================\r\n");
while (1) {
printf("> Ingresa comando: ");
// Espera infinita por una tecla del ingeniero
if (HAL_UART_Receive(&huart2, &rx_byte, 1, HAL_MAX_DELAY) == HAL_OK) {
printf("%c\r\n", rx_byte); // Eco
switch (rx_byte) {
case '1': Test_Relay_Valve(); break;
case '2': Test_ADC_4_20mA(); break;
case '3': Test_ESP32_Comm(); break;
case '\r':
case '\n': break; // Ignorar enter
default:
printf("[X] Comando inválido.\r\n");
break;
}
}
}
}
Objetivo del día: Certificación de Capa Física y Abstracción de Hardware (HAL).
Cuando construyas el sistema operativo de tu Despachador (El RTOS de la Fase 6), habrá docenas de tareas corriendo simultáneamente: el Wi-Fi gestionando colas MQTT, el display actualizando el precio del gas, y el caudalímetro calculando masa por segundo. Si en ese caos intentas leer el sensor de 4-20mA y devuelve basura, podrías pasar una semana depurando tu código de gestión de memoria, cuando en realidad el operador en la fábrica soldó la resistencia Shunt de 150 Ohmios al revés (Día 273).
Al implementar el **Bring-Up Code** interactivo, aíslas la física del software. Te sientas frente a la placa pelada, conectas tu adaptador serial y presionas "1". Si la válvula hace *Click*, certificas para siempre que el ruteo de potencia (Día 280), el optoacoplador y los diodos Flyback funcionan físicamente. Si presionas "2" y lees `3.8mA`, sabes que el hardware ADC no tiene puentes de soldadura (Día 288). Solo cuando cada pieza de hardware ha respondido satisfactoriamente a su "Ping" manual, el ingeniero sella la placa, borra el código Bring-Up, y da luz verde para inyectar la arquitectura de software de misión crítica.
printf) hacia un puerto serial (UART) de depuración. Esto permite que el microcontrolador "hable" a un emulador de terminal (como PuTTY o TeraTerm) en la PC del ingeniero.