Em sistemas baseados no microcontrolador STM32, redirecionar funções de saída padrão como printf para uma porta serial permite a depuração em tempo real através de um terminal ou software de monitoramento. Este processo envolve a modificação de funções da biblioteca C padrão para que a saída seja enviada via UART em vez do console padrão.
Verificação da porta serial
Para confirmar que a comunicação serial está funcional, envie um comando como *IDN?\r\n para o microcontrolador usando um software de debug serial. Ao receber os dados, o buffer de recepção deve exibir os bytes corretos. Se o dispositivo responder com uma string como "123" dentro da rotina de interrupção de recepção, a porta serial (por exemplo, USART4) está operando corretamente.
Problemas com printf no MDK-ARM
Ao utilizar a função printf no ambiante de desenvolvimento MDK-ARM, é necessário redirecionar a saída padrão e desabilitar o modo Semihosting. Por padrão, as funções da biblioteca C apontam para dispositivos de saída do host, como o monitor do computador. Para enviar a saída para uma porta serial ou display, a função fputc deve ser redefinida.
Exemplo de redirecionamento de fputc para UART1:
#ifdef __GNUC__
#define SAIDA_CARACTERE int __io_putchar(int caractere)
#else
#define SAIDA_CARACTERE int fputc(int caractere, FILE *arquivo)
#endif
SAIDA_CARACTERE
{
USART_SendData(USART2, (uint8_t) caractere);
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
return caractere;
}
Soluções para desabilitar o Semihosting
O Semihosting é um mecanismo que permite que o microcontrolador comunique-se com o host durante a depuração, redirecionando operações de I/O. No entanto, ele interfere no redirecionamento de printf. Para solucionar isso, existem duas abordagens principais:
1. Usar a MicroLIB
Ativar a MicroLIB nas configurações do projeto (Target → Code Generation → Use MicroLIB) evita a inclusão de código Semihosting, simplificando o redirecionamento.
2. Adicionar código para desabilitar Semihosting manualmente
Inclua as seguintes diretivas e definições no código:
#pragma import(__use_no_semihosting)
struct __FILE
{
int manipulador;
// Estrutura necessária para evitar chamadas Semihosting
};
FILE __stdout;
// Definir _sys_exit() para prevenir o uso do modo Semihosting
void _sys_exit(int codigo)
{
codigo = codigo; // Evitar avisos do compilador
}
// Redefinir fputc para UART2, assumindo que USART2 é a porta desejada
int fputc(int caractere, FILE *arquivo)
{
USART2->DR = (uint8_t) caractere;
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
return caractere;
}
Papel do Semihosting
O Semihosting é um mecanismo que permite que código em execução no microcontrolador utilize os recursos de I/O do host, como teclado e tela, através de um depurador. Isso é útil durante o desenvolvimento, pois evita a necessidade de hardware adicional para entrada e saída. No entanto, ele substitui as rotinas padrão de I/O, tornando necessário o redirecionamento explícito de funções como printf quando se deseja saída via serial.
Resumo da implementação
Para habilitar o uso de printf em um STM32 com saída via UART:
- Redirecione a função
fputcpara enviar caracteres pela porta serial desejada. - Desabilite o Semihosting usando a MicroLIB ou código adicional para evitar conflitos.
- Garanta que a definição de
__stdoute__stdinesteja correta para o ambiente.
Em projetos com múltiplas portas UART, certifique-se de que a redirecionamento aponte para a porta correta (por exemplo, USART1 em vez de USART3) para evitar travamentos. Adicione sempre sequências de fim de linha como \r\n ao usar printf para formatação adequada no terminal.