<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>STM32F411 - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/stm32f411/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Wed, 10 Dec 2025 16:46:34 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://mcu.tec.br/wp-content/uploads/2025/02/Robo-para-o-site-MCU.tec_.br-512x512-1-150x150.png</url>
	<title>STM32F411 - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Usando o Sensor Interno de Temperatura do STM32F411</title>
		<link>https://mcu.tec.br/microcontroladores/stm32/usando-o-sensor-interno-de-temperatura-do-stm32f411/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=usando-o-sensor-interno-de-temperatura-do-stm32f411</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Wed, 10 Dec 2025 16:46:30 +0000</pubDate>
				<category><![CDATA[Periféricos]]></category>
		<category><![CDATA[STM32]]></category>
		<category><![CDATA[ADC interno]]></category>
		<category><![CDATA[ADC1_IN16]]></category>
		<category><![CDATA[CubeMX]]></category>
		<category><![CDATA[HAL]]></category>
		<category><![CDATA[leitura de temperatura]]></category>
		<category><![CDATA[MCU.TEC.BR]]></category>
		<category><![CDATA[sensor interno de temperatura]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[STM32F411]]></category>
		<category><![CDATA[telemetria térmica]]></category>
		<category><![CDATA[temperatura interna MCU]]></category>
		<category><![CDATA[tutorial STM32]]></category>
		<category><![CDATA[UART]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=996</guid>

					<description><![CDATA[<p>Este artigo ensina passo a passo como ler a temperatura interna do microcontrolador STM32F411 utilizando o ADC e o sensor térmico embutido, configurados através do STM32CubeMX. Você aprenderá como habilitar o canal interno ADC1_IN16, ajustar corretamente o tempo de amostragem, aplicar as fórmulas oficiais da ST para converter o valor bruto do ADC em graus Celsius e enviar o resultado pela UART para monitoramento em terminal serial. O conteúdo é ideal para estudantes, profissionais e entusiastas de sistemas embarcados que desejam implementar telemetria térmica ou compreender melhor o funcionamento interno do STM32F4. O tutorial é claro, didático e totalmente aplicado.</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/usando-o-sensor-interno-de-temperatura-do-stm32f411/">Usando o Sensor Interno de Temperatura do STM32F411</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h3 class="wp-block-heading"><strong>Introdução ao Sensor Interno de Temperatura</strong></h3>



<p class="wp-block-paragraph">Os microcontroladores da família <strong>STM32F4</strong>, incluindo o <strong>STM32F411</strong>, possuem um sensor interno de temperatura capaz de medir a temperatura do chip (junction temperature). Esse recurso é extremamente útil em sistemas embarcados que exigem monitoramento térmico, proteção contra sobreaquecimento, calibração térmica de ADC ou simplesmente coleta de telemetria para diagnóstico.</p>



<p class="wp-block-paragraph">É importante destacar que este sensor não é pensado como um termômetro ambiental de alta precisão. Ele mede a temperatura interna do silício e sua calibração depende de constantes fornecidas pela ST no banco de dados do próprio microcontrolador. Ainda assim, quando configurado corretamente, oferece leituras estáveis e suficientemente precisas para aplicações de controle interno.</p>



<p class="wp-block-paragraph">Neste artigo, vamos desenvolver um projeto completo para <strong>ler a temperatura interna do STM32F411</strong>, usando o <strong>STM32CubeMX</strong> para gerar a configuração base, o <strong>HAL ADC</strong> para realizar a aquisição e, por fim, exibiremos a temperatura em <strong>graus Celsius</strong> através da <strong>porta serial (UART)</strong> padrão.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading"><strong>Configurando o ADC e o Sensor de Temperatura no STM32CubeMX</strong></h1>



<p class="wp-block-paragraph">A configuração do sensor interno de temperatura no <strong>STM32F411</strong> começa pela ativação correta do <strong>ADC1</strong>, que é o periférico responsável por ler o canal dedicado ao sensor térmico. O CubeMX torna esse processo mais intuitivo ao apresentar as opções de forma gráfica, porém alguns detalhes técnicos são essenciais para garantir uma leitura precisa.</p>



<p class="wp-block-paragraph">O sensor de temperatura do STM32 está ligado ao canal <strong>ADC1_IN16</strong> (temperature sensor chanel), um canal especial que não se conecta a nenhum pino físico do microcontrolador. Para habilitá-lo, abra o CubeMX, crie um novo projeto selecionando a placa ou o microcontrolador STM32F411, e navegue até a aba de configuração dos ADCs. É necessário habilitar o ADC1 e marcar o canal interno correspondente ao sensor térmico. Além disso, como esse canal depende da estabilidade de referência interna, é imprescindível ativar o <strong>Temperature Sensor</strong> dentro das opções internas do ADC.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="793" height="697" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-27.png" alt="" class="wp-image-997" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-27.png 793w, https://mcu.tec.br/wp-content/uploads/2025/12/image-27-300x264.png 300w, https://mcu.tec.br/wp-content/uploads/2025/12/image-27-768x675.png 768w" sizes="(max-width: 793px) 100vw, 793px" /></figure>



<p class="wp-block-paragraph">Ainda no CubeMX, habiliter o <strong>continuous conversion mode</strong>, caso você deseje atualização contínua de temperatura, ou manter o modo simples de conversão por software, ideal para monitoramento periódico.</p>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img decoding="async" width="525" height="241" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-28.png" alt="" class="wp-image-998" style="width:427px;height:auto" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-28.png 525w, https://mcu.tec.br/wp-content/uploads/2025/12/image-28-300x138.png 300w" sizes="(max-width: 525px) 100vw, 525px" /></figure>
</div>


<p class="wp-block-paragraph">Depois da configuração do ADC, configure uma <strong>UART</strong> (geralmente USART2) para permitir o envio das leituras para o computador. Defina velocidade, pinos e parâmetros tradicionais de comunicação. Por fim, gere o código automaticamente via CubeMX. O projeto estará pronto para receber a lógica de cálculo da temperatura e impressão via UART. Veja como fazer no artigo: <a href="https://mcu.tec.br/microcontroladores/stm32/como-ler-e-escrever-dados-pela-uart-no-stm32f411re-guia-completo-com-stm32cubemx/" title="Como Ler e Escrever Dados pela UART no STM32F411RE: Guia Completo com STM32CubeMX">Como Ler e Escrever Dados pela UART no STM32F411RE: Guia Completo com STM32CubeMX</a> </p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading"><strong>Seção 3 — Cálculo da Temperatura em Graus Celsius e Código em C (HAL)</strong></h1>



<p class="wp-block-paragraph">Com o projeto gerado pelo CubeMX, o próximo passo é transformar o valor bruto do ADC em uma leitura de temperatura em graus Celsius. O STM32F411 fornece constantes de calibração na memória do sistema que permitem calcular a temperatura interna com boa precisão. A fórmula geral utilizada pela ST é:</p>



<p class="wp-block-paragraph">\[<br>T(°C) = \left(\frac{V_{\text{sense}} &#8211; V_{25}}{\text{Avg_Slope}}\right) + 25<br>\]



<p class="wp-block-paragraph">Onde:</p>



<ul class="wp-block-list">
<li><strong>Vsense</strong> é a tensão lida no canal do sensor de temperatura.</li>



<li><strong>V25</strong> é o valor de Vsense quando o chip está a 25°C (valor fornecido pela ST, geralmente 0,76V).</li>



<li><strong>Avg_Slope</strong> é a inclinação média da curva do sensor (típico 2,5 mV/°C).</li>
</ul>



<p class="wp-block-paragraph">Como o ADC trabalha por amostragem digital, calcula-se Vsense usando:</p>



<p class="wp-block-paragraph">\[<br>V_{\text{sense}} = \frac{\text{ADC_Value} \times V_{\text{ref}}}{4095}<br>\]



<p class="wp-block-paragraph">Em que:</p>



<ul class="wp-block-list">
<li><strong>ADC_Value</strong> é o valor lido do ADC.</li>



<li><strong>Vref</strong> é a tensão de referência do ADC, tipicamente 3,3V.</li>



<li><strong>4095</strong> corresponde à resolução de 12 bits do ADC.</li>
</ul>



<p class="wp-block-paragraph">Após esse cálculo, basta aplicar a fórmula principal para obter a temperatura real. No firmware, essa operação deve ocorrer sempre após uma conversão válida do ADC.</p>



<p class="wp-block-paragraph">A seguir apresento um exemplo completo em C usando HAL, incluindo a aquisição do ADC e a impressão da temperatura via UART:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "main.h"
#include &lt;stdio.h>

extern ADC_HandleTypeDef hadc1;
extern UART_HandleTypeDef huart2;

float read_internal_temperature(void) {
    uint32_t raw = 0;
    float Vsense, temperature;

    // Inicia a conversão ADC
    HAL_ADC_Start(&amp;hadc1);
    HAL_ADC_PollForConversion(&amp;hadc1, HAL_MAX_DELAY);
    raw = HAL_ADC_GetValue(&amp;hadc1);

    // Converte leitura para tensão
    Vsense = (raw * 3.3f) / 4095.0f;

    // Aplica fórmula da ST
    const float V25 = 0.76f;
    const float Avg_Slope = 0.0025f; // 2.5 mV/°C

    temperature = ((Vsense - V25) / Avg_Slope) + 25.0f;

    return temperature;
}

void print_temperature(void) {
    char buffer&#91;64&#93;;
    float temp = read_internal_temperature();

    snprintf(buffer, sizeof(buffer), "Temperatura Interna: %.2f C\r\n", temp);
    HAL_UART_Transmit(&amp;huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">main.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdio</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">extern</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ADC_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">hadc1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">extern</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">UART_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">huart2</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">read_internal_temperature</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Vsense</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temperature</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Inicia a conversão ADC</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_ADC_Start</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">hadc1</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_ADC_PollForConversion</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">hadc1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_ADC_GetValue</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">hadc1</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Converte leitura para tensão</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">Vsense</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> 3</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">3</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> 4095</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Aplica fórmula da ST</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> V25 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">76</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> Avg_Slope </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0025</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 2.5 mV/°C</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">temperature</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> ((</span><span style="color: #D8DEE9">Vsense</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">V25</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Avg_Slope</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> 25</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temperature</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">print_temperature</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buffer</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">64</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">read_internal_temperature</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">snprintf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">buffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">buffer</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Temperatura Interna: %.2f C</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temp</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">buffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">buffer</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Com essa função, basta chamá-la dentro do <code>while(1)</code> de sua aplicação:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>while (1) {
    print_temperature();
    HAL_Delay(1000); // 1 segundo entre leituras
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">print_temperature</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_Delay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 1 segundo entre leituras</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse código fornece a temperatura interna do microcontrolador e a envia pela UART configurada no CubeMX, permitindo visualização direta no terminal serial do computador.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading"><strong>Exibindo a Temperatura na Porta Serial e Testando o Sistema</strong></h1>



<p class="wp-block-paragraph">Com o ADC e a UART configurados no CubeMX e o código de leitura implementado, o próximo passo é garantir que a <strong>temperatura interna</strong> seja exibida corretamente na <strong>saída serial padrão</strong> (por exemplo, <code>USART2</code>, ligada ao conversor USB–Serial da sua placa de desenvolvimento).</p>



<p class="wp-block-paragraph">No CubeMX, normalmente a UART usada como “console” é a <strong>USART2</strong>, configurada como <strong>Asynchronous</strong>, com parâmetros típicos: <strong>115200 bps</strong>, 8 bits de dados, 1 stop bit, sem paridade e sem controle de fluxo. Esses ajustes devem ser reproduzidos no software terminal do PC (PuTTY, minicom, screen, TeraTerm etc.). Certifique-se também de selecionar a <strong>porta COM</strong> correta (no Linux, algo como <code>/dev/ttyUSB0</code> ou <code>/dev/ttyACM0</code>).</p>



<p class="wp-block-paragraph">No firmware, ao chamar periodicamente a função <code>print_temperature()</code> dentro do laço principal, a cada segundo (ou intervalo definido por você) será enviada uma linha de texto pelo UART com a leitura atual. Ao abrir o terminal no computador, você deverá ver algo como:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Temperatura Interna: 32.45 C
Temperatura Interna: 32.62 C
Temperatura Interna: 32.80 C
...
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Temperatura</span><span style="color: #D8DEE9FF"> Interna</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">32.45</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span></span>
<span class="line"><span style="color: #D8DEE9">Temperatura</span><span style="color: #D8DEE9FF"> Interna</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">32.62</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span></span>
<span class="line"><span style="color: #D8DEE9">Temperatura</span><span style="color: #D8DEE9FF"> Interna</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">32.80</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span></span>
<span class="line"><span style="color: #81A1C1">...</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">É normal que a temperatura interna seja superior à temperatura ambiente, pois o próprio núcleo do microcontrolador se aquece com a execução do código. Para testar o comportamento, você pode tocar o dedo sobre o encapsulamento do microcontrolador ou usar uma fonte de calor moderada (como a aproximação da mão ou um leve fluxo de ar quente) e observar a variação gradual dos valores.</p>



<p class="wp-block-paragraph">Caso não apareça nada no terminal, verifique:</p>



<ul class="wp-block-list">
<li>Se a <code>HAL_UART_Transmit</code> está usando o mesmo <code>UART_HandleTypeDef</code> configurado no CubeMX.</li>



<li>Se o <code>SystemClock_Config()</code> está correto (clock interferindo no baud rate).</li>



<li>Se o cabo USB está funcionando e a porta serial foi reconhecida pelo sistema operacional.</li>



<li>Se a função de leitura do ADC está sendo chamada corretamente e o projeto não está preso em interrupções ou em <code>Error_Handler()</code>.</li>
</ul>



<p class="wp-block-paragraph">Uma vez validada a comunicação, você passa a ter uma <strong>telemetria térmica básica</strong> do STM32F411, que pode ser integrada a outras rotinas, logs ou mecanismos de proteção térmica.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading"><strong>Seção 5 — Boas Práticas, Conclusão e Materiais de SEO</strong></h1>



<p class="wp-block-paragraph">O sensor interno de temperatura do STM32F411 é uma ferramenta valiosa para monitoramento térmico de sistemas embarcados. Apesar de não substituir sensores externos de alta precisão, oferece uma forma simples e eficiente de acompanhar variações internas, auxiliar em algoritmos de proteção, calibração térmica ou levantamento de diagnóstico. Uma boa prática importante é sempre considerar que a leitura térmica interna sofre influências da carga de processamento, clock, periféricos ativos e dissipação geral do encapsulamento. Por isso, quando o objetivo for avaliação absoluta de temperatura, recomenda-se aplicar curvas de calibração próprias ou ajustes empíricos baseados em testes de bancada.</p>



<p class="wp-block-paragraph">Outro ponto relevante é a escolha de tempos adequados de amostragem no ADC. O sensor térmico da ST exige tempos de conversão maiores do que canais analógicos comuns devido à natureza interna do sinal. Utilizar tempos muito curtos pode introduzir ruído ou leituras inconsistentes. Além disso, lembre-se de que o cálculo da temperatura depende de valores típicos fornecidos no datasheet. Alguns microcontroladores possuem valores de calibração únicos gravados em memória, o que pode melhorar ainda mais a precisão se utilizados corretamente.</p>



<p class="wp-block-paragraph">O envio da leitura pela UART, como apresentado no artigo, permite integrar o microcontrolador a sistemas de log, análise ou monitoramento remoto. Isso é particularmente útil em laboratórios, projetos educacionais e sistemas mais complexos, como servidores embarcados, drones, sensores industriais e robôs autônomos. Ao dominar essa técnica, você abre caminho para implementar lógica adaptativa baseada em temperatura — como redução de clock, acionamento de ventilação, alarmes e muito mais.</p>



<p class="wp-block-paragraph">Com essas práticas, o desenvolvedor ganha autonomia e visão clara do comportamento térmico interno do STM32F411. Esse conhecimento fortalece a segurança e a confiabilidade dos sistemas embarcados, alinhando-se aos padrões profissionais do mercado e às necessidades de projetos robustos.</p><p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/usando-o-sensor-interno-de-temperatura-do-stm32f411/">Usando o Sensor Interno de Temperatura do STM32F411</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">996</post-id>	</item>
		<item>
		<title>Como Redirecionar o printf para a UART no STM32F411: Um Guia Completo para Debug Serial</title>
		<link>https://mcu.tec.br/linguagem/c/como-redirecionar-o-printf-para-a-uart-no-stm32f411-um-guia-completo-para-debug-serial/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-redirecionar-o-printf-para-a-uart-no-stm32f411-um-guia-completo-para-debug-serial</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Sat, 06 Dec 2025 22:08:24 +0000</pubDate>
				<category><![CDATA[Algoritimos]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[STM32]]></category>
		<category><![CDATA[__io_putchar() STM32]]></category>
		<category><![CDATA[_write() STM32]]></category>
		<category><![CDATA[debug embarcado]]></category>
		<category><![CDATA[debug serial STM32]]></category>
		<category><![CDATA[HAL UART Transmit]]></category>
		<category><![CDATA[microcontroladores ARM]]></category>
		<category><![CDATA[Nucleo F411]]></category>
		<category><![CDATA[printf UART]]></category>
		<category><![CDATA[redirecionar printf STM32]]></category>
		<category><![CDATA[RTT SEGGER]]></category>
		<category><![CDATA[STM32CubeIDE UART]]></category>
		<category><![CDATA[STM32F411]]></category>
		<category><![CDATA[SWO ITM debug]]></category>
		<category><![CDATA[transmissão serial STM32]]></category>
		<category><![CDATA[tutorial STM32 UART]]></category>
		<category><![CDATA[UART debug]]></category>
		<category><![CDATA[USART2 STM32]]></category>
		<category><![CDATA[Virtual COM Port ST-LINK]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=964</guid>

					<description><![CDATA[<p>Este tutorial apresenta um guia completo, didático e detalhado sobre como redirecionar a função printf para a UART no microcontrolador STM32F411, utilizando a placa Nucleo e o ambiente STM32CubeIDE. Explicamos desde a configuração inicial da USART2, o funcionamento da Virtual COM Port (VCP) do ST-LINK, até a implementação da função _write() para capturar a saída de printf e transmiti-la via porta serial. Inclui também recomendações práticas, cuidados com bufferização, técnicas de debug, alternativas como ITM/SWO e RTT, além de exemplos de código e validação com terminal serial no PC. Ideal para estudantes, desenvolvedores e engenheiros que desejam aprimorar a depuração em sistemas embarcados usando STM32.</p>
<p>The post <a href="https://mcu.tec.br/linguagem/c/como-redirecionar-o-printf-para-a-uart-no-stm32f411-um-guia-completo-para-debug-serial/">Como Redirecionar o printf para a UART no STM32F411: Um Guia Completo para Debug Serial</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h3 class="wp-block-heading">Por que redirecionar o <code>printf</code> para a UART?</h3>



<p class="wp-block-paragraph">Durante o desenvolvimento de firmware para STM32, uma das formas mais simples e eficazes de entender o comportamento do código é imprimir mensagens de log: valores de variáveis, estados de máquina de estados, mensagens de erro, etc. Em ambientes embarcados, não temos um “console” como no PC, então precisamos escolher um canal físico para transportar essas mensagens. A forma mais comum, simples e robusta é usar uma UART (porta serial) ligada ao computador do desenvolvedor.</p>



<p class="wp-block-paragraph">Na placa de prototipação <strong>Nucleo STM32F411</strong> (por exemplo, NUCLEO-F411RE), o próprio <strong>ST-LINK</strong> já oferece uma <strong>porta serial virtual (Virtual COM Port – VCP)</strong>. Quando você conecta a placa via USB ao PC, além da interface de debug SWD, é criada uma porta serial (como <code>COMx</code> no Windows ou <code>/dev/ttyACMx</code> no Linux). Essa porta está conectada internamente a um dos periféricos UART do microcontrolador (tipicamente <strong>USART2</strong>, pinos <code>PA2/PA3</code>), permitindo que tudo o que for enviado por essa UART apareça em um terminal serial no computador.</p>



<p class="wp-block-paragraph">O artigo da ST sobre redirecionar o <code>printf</code> para uma UART segue justamente essa ideia: em vez de mandar o <code>printf</code> para o “stdout” abstrato, fazemos com que a função de baixo nível que o <code>printf</code> usa internamente envie cada caractere pela UART, por meio da função <code>HAL_UART_Transmit()</code>. Em muitos exemplos oficiais da ST, isso é feito definindo um macro do tipo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">ifdef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">__GNUC__</span></span>
<span class="line"><span style="color: #D8DEE9FF">  #</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PUTCHAR_PROTOTYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">__io_putchar</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ch</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #D8DEE9FF">  #</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PUTCHAR_PROTOTYPE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">fputc</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ch</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FILE</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">endif</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">e depois implementando essa função para transmitir o caractere pela UART configurada. (<a href="https://gist.github.com/fdelbos/1cf987d75f2954a11161a18c943e2d67">Gist</a>)</p>



<p class="wp-block-paragraph">No contexto da <strong>Nucleo STM32F411</strong>, isso significa que, depois de configurarmos corretamente a UART no STM32CubeIDE (por exemplo, <code>USART2</code> a 115200 bps, 8N1), qualquer chamada a <code>printf("Hello, world!\r\n");</code> no código C passará a sair pela porta USB da placa, aparecendo no seu terminal serial. Isso elimina a necessidade de ficar alternando LEDs, pausando com breakpoints, ou usando ferramentas mais complexas de trace apenas para ver valores simples.</p>



<p class="wp-block-paragraph">Neste tutorial, vamos seguir uma abordagem estruturada, inspirada no procedimento descrito pela ST e em exemplos de comunidade:</p>



<ol class="wp-block-list">
<li><strong>Entender a UART e o VCP da Nucleo STM32F411</strong> – quais pinos estão envolvidos, como a UART é ligada ao ST-LINK e à porta USB no PC.</li>



<li><strong>Criar e configurar o projeto no STM32CubeIDE</strong> – habilitando a UART correta e os clocks necessários.</li>



<li><strong>Implementar o redirecionamento do <code>printf</code></strong> – adicionando o macro <code>PUTCHAR_PROTOTYPE</code> e a função que chama <code>HAL_UART_Transmit()</code>.</li>



<li><strong>Ajustar o buffer e o comportamento do <code>printf</code></strong> – explicando questões como <code>setvbuf()</code>, uso de <code>\n</code>/<code>\r</code> e possíveis travamentos.</li>



<li><strong>Testar com um terminal serial no PC</strong> – configurando o terminal, verificando a comunicação e mostrando um exemplo de sessão de debug.</li>



<li><strong>Boas práticas e limitações</strong> – impacto em tempo de execução, alternativas (ITM/SWO, semihosting, logs condicionais, etc.).</li>
</ol>


<div class="wp-block-image">
<figure class="alignright size-full"><img decoding="async" width="433" height="472" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-8.png" alt="" class="wp-image-965" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-8.png 433w, https://mcu.tec.br/wp-content/uploads/2025/12/image-8-275x300.png 275w" sizes="(max-width: 433px) 100vw, 433px" /></figure>
</div>


<p class="wp-block-paragraph">Ao longo das próximas seções, vamos sempre assumir como placa-alvo a <strong>Nucleo STM32F411</strong> e o ambiente de desenvolvimento <strong>STM32CubeIDE</strong>, usando a HAL da ST. A ideia é que, ao final do tutorial, você tenha um “esqueleto” de projeto no qual basta chamar <code>printf()</code> em qualquer parte do código para enviar mensagens de debug pela UART/USB para o seu PC.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. Entendendo a UART e a Virtual COM Port (VCP) na Nucleo STM32F411</h3>



<p class="wp-block-paragraph">A plataforma <strong>Nucleo STM32F411</strong> possui um recurso extremamente útil para debug: o <strong>ST-LINK/V2-1</strong>, que integra no mesmo cabo USB tanto a interface de programação/debug quanto uma <strong>porta serial virtual</strong> que aparece no computador como um dispositivo COM (Windows) ou <code>/dev/ttyACMx</code> (Linux). Essa porta é automaticamente conectada, via jumpers na placa, ao periférico <strong>USART2</strong> do microcontrolador STM32F411.</p>



<p class="wp-block-paragraph">Isso significa que <strong>não é necessário nenhum conversor USB-Serial adicional</strong>: basta conectar a placa ao PC e abrir um terminal serial. Do ponto de vista elétrico e lógico, o ST-LINK faz a ponte entre os pinos da UART do MCU e o USB do computador, simplificando enormemente o processo de debug.</p>



<h4 class="wp-block-heading">2.1. Mapeamento de pinos na Nucleo F411RE</h4>


<div class="wp-block-image">
<figure class="alignright size-full"><img loading="lazy" decoding="async" width="490" height="303" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-9.png" alt="" class="wp-image-966" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-9.png 490w, https://mcu.tec.br/wp-content/uploads/2025/12/image-9-300x186.png 300w" sizes="(max-width: 490px) 100vw, 490px" /></figure>
</div>


<p class="wp-block-paragraph">Na maioria das placas Nucleo baseadas no F4, o mapeamento é:</p>



<ul class="wp-block-list">
<li><strong>USART2_TX → PA2</strong></li>



<li><strong>USART2_RX → PA3</strong></li>
</ul>



<p class="wp-block-paragraph">Esses sinais passam pelo circuito do ST-LINK através de jumpers normalmente identificados como:</p>



<ul class="wp-block-list">
<li><strong>JP5 (ou equivalente)</strong> — controla a conexão da UART ao ST-LINK.</li>
</ul>



<p class="wp-block-paragraph">Se os jumpers estiverem na posição padrão (factory default), a UART estará conectada ao ST-LINK, e o <code>printf</code> será exibido no terminal do computador.</p>



<h4 class="wp-block-heading">2.2. Configuração típica da UART para debug</h4>



<p class="wp-block-paragraph">A configuração mais comum, e recomendada pela ST, é:</p>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img loading="lazy" decoding="async" width="519" height="371" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-10.png" alt="" class="wp-image-967" style="width:489px;height:auto" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-10.png 519w, https://mcu.tec.br/wp-content/uploads/2025/12/image-10-300x214.png 300w" sizes="(max-width: 519px) 100vw, 519px" /></figure>
</div>


<ul class="wp-block-list">
<li><strong>Baudrate</strong>: 115200 bps</li>



<li><strong>Bits de dados</strong>: 8</li>



<li><strong>Paridade</strong>: None</li>



<li><strong>Stop bits</strong>: 1</li>



<li><strong>Modo</strong>: TX (opcionalmente RX se quiser receber dados)</li>



<li><strong>Hardware Flow Control</strong>: None</li>
</ul>



<p class="wp-block-paragraph">Essas configurações funcionam com praticamente todos os terminais como PuTTY, screen, Minicom, CoolTerm, Serial Studio e o monitor serial da própria ST.</p>



<h4 class="wp-block-heading">2.3. Clocks envolvidos</h4>



<p class="wp-block-paragraph">A UART só funcionará corretamente se:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="641" height="312" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-11.png" alt="" class="wp-image-968" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-11.png 641w, https://mcu.tec.br/wp-content/uploads/2025/12/image-11-300x146.png 300w" sizes="(max-width: 641px) 100vw, 641px" /></figure>
</div>


<ol class="wp-block-list">
<li>O clock do barramento <strong>APB1</strong> estiver configurado.</li>



<li>O clock da UART seja habilitado (feito automaticamente pelo CubeIDE ao ativar a USART2).</li>



<li>Os pinos PA2 e PA3 estejam configurados como <strong>Alternate Function 7 (AF7)</strong>.</li>
</ol>


<div class="wp-block-image">
<figure class="alignright size-full"><img loading="lazy" decoding="async" width="511" height="252" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-12.png" alt="" class="wp-image-969" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-12.png 511w, https://mcu.tec.br/wp-content/uploads/2025/12/image-12-300x148.png 300w" sizes="(max-width: 511px) 100vw, 511px" /></figure>
</div>


<p class="wp-block-paragraph">Todos esses passos serão automatizados quando configurarmos o projeto no STM32CubeIDE, mas é importante compreender que a comunicação serial depende diretamente da estabilidade do clock do sistema. Uma configuração inadequada do PLL ou do HSE/HSI pode fazer a UART transmitir dados corrompidos.</p>



<h4 class="wp-block-heading">2.4. Como o fluxo de debug é estabelecido</h4>



<p class="wp-block-paragraph">O caminho do <code>printf</code> até o terminal serial pode ser resumido assim:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>printf() 
    → função de baixo nível __io_putchar() 
        → HAL_UART_Transmit()
            → USART2
                → ST-LINK (Virtual COM Port)
                    → Cabo USB
                        → PC (Terminal Serial)
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">() </span></span>
<span class="line"><span style="color: #D8DEE9FF">    → </span><span style="color: #D8DEE9">função</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">baixo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">nível</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">__io_putchar</span><span style="color: #D8DEE9FF">() </span></span>
<span class="line"><span style="color: #D8DEE9FF">        → </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">            → </span><span style="color: #D8DEE9">USART2</span></span>
<span class="line"><span style="color: #D8DEE9FF">                → </span><span style="color: #D8DEE9">ST</span><span style="color: #81A1C1">-</span><span style="color: #88C0D0">LINK</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">Virtual</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">COM</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Port</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    → </span><span style="color: #D8DEE9">Cabo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USB</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        → </span><span style="color: #88C0D0">PC</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">Terminal</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Serial</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse pipeline deixa claro que:</p>



<ul class="wp-block-list">
<li>O <code>printf</code> não sabe nada sobre UART; ele apenas escreve caracteres.</li>



<li>Quem realmente envia cada caractere é nossa implementação de <code>_write()</code> ou <code>__io_putchar()</code>.</li>



<li>Se a UART não estiver inicializada, nada será transmitido.</li>



<li>Se a UART bloquear (modo polling), o <code>printf</code> também bloqueará.</li>
</ul>



<p class="wp-block-paragraph">Por isso, utilizaremos uma implementação simples usando <strong>HAL_UART_Transmit()</strong>, que é suficiente para debug e fácil de manter.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">3. Configurando o Projeto no STM32CubeIDE para Habilitar a UART</p>



<p class="wp-block-paragraph">Nesta etapa vamos preparar o ambiente no <strong>STM32CubeIDE</strong> para que a placa <strong>Nucleo STM32F411</strong> use corretamente a <strong>USART2</strong> como canal de debug. O CubeIDE facilita muito o processo automatizando a configuração de pinos, clocks e inicialização do HAL.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3.1. Criando um novo projeto</h2>



<ol class="wp-block-list">
<li>Abra o <strong>STM32CubeIDE</strong>.</li>



<li>Vá em <strong>File > New > STM32 Project</strong>.</li>



<li>Pesquise por <strong>Nucleo-F411RE</strong>.</li>



<li>Selecione a placa e avance.</li>



<li>Escolha o nome do projeto (por exemplo: <code>UART_Debug_Printf</code>).</li>
</ol>



<p class="wp-block-paragraph">O CubeIDE automaticamente carregará a configuração de pinos padrão da placa.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3.2. Habilitando a USART2 como canal de debug</h2>



<ol class="wp-block-list">
<li>No <em>Device Configuration Tool</em> (a tela .ioc), clique no pino <strong>PA2</strong> e selecione <strong>USART2_TX</strong>.</li>



<li>Clique em <strong>PA3</strong> e selecione <strong>USART2_RX</strong>.</li>



<li>No menu lateral, selecione <strong>Connectivity → USART2</strong>.</li>



<li>Configure como:</li>
</ol>



<ul class="wp-block-list">
<li><strong>Mode</strong>: Asynchronous</li>



<li><strong>Baudrate</strong>: 115200</li>



<li><strong>Word Length</strong>: 8 Bits</li>



<li><strong>Parity</strong>: None</li>



<li><strong>Stop Bits</strong>: 1</li>



<li><strong>Hardware Flow Control</strong>: None</li>
</ul>



<p class="wp-block-paragraph">O CubeIDE automaticamente adicionará a chamada:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>MX_USART2_UART_Init();
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">MX_USART2_UART_Init</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">no arquivo <code>main.c</code>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3.3. Verificando os clocks</h2>



<p class="wp-block-paragraph">Entre em <strong>Clock Configuration</strong> e confirme:</p>



<ul class="wp-block-list">
<li><strong>SYSCLK</strong>: 84 MHz (valor típico no F411 configurado pelo CubeIDE)</li>



<li><strong>APB1</strong>: ≤ 42 MHz</li>



<li><strong>USART2 Clock</strong>: habilitado automaticamente pelo CubeIDE</li>
</ul>



<p class="wp-block-paragraph">A UART depende diretamente desses clocks. Se você modificar manualmente o PLL, ajuste os divisores para manter APB1 em valores seguros.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3.4. Interação entre HAL e UART para debug</h2>



<p class="wp-block-paragraph">Ao habilitar a UART no .ioc, o CubeIDE:</p>



<ul class="wp-block-list">
<li>Gera o handle global <code>UART_HandleTypeDef huart2;</code></li>



<li>Cria a função <code>MX_USART2_UART_Init()</code></li>



<li>Configura os pinos PA2 e PA3 como <strong>Alternate Function 7</strong></li>



<li>Habilita o clock da USART2</li>
</ul>



<p class="wp-block-paragraph">Com isso, <code>HAL_UART_Transmit()</code> já pode ser usado imediatamente na aplicação.</p>



<p class="wp-block-paragraph">Exemplo simples:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>uint8_t msg[] = "UART funcionando\r\n";
HAL_UART_Transmit(&amp;huart2, msg, sizeof(msg)-1, HAL_MAX_DELAY);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">[] </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">UART funcionando</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">-</span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse é o passo fundamental antes de redirecionar o <code>printf</code>. Sem uma UART funcional, o redirecionamento não terá efeito.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3.5. Compilar e validar</h2>



<p class="wp-block-paragraph">Clique em:</p>



<ul class="wp-block-list">
<li><strong>Project > Build Project</strong></li>



<li>Depois <strong>Run</strong> ou <strong>Debug</strong></li>
</ul>



<p class="wp-block-paragraph">Ao conectar a placa ao PC, confirme no sistema operacional que a <strong>porta serial virtual</strong> foi criada.</p>



<p class="wp-block-paragraph">Exemplos:</p>



<ul class="wp-block-list">
<li><strong>Windows</strong>: COM5</li>



<li><strong>Linux</strong>: <code>/dev/ttyACM0</code></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4. Implementando o redirecionamento do <code>printf</code> para a UART</h3>



<p class="wp-block-paragraph">Agora que a <strong>USART2</strong> da Nucleo STM32F411 está configurada e testada com um <code>HAL_UART_Transmit()</code> simples, podemos dar o passo mais importante: <strong>fazer com que o <code>printf()</code> use essa UART como “saída padrão”</strong>.</p>



<p class="wp-block-paragraph">Em microcontroladores ARM com <strong>newlib</strong> (caso do STM32CubeIDE, que usa <code>arm-none-eabi-gcc</code>), o <code>printf</code> não escreve diretamente no hardware. Ele chama funções de baixo nível, como <code>_write()</code> ou, em alguns exemplos da ST, uma função auxiliar chamada <code>__io_putchar()</code>. A ideia do redirecionamento é simples:</p>



<ul class="wp-block-list">
<li>Implementar <code>_write()</code> (ou <code>__io_putchar()</code>) para enviar os bytes pela UART;</li>



<li>Compilar e linkar essa implementação junto ao projeto;</li>



<li>A partir daí, qualquer <code>printf()</code> encaminha os dados para a UART.</li>
</ul>



<p class="wp-block-paragraph">A seguir vou mostrar um modelo que <strong>funciona muito bem com o STM32CubeIDE/GCC</strong> e a Nucleo F411.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">4.1. Incluindo os headers necessários</h4>



<p class="wp-block-paragraph">Primeiro, em um arquivo C do seu projeto (pode ser o próprio <code>main.c</code> ou, melhor ainda, um arquivo dedicado como <code>retarget.c</code>), inclua:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include "stm32f4xx_hal.h"
#include &lt;stdio.h>
#include &lt;unistd.h>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">stm32f4xx_hal.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdio</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">unistd</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Depois, declare o handle da UART como <code>extern</code>, pois ele é criado em outro arquivo (gerado pelo CubeIDE):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>extern UART_HandleTypeDef huart2;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">extern</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">UART_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">huart2</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">4.2. Implementando <code>_write()</code> para o GCC/newlib</h4>



<p class="wp-block-paragraph">A abordagem mais robusta, em ambiente GCC + newlib, é sobrescrever a função <code>_write()</code>. O <code>printf</code> acaba chamando <code>_write()</code> internamente para escrever os dados:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int _write(int file, char *ptr, int len)
{
    // Envia o buffer "ptr" com "len" bytes pela UART2
    HAL_UART_Transmit(&amp;huart2, (uint8_t *)ptr, len, HAL_MAX_DELAY);
    return len;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">file</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">ptr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Envia o buffer &quot;ptr&quot; com &quot;len&quot; bytes pela UART2</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">ptr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Alguns detalhes importantes:</p>



<ul class="wp-block-list">
<li>O parâmetro <code>file</code> representa o descritor de arquivo (stdout, stderr, etc.). Para debug simples, você pode ignorá-lo.</li>



<li><code>ptr</code> é o endereço do buffer com os caracteres já montados pelo <code>printf</code>.</li>



<li><code>len</code> é a quantidade de bytes a transmitir.</li>



<li><code>HAL_MAX_DELAY</code> faz a função bloquear até a transmissão terminar. É simples e suficiente para debug (não é ideal em aplicações com requisitos de tempo real estritos).</li>
</ul>



<p class="wp-block-paragraph">Com essa implementação, qualquer <code>printf()</code> que escreva em <code>stdout</code> já será redirecionado para a UART2.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">4.3. Implementando <code>__io_putchar()</code> (opcional, mas comum em exemplos ST)</h4>



<p class="wp-block-paragraph">Em muitos exemplos da ST, você verá o uso de um macro <code>PUTCHAR_PROTOTYPE</code> que mapeia para <code>__io_putchar()</code> (no GCC) ou <code>fputc()</code> (em outros toolchains). Você pode combinar as duas ideias:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#ifdef __GNUC__
/* GCC/STM32CubeIDE usa __io_putchar() internamente em printf em alguns exemplos da ST */
int __io_putchar(int ch)
{
    HAL_UART_Transmit(&amp;huart2, (uint8_t *)&amp;ch, 1, HAL_MAX_DELAY);
    return ch;
}
#else
/* Para outros compiladores, como Keil ou IAR */
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&amp;huart2, (uint8_t *)&amp;ch, 1, HAL_MAX_DELAY);
    return ch;
}
#endif
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">ifdef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">__GNUC__</span></span>
<span class="line"><span style="color: #616E88">/* GCC/STM32CubeIDE usa __io_putchar() internamente em printf em alguns exemplos da ST */</span></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">__io_putchar</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ch</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">ch</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ch</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #616E88">/* Para outros compiladores, como Keil ou IAR */</span></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">fputc</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ch</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FILE</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">ch</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ch</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">endif</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Se você implementar <strong>apenas <code>_write()</code></strong>, o <code>printf</code> já funciona no GCC/newlib. Se quiser compatibilidade máxima com exemplos da ST e outros toolchains, mantenha também <code>__io_putchar()</code>/<code>fputc()</code>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">4.4. Onde colocar esse código no projeto</h4>



<p class="wp-block-paragraph">Existem duas abordagens:</p>



<ol class="wp-block-list">
<li><strong>No próprio <code>main.c</code></strong>
<ul class="wp-block-list">
<li>Mais simples para começar, ideal para experimentos.</li>



<li>Basta inserir a implementação de <code>_write()</code> e/ou <code>__io_putchar()</code> <strong>abaixo</strong> das includes e da declaração <code>extern UART_HandleTypeDef huart2;</code>.</li>
</ul>
</li>



<li><strong>Em um arquivo separado, por exemplo <code>retarget.c</code></strong>
<ul class="wp-block-list">
<li>Organização melhor, especialmente em projetos grandes.</li>



<li>Crie o arquivo via <strong>New > Source File</strong>, inclua as cabeçalhos e implemente <code>_write()</code> ali.</li>



<li>Não esqueça de adicionar <code>retarget.c</code> ao build (o CubeIDE já faz isso automaticamente ao criar dentro do projeto).</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">O ponto fundamental é: <strong>o arquivo que contém <code>_write()</code>/<code>__io_putchar()</code> precisa ser compilado junto com o projeto</strong> para que o linker substitua a implementação fraca (weak) padrão de <code>_write()</code> pela sua.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">4.5. Pequeno exemplo de uso no <code>main.c</code></h4>



<p class="wp-block-paragraph">Depois de configurada a UART e implementado <code>_write()</code>, o <code>main.c</code> pode conter algo como:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_USART2_UART_Init();   // Importante: inicializa a UART2 antes do primeiro printf

    printf("Sistema iniciado!\r\n");
    printf("Clock do sistema: %lu Hz\r\n", HAL_RCC_GetHCLKFreq());

    while (1)
    {
        printf("Loop principal, tick = %lu\r\n", HAL_GetTick());
        HAL_Delay(1000);
    }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_Init</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">SystemClock_Config</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">MX_USART2_UART_Init</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">// Importante: inicializa a UART2 antes do primeiro printf</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Sistema iniciado!</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Clock do sistema: %lu Hz</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_RCC_GetHCLKFreq</span><span style="color: #D8DEE9FF">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Loop principal, tick = %lu</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_GetTick</span><span style="color: #D8DEE9FF">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">HAL_Delay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Se tudo estiver correto, essas mensagens aparecerão no terminal serial do seu PC, na porta correspondente à Virtual COM Port, a 115200 bps.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5. Cuidados com <code>printf</code>: buffer, quebra de linha e impacto em tempo real</h3>



<p class="wp-block-paragraph">Com o <code>printf</code> já saindo pela UART2, é hora de falar dos <strong>detalhes práticos</strong> que mais costumam pegar de surpresa: comportamento de buffer, diferença entre <code>\n</code> e <code>\r\n</code>, e o impacto de sair “espalhando <code>printf</code> pelo código” em um sistema que tem requisitos de tempo real.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">5.1. <code>\n</code> vs <code>\r\n</code> – por que às vezes o texto “sobe” no terminal?</h4>



<p class="wp-block-paragraph">Em muitos terminais seriais (PuTTY, Minicom, screen, etc.), o caractere <strong><code>\n</code> (line feed)</strong> apenas move o cursor para a linha de baixo, <strong>sem retornar para a coluna 0</strong>. Já <strong><code>\r</code> (carriage return)</strong> volta o cursor para o início da linha, mas não desce. O comportamento mais comum em sistemas embarcados é usar a combinação:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>printf("Mensagem de debug\r\n");
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Mensagem de debug</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Se você usar somente <code>\n</code>, é comum ver efeito de “escada” ou textos desalinhados no terminal. O padrão “universal” para logs em interface serial é <code>\r\n</code>. Se quiser, pode criar um helper:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>void logln(const char *msg)
{
    printf("%s\r\n", msg);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">logln</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">%s</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">E usar <code>logln("Sistema iniciado");</code> ao invés de lembrar sempre do <code>\r\n</code>.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">5.2. Bufferização do <code>printf</code> (stdout) e “trava” aparente</h4>



<p class="wp-block-paragraph">Por padrão, a biblioteca C pode <strong>bufferizar</strong> a saída (stdout). Em ambiente embarcado, isso varia conforme a toolchain, mas alguns sintomas são:</p>



<ul class="wp-block-list">
<li>Você chama <code>printf("Teste\r\n");</code> e nada aparece no terminal.</li>



<li>Ao chamar outro <code>printf</code> maior ou ao encerrar o programa (em PC), tudo aparece “de uma vez”.</li>
</ul>



<p class="wp-block-paragraph">Para evitar esse tipo de surpresa, você pode:</p>



<ol class="wp-block-list">
<li><strong>Desabilitar o buffer de <code>stdout</code></strong> (quando suportado), logo após iniciar o sistema: <code>setvbuf(stdout, NULL, _IONBF, 0); // stdout sem buffer</code> Em muitos ambientes embarcados com newlib-nano, isso já é o comportamento, mas não custa colocar.</li>



<li><strong>Sempre finalizar as linhas com <code>\r\n</code></strong>, o que, em algumas implementações, força flush.</li>
</ol>



<p class="wp-block-paragraph">Se perceber comportamentos estranhos, experimente remover otimizações extremas de compilação e garantir que <code>_write()</code> está sendo realmente linkado (às vezes uma implementação fraca default pode estar sendo usada por engano).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">5.3. Cuidado com o tempo de bloqueio: <code>HAL_UART_Transmit()</code> é bloqueante</h4>



<p class="wp-block-paragraph">Na implementação que fizemos:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int _write(int file, char *ptr, int len)
{
    HAL_UART_Transmit(&amp;huart2, (uint8_t *)ptr, len, HAL_MAX_DELAY);
    return len;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">file</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">ptr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">ptr</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">o <code>HAL_UART_Transmit()</code> é <strong>bloqueante</strong>: a CPU fica parada até todos os bytes serem transmitidos. Em termos práticos:</p>



<ul class="wp-block-list">
<li>Uma linha como<br><code>printf("Valor = %d, estado = %d\r\n", x, estado);</code><br>pode gerar 30–60 bytes.</li>



<li>A 115200 bps, você transmite cerca de 11.520 bytes/s (aprox. 10 bits por byte, contando start/stop).</li>



<li>Então <strong>50 bytes ≈ 4,3 ms</strong> de transmissão não-interrompida.</li>
</ul>



<p class="wp-block-paragraph">Se você fizer isso dentro de uma <strong>ISR (rotina de interrupção)</strong> ou em uma tarefa crítica de tempo real, esses milissegundos a mais podem causar problemas:</p>



<ul class="wp-block-list">
<li>Perda de deadlines.</li>



<li>Atraso na leitura de sensores ou controle de motor.</li>



<li>Estouro de watchdog, se o sistema for mais rígido.</li>
</ul>



<p class="wp-block-paragraph">Boas práticas:</p>



<ul class="wp-block-list">
<li><strong>Nunca usar <code>printf</code> em ISR.</strong><br>Se precisar debugar uma interrupção, registre flags ou copie dados para um buffer e imprima em contexto de thread/tarefa.</li>



<li><strong>Usar <code>printf</code> com parcimônia</strong> em laços que rodam com alta frequência.</li>



<li>Em sistemas com RTOS, considerar <strong>uma tarefa de log</strong> dedicada.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">5.4. Estratégia com RTOS: fila de logs (opcional, mas muito recomendável)</h4>



<p class="wp-block-paragraph">Se você estiver usando FreeRTOS (ou outro RTOS), uma abordagem mais limpa é:</p>



<ol class="wp-block-list">
<li>Criar uma <strong>fila (queue)</strong> para mensagens de log.</li>



<li>Criar uma <strong>tarefa “Logger”</strong> que:
<ul class="wp-block-list">
<li>Bloqueia esperando mensagens na fila.</li>



<li>Ao receber, chama <code>HAL_UART_Transmit()</code> para mandar pela UART.</li>
</ul>
</li>



<li>Substituir <code>printf</code> por algo como <code>log_printf()</code>, que formata a string e envia para a fila.</li>
</ol>



<p class="wp-block-paragraph">Esboço de ideia (bem simplificado):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// Tamanho máximo de uma mensagem de log
#define LOG_MSG_MAX 128

QueueHandle_t xLogQueue;

void LoggerTask(void *argument)
{
    char msg&#91;LOG_MSG_MAX&#93;;

    for (;;)
    {
        if (xQueueReceive(xLogQueue, &amp;msg, portMAX_DELAY) == pdTRUE)
        {
            HAL_UART_Transmit(&amp;huart2, (uint8_t *)msg, strlen(msg), HAL_MAX_DELAY);
        }
    }
}

// Exemplo simples de função de log (sem vsnprintf, apenas ilustrativo)
void log_printf(const char *fmt, ...)
{
    char buffer&#91;LOG_MSG_MAX&#93;;
    va_list args;
    va_start(args, fmt);
    vsnprintf(buffer, LOG_MSG_MAX, fmt, args);
    va_end(args);

    xQueueSend(xLogQueue, &amp;buffer, 0);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">// Tamanho máximo de uma mensagem de log</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LOG_MSG_MAX</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">128</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">QueueHandle_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">xLogQueue</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">LoggerTask</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">argument</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">LOG_MSG_MAX</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">;;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">xQueueReceive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xLogQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">portMAX_DELAY</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pdTRUE</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">HAL_UART_Transmit</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">msg</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// Exemplo simples de função de log (sem vsnprintf, apenas ilustrativo)</span></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">log_printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">fmt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buffer</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">LOG_MSG_MAX</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">va_list</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">args</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">va_start</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">args</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fmt</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vsnprintf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">buffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LOG_MSG_MAX</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fmt</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">args</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">va_end</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">args</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">xQueueSend</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">xLogQueue</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">buffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Essa abordagem tira a carga do contexto onde a mensagem é gerada e concentra o custo de transmissão em uma única tarefa de menor prioridade.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">5.5. <code>printf</code> grande demais e estouro de stack/heap</h4>



<p class="wp-block-paragraph">Outra armadilha comum: <strong>strings muito grandes em <code>printf</code></strong>, especialmente em sistemas com pouco RAM:</p>



<ul class="wp-block-list">
<li>Cada <code>printf</code> complexa pode usar <code>vsnprintf</code> internamente, exigindo buffers temporários.</li>



<li>Se o stack ou heap forem pequenos, isso pode levar a <strong>stack overflow</strong> ou corromper memória silenciosamente.</li>
</ul>



<p class="wp-block-paragraph">Recomendações:</p>



<ul class="wp-block-list">
<li><strong>Evite prints gigantescos</strong>; prefira várias mensagens menores e objetivas.</li>



<li>Ajuste o tamanho de stack das tarefas em RTOS que usam <code>printf</code>.</li>



<li>Se possível, use a <code>newlib-nano</code> com suporte a <code>printf</code> reduzido (sem float), a menos que precise imprimir <code>float/double</code>.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6. Testando o redirecionamento do <code>printf</code> no PC com terminal serial</h3>



<p class="wp-block-paragraph">Com toda a infraestrutura montada — UART configurada, <code>_write()</code> implementado e <code>printf()</code> funcionando — é hora de validar tudo com um terminal serial no computador. Esta etapa confirma que a <strong>Virtual COM Port (VCP)</strong> do ST-LINK está operando corretamente e que os dados enviados pelo microcontrolador estão realmente chegando até o PC.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6.1. Identificando a porta serial (VCP) no sistema operacional</h2>



<p class="wp-block-paragraph">Quando você conecta a <strong>Nucleo STM32F411</strong> ao computador usando o cabo USB no conector do ST-LINK (não no USB OTG do microcontrolador), o ST-LINK cria automaticamente uma <strong>porta serial virtual</strong>.</p>



<p class="wp-block-paragraph">Para verificar:</p>



<h3 class="wp-block-heading"><strong>No Windows</strong></h3>



<p class="wp-block-paragraph">Abra o <strong>Gerenciador de Dispositivos</strong> → <em>Portas (COM &amp; LPT)</em><br>Aparecerá algo como:</p>



<ul class="wp-block-list">
<li><strong>STMicroelectronics Virtual COM Port (COM5)</strong></li>
</ul>



<p class="wp-block-paragraph">O número da porta (COM5, COM7 etc.) varia de máquina para máquina.</p>



<h3 class="wp-block-heading"><strong>No Linux</strong></h3>



<p class="wp-block-paragraph">Use no terminal:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>ls /dev/ttyACM*
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">ls</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">dev</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">ttyACM</span><span style="color: #81A1C1">*</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">ou observe mensagens do <code>dmesg</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>dmesg | tail
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">dmesg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tail</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Normalmente será:</p>



<ul class="wp-block-list">
<li><code>/dev/ttyACM0</code></li>



<li><code>/dev/ttyACM1</code></li>
</ul>



<h3 class="wp-block-heading"><strong>No macOS</strong></h3>



<p class="wp-block-paragraph">Em geral:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>ls /dev/tty.usbmodem*
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">ls</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">dev</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">tty</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">usbmodem</span><span style="color: #81A1C1">*</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>[Espaço para Imagem 9 – Captura mostrando a porta STMicroelectronics Virtual COM Port no Windows /dev/ttyACM0 no Linux]</strong></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6.2. Configurando o terminal serial</h2>



<p class="wp-block-paragraph">Você pode usar ferramentas como:</p>



<ul class="wp-block-list">
<li><strong>PuTTY</strong></li>



<li><strong>screen</strong> (Linux/macOS)</li>



<li><strong>Minicom</strong></li>



<li><strong>CoolTerm</strong></li>



<li><strong>Serial Studio</strong></li>



<li><strong>TeraTerm</strong></li>
</ul>



<p class="wp-block-paragraph">As configurações fundamentais:</p>



<ul class="wp-block-list">
<li><strong>Baud rate:</strong> 115200</li>



<li><strong>Data bits:</strong> 8</li>



<li><strong>Parity:</strong> None</li>



<li><strong>Stop bits:</strong> 1</li>



<li><strong>Flow control:</strong> <em>None</em></li>
</ul>



<p class="wp-block-paragraph">Essas são as mesmas configurações definidas no CubeIDE para a UART2.</p>



<h3 class="wp-block-heading">Exemplos:</h3>



<h3 class="wp-block-heading">No PuTTY (Windows):</h3>



<ul class="wp-block-list">
<li><em>Connection type:</em> Serial</li>



<li><em>Serial line:</em> COM5</li>



<li><em>Speed:</em> 115200</li>



<li>Clique em <strong>Open</strong>.</li>
</ul>



<h3 class="wp-block-heading">No Linux (screen):</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>screen /dev/ttyACM0 115200
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">screen</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">dev</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">ttyACM0</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">115200</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Para sair:</p>



<ul class="wp-block-list">
<li>Pressione: <code>Ctrl + A</code>, depois <code>K</code>.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6.3. Primeiro teste: envio de mensagem simples</h2>



<p class="wp-block-paragraph">Carregue o firmware na placa e inicialize. Logo no início, se o seu <code>main.c</code> tiver:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>printf("Sistema iniciado!\r\n");
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Sistema iniciado!</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Você deverá ver no terminal:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Sistema iniciado!
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Sistema</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">iniciado</span><span style="color: #81A1C1">!</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Se após alguns segundos o loop do seu exemplo estiver imprimindo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>printf("Loop principal, tick = %lu\r\n", HAL_GetTick());
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Loop principal, tick = %lu</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_GetTick</span><span style="color: #D8DEE9FF">())</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Você verá:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Loop principal, tick = 1001
Loop principal, tick = 2002
Loop principal, tick = 3003
...
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Loop</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">principal</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tick</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1001</span></span>
<span class="line"><span style="color: #D8DEE9">Loop</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">principal</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tick</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2002</span></span>
<span class="line"><span style="color: #D8DEE9">Loop</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">principal</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tick</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3003</span></span>
<span class="line"><span style="color: #81A1C1">...</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Se nada aparecer:</h3>



<ul class="wp-block-list">
<li>Verifique a porta correta.</li>



<li>Confirme a velocidade (115200).</li>



<li>Garanta que <em>MX_USART2_UART_Init()</em> é chamado antes do primeiro <code>printf</code>.</li>



<li>Confira se <code>_write()</code> está realmente sendo compilado (abra a pasta <code>/Debug</code> e verifique se retarget.o está lá).</li>



<li>Veja se PA2/PA3 não foram sobrescritos no .ioc.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6.4. Segundo teste: envio de valores variáveis</h2>



<p class="wp-block-paragraph">Para testar formatação e estabilidade, experimente inserir:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>int contador = 0;
while (1)
{
    printf("Contador = %d\r\n", contador++);
    HAL_Delay(500);
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">contador</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">while</span><span style="color: #D8DEE9FF"> (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Contador = %d</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">contador</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_Delay</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">500</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Após rodar, o terminal deve exibir algo como:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Contador = 0
Contador = 1
Contador = 2
Contador = 3
...
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">Contador</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span></span>
<span class="line"><span style="color: #D8DEE9">Contador</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span></span>
<span class="line"><span style="color: #D8DEE9">Contador</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2</span></span>
<span class="line"><span style="color: #D8DEE9">Contador</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span></span>
<span class="line"><span style="color: #81A1C1">...</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse teste simples valida:</p>



<ul class="wp-block-list">
<li>Integração com <code>printf</code></li>



<li>Transmissão contínua</li>



<li>Quebras de linha <code>\r\n</code></li>



<li>Buffer do terminal</li>



<li>Confiabilidade da UART</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7. Boas práticas, alternativas ao <code>printf</code> e resumo final</h3>



<p class="wp-block-paragraph">Agora que o redirecionamento do <code>printf</code> para a UART está funcionando e validado no terminal, é importante fechar o tutorial consolidando boas práticas e apresentando métodos alternativos de debug que podem ser superiores dependendo do contexto do projeto.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7.1. Boas práticas ao usar <code>printf</code> em sistemas embarcados</h2>



<p class="wp-block-paragraph">O <code>printf</code> é muito útil para desenvolvimento, testes e prototipagem. Porém, em firmware profissional, seu uso deve ser criterioso. Aqui estão as principais recomendações:</p>



<h3 class="wp-block-heading">1. <strong>Evite usar <code>printf</code> dentro de interrupções (ISR)</strong></h3>



<p class="wp-block-paragraph">Como vimos, o <code>HAL_UART_Transmit()</code> é bloqueante. Se for chamado dentro de uma interrupção:</p>



<ul class="wp-block-list">
<li>A interrupção ficará presa transmitindo os bytes,</li>



<li>O sistema pode perder deadlines,</li>



<li>Outras interrupções podem ser atrasadas,</li>



<li>Pode ocorrer estouro do watchdog.</li>
</ul>



<p class="wp-block-paragraph">Sempre registre dados críticos em buffers e imprima em contexto de thread.</p>



<h3 class="wp-block-heading">2. <strong>Não abuse do <code>printf</code> em laços rápidos</strong></h3>



<p class="wp-block-paragraph">Se o loop roda a cada 1 ms e imprime texto extenso, a UART não acompanhará o ritmo. Isso pode causar:</p>



<ul class="wp-block-list">
<li>Travamento aparente,</li>



<li>Perda de cadência no controle,</li>



<li>Saturação de buffer,</li>



<li>Queda de desempenho.</li>
</ul>



<h3 class="wp-block-heading">3. <strong>Evite <code>printf</code> com floats</strong></h3>



<p class="wp-block-paragraph">O suporte a <code>float</code> aumenta muito o tamanho do binário e o custo computacional.<br>Prefira converter para inteiro multiplicando por 100 ou 1000:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>printf("Temperatura = %d.%02d C\r\n", (int)temp, (int)(temp * 100) % 100);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Temperatura = %d.%02d C</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">temp</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">temp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">%</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">4. <strong>Desative logs em builds finais</strong></h3>



<p class="wp-block-paragraph">Em builds de produção, é comum:</p>



<ul class="wp-block-list">
<li>Compilar sem logs,</li>



<li>Usar <code>#define DEBUG</code> para habilitar/desabilitar os prints,</li>



<li>Criar macros como:</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#ifdef DEBUG
    #define debug_printf(...) printf(__VA_ARGS__)
#else
    #define debug_printf(...)
#endif
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">ifdef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DEBUG</span></span>
<span class="line"><span style="color: #D8DEE9FF">    #</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">debug_printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF">) </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">__VA_ARGS__</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #D8DEE9FF">    #</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">debug_printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">endif</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Assim você elimina overhead quando não precisa de logs.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7.2. Alternativas avançadas ao <code>printf</code></h2>



<p class="wp-block-paragraph">Embora a UART seja excelente para debug, ela não é a única nem a melhor solução em todos os casos.</p>



<h3 class="wp-block-heading"><strong>1. ITM/SWO (Single Wire Output)</strong></h3>



<p class="wp-block-paragraph">Disponível na maioria dos STM32F4, incluindo o F411.<br>Oferece:</p>



<ul class="wp-block-list">
<li>Alta velocidade,</li>



<li>Impressão quase imediata,</li>



<li>Baixíssimo overhead,</li>



<li>Não bloqueia o firmware,</li>



<li>Funciona dentro de ISR.</li>
</ul>



<p class="wp-block-paragraph">Requer que seu ST-LINK suporte SWO (quase todos os V2-1 suportam).</p>



<p class="wp-block-paragraph">A função usada no HAL é:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>ITM_SendChar(ch);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #88C0D0">ITM_SendChar</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ch</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Muitos desenvolvedores substituem <code>__io_putchar()</code> para cair aqui.</p>



<h3 class="wp-block-heading"><strong>2. RTT (Real-Time Transfer) – SEGGER J-Link</strong></h3>



<p class="wp-block-paragraph">Se você usa J-Link:</p>



<ul class="wp-block-list">
<li>RTT é extremamente rápido,</li>



<li>Zero bloqueio,</li>



<li>Permite canais bidirecionais,</li>



<li>Ideal para sistemas de alto desempenho.</li>
</ul>



<p class="wp-block-paragraph">Funciona mesmo com microcontroladores sem UART sobrando.</p>



<h3 class="wp-block-heading"><strong>3. Semihosting</strong></h3>



<p class="wp-block-paragraph">O <code>printf</code> é exibido no console do IDE, sem precisar de UART.</p>



<p class="wp-block-paragraph">Porém:</p>



<ul class="wp-block-list">
<li><strong>Extremamente lento</strong>,</li>



<li>Bloqueante,</li>



<li>Inadequado para quase tudo exceto testes acadêmicos.</li>
</ul>



<h3 class="wp-block-heading"><strong>4. Logs estruturados por DMA</strong></h3>



<p class="wp-block-paragraph">Você pode configurar a UART com <strong>DMA circular</strong> para transmitir logs sem bloquear a CPU.<br>Exige controle mais sofisticado, mas reduz o custo de tempo real.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7.3. Resumo final do processo</h2>



<p class="wp-block-paragraph">Aqui está um resumo objetivo de tudo o que você implementou:</p>



<ol class="wp-block-list">
<li><strong>Configure a USART2 no CubeIDE</strong> usando PA2 (TX) e PA3 (RX), 115200 bps.</li>



<li>Confirme que a VCP do ST-LINK está ativa (porta COM/ttyACM).</li>



<li>Compile o projeto e inicialize a UART com <code>MX_USART2_UART_Init()</code>.</li>



<li>Implemente a função <code>_write()</code> ou <code>__io_putchar()</code> para enviar caracteres via <code>HAL_UART_Transmit()</code>.</li>



<li>Teste com um terminal serial como PuTTY, Minicom ou screen.</li>



<li>Use <code>\r\n</code> para evitar quebras de linha incorretas.</li>



<li>Evite <code>printf</code> em ISR e em laços críticos.</li>



<li>Em aplicações mais avançadas, considere alternativas como ITM/SWO ou RTT.</li>
</ol>



<p class="wp-block-paragraph">Com isso, você agora possui um ambiente completo, simples e confiável para fazer debug via UART no STM32F411 — exatamente como demonstrado no guia da ST, mas adaptado para o contexto da Nucleo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/linguagem/c/como-redirecionar-o-printf-para-a-uart-no-stm32f411-um-guia-completo-para-debug-serial/">Como Redirecionar o printf para a UART no STM32F411: Um Guia Completo para Debug Serial</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">964</post-id>	</item>
	</channel>
</rss>
