<?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>STM32 - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/categorias/microcontroladores/stm32/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Mon, 15 Dec 2025 22:17:41 +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>STM32 - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>STM32V8: o novo microcontrolador da ST com Cortex-M85, PCM e tecnologia 18 nm FD-SOI</title>
		<link>https://mcu.tec.br/microcontroladores/stm32/stm32v8-o-novo-microcontrolador-da-st-com-cortex-m85-pcm-e-tecnologia-18-nm-fd-soi/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=stm32v8-o-novo-microcontrolador-da-st-com-cortex-m85-pcm-e-tecnologia-18-nm-fd-soi</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 16 Dec 2025 21:32:02 +0000</pubDate>
				<category><![CDATA[STM32]]></category>
		<category><![CDATA[automação industrial]]></category>
		<category><![CDATA[Cortex-M85]]></category>
		<category><![CDATA[DSP embarcado]]></category>
		<category><![CDATA[Edge AI]]></category>
		<category><![CDATA[FD-SOI 18 nm]]></category>
		<category><![CDATA[inteligência artificial embarcada]]></category>
		<category><![CDATA[memória PCM]]></category>
		<category><![CDATA[microcontrolador de alto desempenho]]></category>
		<category><![CDATA[microcontrolador ST]]></category>
		<category><![CDATA[Renesas RA8M1]]></category>
		<category><![CDATA[sistemas embarcados avançados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[STM32V8]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1032</guid>

					<description><![CDATA[<p>O STM32V8 é a nova família de microcontroladores de alto desempenho da STMicroelectronics, baseada no núcleo Arm Cortex-M85 e fabricada em tecnologia avançada de 18 nm FD-SOI com memória não volátil do tipo PCM integrada. Este artigo apresenta uma análise técnica e prática do STM32V8, explorando sua arquitetura de fabricação, sistema de memória, capacidades de DSP e inteligência artificial embarcada, além de suas aplicações em automação industrial, edge computing, robótica e sistemas ciberfísicos. Também é realizada uma comparação objetiva com o Renesas RA8M1, destacando diferenças em arquitetura, memória, eficiência energética e escalabilidade tecnológica. O conteúdo é voltado a engenheiros, desenvolvedores de firmware e profissionais de sistemas embarcados que buscam compreender os avanços que definem a próxima geração de microcontroladores.</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/stm32v8-o-novo-microcontrolador-da-st-com-cortex-m85-pcm-e-tecnologia-18-nm-fd-soi/">STM32V8: o novo microcontrolador da ST com Cortex-M85, PCM e tecnologia 18 nm FD-SOI</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading"><strong>o surgimento do STM32V8 e uma nova geração de microcontroladores de alto desempenho</strong></h2>



<p class="wp-block-paragraph">A STMicroelectronics anunciou recentemente a família <strong>STM32V8</strong>, marcando um avanço significativo na evolução dos microcontroladores de uso geral e industrial. Diferentemente das gerações anteriores da linha STM32, o STM32V8 foi concebido desde a origem para atender aplicações que exigem <strong>altíssimo desempenho computacional</strong>, <strong>baixa latência</strong>, <strong>eficiência energética</strong> e <strong>capacidade de executar algoritmos avançados</strong>, incluindo inteligência artificial embarcada, controle em tempo real e processamento digital de sinais.</p>



<p class="wp-block-paragraph">O grande diferencial tecnológico do STM32V8 está no uso de um <strong>processo de fabricação em 18 nm FD-SOI (Fully Depleted Silicon On Insulator)</strong>, aliado à integração de <strong>memória não volátil do tipo PCM (Phase-Change Memory)</strong> diretamente no chip. Essa combinação permite à ST superar limitações clássicas dos microcontroladores baseados em Flash tradicional, como latência de acesso à memória, consumo energético elevado durante escrita e restrições de escalabilidade em nós tecnológicos mais avançados.</p>



<p class="wp-block-paragraph">No núcleo computacional, o STM32V8 é baseado no <strong>Arm Cortex-M85</strong>, atualmente o núcleo mais poderoso da família Cortex-M. Esse núcleo oferece suporte nativo a <strong>extensões Helium (M-Profile Vector Extension)</strong> para aceleração de DSP (Processamento Digital de Sinais) e workloads de machine learning, além de um pipeline mais profundo e recursos avançados de predição e paralelismo interno. Com frequências de operação significativamente mais altas que gerações anteriores, o STM32V8 se posiciona como um microcontrolador que começa a ocupar o espaço tradicionalmente reservado a microprocessadores de entrada, porém mantendo as vantagens de um MCU: determinismo, baixo consumo e integração periférica.</p>



<p class="wp-block-paragraph">Do ponto de vista prático, a ST posiciona o STM32V8 para aplicações como <strong>controle industrial avançado</strong>, <strong>robótica</strong>, <strong>automação predial e fabril</strong>, <strong>dispositivos médicos</strong>, <strong>edge AI</strong>, <strong>sensoriamento inteligente</strong> e <strong>sistemas ciberfísicos</strong>. O objetivo é permitir que arquiteturas antes dependentes de SoCs com Linux ou coprocessadores externos possam ser implementadas em um único microcontrolador, reduzindo custo, consumo, complexidade de software e requisitos de certificação.</p>



<p class="wp-block-paragraph">Essa nova família não substitui as linhas STM32 já consolidadas (como STM32F, G, H ou U), mas inaugura uma <strong>nova classe de MCU dentro do portfólio da ST</strong>, voltada explicitamente para aplicações que exigem o máximo desempenho possível dentro do ecossistema Cortex-M. Nas próximas seções, serão detalhados os pilares tecnológicos do STM32V8, começando pela sua <strong>arquitetura de fabricação e sistema de memória</strong>, e posteriormente avançando para núcleo, periféricos, segurança e uma comparação técnica objetiva com o <strong>Renesas RA8M1</strong>.</p>



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



<h2 class="wp-block-heading"><strong>Seção 2 – Tecnologia de Fabricação do STM32V8: 18 nm FD-SOI e Memória PCM</strong></h2>



<p class="wp-block-paragraph">Um dos aspectos mais disruptivos do <strong>STM32V8</strong> não está apenas no núcleo Cortex-M85, mas principalmente na <strong>tecnologia de fabricação adotada pela STMicroelectronics</strong>. Pela primeira vez em microcontroladores de uso geral, a ST emprega um processo <strong>18 nm FD-SOI (Fully Depleted Silicon On Insulator)</strong> combinado com <strong>memória não volátil do tipo PCM (Phase-Change Memory)</strong> integrada no próprio chip. Essa escolha tem implicações diretas em desempenho, consumo, confiabilidade e escalabilidade tecnológica.</p>



<p class="wp-block-paragraph">A tecnologia <strong>FD-SOI</strong> difere significativamente do CMOS convencional utilizado em processos mais antigos (40 nm, 65 nm, 90 nm). No FD-SOI, o transistor é construído sobre uma camada isolante extremamente fina, o que reduz drasticamente correntes parasitas, melhora o controle eletrostático do canal e diminui a variabilidade dos transistores. Na prática, isso se traduz em <strong>menor consumo dinâmico e estático</strong>, <strong>maior frequência de operação</strong> e <strong>melhor comportamento térmico</strong>, fatores críticos para sistemas embarcados que operam 24/7 ou em ambientes industriais severos.</p>



<p class="wp-block-paragraph">Outro benefício importante do FD-SOI é a possibilidade de <strong>body biasing dinâmico</strong>, técnica que permite ajustar o limiar de tensão dos transistores por software ou hardware. Isso dá ao projetista a capacidade de <strong>priorizar desempenho ou eficiência energética em tempo real</strong>, algo particularmente relevante em aplicações que alternam entre modos de processamento intenso e estados de baixo consumo. Em um microcontrolador de alto desempenho como o STM32V8, esse recurso amplia significativamente a flexibilidade arquitetural do sistema.</p>



<p class="wp-block-paragraph">Complementando o processo de 18 nm, a ST substituiu a Flash tradicional por <strong>memória PCM (Phase-Change Memory)</strong>. Diferente da Flash, a PCM não depende de tunelamento de elétrons através de óxidos finos, o que elimina vários gargalos clássicos: latência elevada de leitura, alto consumo durante escrita e desgaste acelerado com ciclos de programação/apagamento. A PCM permite <strong>leituras praticamente tão rápidas quanto SRAM</strong>, com <strong>maior densidade</strong> e <strong>excelente retenção de dados</strong>, mesmo em temperaturas elevadas.</p>



<p class="wp-block-paragraph">Do ponto de vista prático de firmware, a presença da PCM impacta diretamente a forma como o código é executado. O STM32V8 consegue operar em <strong>execução direta da memória não volátil (XIP – Execute In Place)</strong> sem as penalidades comuns da Flash, reduzindo ou até eliminando a necessidade de copiar rotinas críticas para RAM. Isso simplifica o linker script, reduz o uso de SRAM e melhora o determinismo temporal — um ponto fundamental para <strong>RTOS, controle em tempo real e aplicações safety-critical</strong>.</p>



<p class="wp-block-paragraph">Além disso, a PCM é naturalmente mais adequada a nós tecnológicos avançados, o que garante <strong>longevidade à família STM32V8</strong>. Enquanto a Flash enfrenta sérias dificuldades de escalabilidade abaixo de 28 nm, a PCM se mantém viável em processos ainda menores, preparando o caminho para futuras evoluções da linha sem rupturas arquiteturais. Para desenvolvedores e fabricantes de equipamentos, isso significa <strong>maior segurança de investimento e continuidade de plataforma</strong>.</p>



<p class="wp-block-paragraph">Na próxima seção, entraremos no coração computacional do STM32V8, analisando em detalhes o <strong>núcleo Arm Cortex-M85</strong>, suas extensões vetoriais, impacto prático em DSP e inteligência artificial embarcada, e como isso redefine o limite do que se espera de um microcontrolador.</p>



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



<h2 class="wp-block-heading"><strong>Núcleo Arm Cortex-M85 no STM32V8: Desempenho, DSP e Inteligência Artificial Embarcada</strong></h2>



<p class="wp-block-paragraph">No centro do <strong>STM32V8</strong> está o <strong>Arm Cortex-M85</strong>, atualmente o núcleo mais avançado da família Cortex-M. Sua adoção não representa apenas um incremento incremental de desempenho, mas sim uma mudança de patamar naquilo que é possível executar em um microcontrolador sem recorrer a microprocessadores ou aceleradores externos. A ST posiciona o STM32V8 como uma plataforma capaz de consolidar <strong>controle em tempo real, processamento de sinais e inferência de modelos de inteligência artificial</strong> em um único dispositivo.</p>



<p class="wp-block-paragraph">O Cortex-M85 introduz um pipeline mais profundo e otimizado em relação a núcleos anteriores como o Cortex-M7 ou M33, permitindo frequências de operação significativamente mais altas. No contexto do STM32V8, isso se traduz em um MCU capaz de executar centenas de milhões de instruções por segundo, mantendo características fundamentais de sistemas embarcados, como <strong>determinismo temporal</strong>, <strong>interrupções de baixa latência</strong> e <strong>execução previsível</strong>, essenciais para aplicações industriais, automotivas e médicas.</p>



<p class="wp-block-paragraph">Um dos principais diferenciais técnicos do Cortex-M85 é o suporte nativo às <strong>extensões Helium</strong>, também conhecidas como <strong>M-Profile Vector Extension (MVE)</strong>. Essas extensões introduzem um conjunto de instruções vetoriais SIMD (Single Instruction, Multiple Data), permitindo que operações matemáticas sejam executadas em paralelo sobre múltiplos dados. Na prática, isso acelera de forma expressiva algoritmos de <strong>DSP</strong>, como filtros FIR e IIR, FFTs, convoluções, correlação e operações matriciais, amplamente utilizadas em controle, áudio, vibração, sensores e comunicações industriais.</p>



<p class="wp-block-paragraph">No campo da <strong>inteligência artificial embarcada</strong>, o impacto é ainda mais relevante. O Cortex-M85 foi projetado para executar inferência de redes neurais leves diretamente no MCU, especialmente modelos de <strong>machine learning para edge computing</strong>, como classificadores, detectores de padrões e modelos de regressão. Quando combinado com bibliotecas otimizadas como <strong>CMSIS-DSP</strong> e <strong>CMSIS-NN</strong>, o STM32V8 passa a executar modelos treinados em frameworks como TensorFlow Lite Micro com desempenho antes restrito a SoCs mais complexos.</p>



<p class="wp-block-paragraph">Do ponto de vista prático de desenvolvimento, isso significa que tarefas como <strong>detecção de anomalias</strong>, <strong>classificação de sinais</strong>, <strong>reconhecimento de padrões em sensores</strong>, <strong>monitoramento preditivo</strong> e <strong>processamento inteligente de dados</strong> podem ser implementadas diretamente no microcontrolador, sem dependência de sistemas operacionais complexos ou unidades externas de processamento. Além de reduzir consumo e custo, essa abordagem melhora a confiabilidade do sistema e reduz latências críticas.</p>



<p class="wp-block-paragraph">Outro aspecto importante do Cortex-M85 é o avanço nos mecanismos de <strong>segurança e isolamento</strong>, especialmente quando combinado com arquiteturas compatíveis com <strong>TrustZone para Cortex-M</strong>. Embora o foco principal do STM32V8 seja desempenho, a presença de recursos modernos de proteção de memória, execução segura e separação de contextos torna o dispositivo adequado a aplicações conectadas, onde segurança cibernética é um requisito básico e não opcional.</p>



<p class="wp-block-paragraph">Em síntese, o núcleo Cortex-M85 transforma o STM32V8 em um microcontrolador que atua como uma <strong>plataforma computacional completa</strong>, capaz de unificar controle, processamento de sinais e inteligência artificial. Na próxima seção, será analisada a <strong>arquitetura de memória e subsistema de interconexão</strong> do STM32V8, explorando como a combinação de PCM, SRAM e barramentos internos sustenta esse nível de desempenho de forma determinística e eficiente.</p>



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



<h2 class="wp-block-heading"><strong>Arquitetura de Memória e Execução no STM32V8</strong></h2>



<p class="wp-block-paragraph">O desempenho elevado do <strong>STM32V8</strong> não é resultado apenas do núcleo Cortex-M85 ou do processo de fabricação em 18 nm, mas da forma como a <strong>arquitetura de memória</strong> foi projetada para sustentar cargas computacionais intensas com previsibilidade temporal. A ST adotou uma abordagem que combina <strong>memória PCM de alta velocidade</strong>, <strong>SRAM interna otimizada</strong> e um <strong>subsistema de barramentos de alta largura de banda</strong>, criando uma base sólida para aplicações em tempo real, DSP e inteligência artificial embarcada.</p>



<p class="wp-block-paragraph">A <strong>memória PCM (Phase-Change Memory)</strong> atua como principal memória não volátil do sistema, substituindo completamente a Flash tradicional. Diferente da Flash, cujo acesso pode introduzir estados de espera (wait states) em altas frequências, a PCM oferece <strong>latência significativamente menor e mais previsível</strong>, permitindo que o núcleo execute código diretamente da memória não volátil com impacto mínimo no desempenho. Isso reduz a necessidade de técnicas clássicas, como cópia de código crítico para RAM, simplificando o projeto de firmware e melhorando o determinismo.</p>



<p class="wp-block-paragraph">A <strong>SRAM interna</strong> complementa a PCM, sendo utilizada para dados, pilhas, heaps, buffers de comunicação e estruturas temporárias exigidas por algoritmos de DSP e IA. No STM32V8, essa SRAM é distribuída de forma estratégica no mapa de memória, permitindo acessos paralelos e reduzindo contenções no barramento. Essa organização é particularmente importante quando múltiplos mestres — como o núcleo, DMA e aceleradores internos — competem por acesso à memória.</p>



<p class="wp-block-paragraph">O subsistema de interconexão interna do STM32V8 foi projetado para acompanhar o aumento de desempenho do núcleo. Barramentos de alta velocidade interligam o Cortex-M85 às memórias e periféricos, garantindo <strong>baixa latência em acessos críticos</strong> e <strong>previsibilidade temporal</strong>. Para aplicações em tempo real, essa previsibilidade é tão importante quanto a velocidade bruta, pois garante que interrupções, tarefas de RTOS e rotinas de controle cumpram seus prazos de execução.</p>



<p class="wp-block-paragraph">Do ponto de vista prático, essa arquitetura favorece fortemente o uso de <strong>RTOS como FreeRTOS ou Zephyr</strong>, permitindo que múltiplas tarefas executem algoritmos complexos sem interferências imprevisíveis. Em sistemas de controle avançado, por exemplo, é possível isolar tarefas de aquisição de sensores, processamento vetorial e comunicação, mantendo comportamento determinístico mesmo sob carga elevada.</p>



<p class="wp-block-paragraph">Outro ponto relevante é o impacto dessa arquitetura na <strong>eficiência energética</strong>. A menor latência da PCM reduz o tempo total de execução das instruções, permitindo que o microcontrolador entre mais rapidamente em estados de baixo consumo. Aliado aos recursos do FD-SOI, como body biasing dinâmico, o STM32V8 consegue equilibrar alto desempenho com consumo otimizado, algo essencial em aplicações industriais e embarcadas que operam continuamente.</p>



<p class="wp-block-paragraph">Em resumo, a arquitetura de memória do STM32V8 foi concebida para remover gargalos históricos dos microcontroladores de alto desempenho, oferecendo uma plataforma onde execução direta da memória, acesso previsível e alto paralelismo são características intrínsecas. Na próxima seção, o foco será a <strong>integração de periféricos, interfaces e capacidades de sistema</strong>, analisando como o STM32V8 se posiciona em aplicações reais de automação, controle e edge computing.</p>



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



<h2 class="wp-block-heading"><strong>Periféricos, Interfaces e Aplicações Práticas do STM32V8</strong></h2>



<p class="wp-block-paragraph">Além do avanço significativo em núcleo, processo de fabricação e arquitetura de memória, o <strong>STM32V8</strong> foi concebido como um microcontrolador altamente integrado, capaz de atender sistemas complexos sem a necessidade de circuitos externos adicionais. A ST mantém a filosofia histórica da família STM32: oferecer um <strong>ecossistema robusto de periféricos</strong>, com forte integração a ferramentas de software e suporte de longo prazo, agora elevado a um novo patamar de desempenho.</p>



<p class="wp-block-paragraph">Embora a publicação oficial foque principalmente nos avanços tecnológicos de processo e memória, o posicionamento do STM32V8 indica claramente a presença de um conjunto completo de <strong>periféricos de alto desempenho</strong>, incluindo temporizadores avançados, interfaces de comunicação industriais e subsistemas de conversão analógica. Esses recursos são essenciais para aplicações que combinam <strong>controle em tempo real</strong>, <strong>aquisição de sinais</strong> e <strong>processamento intensivo</strong> em um único dispositivo.</p>



<p class="wp-block-paragraph">No contexto de controle e automação, temporizadores de alta resolução e baixo jitter permitem a implementação de <strong>controle de motores</strong>, <strong>conversores de potência</strong>, <strong>robótica</strong> e <strong>sistemas mecatrônicos</strong> com precisão elevada. A capacidade de executar algoritmos complexos diretamente no MCU possibilita a adoção de técnicas mais sofisticadas, como controle preditivo, observadores de estado e filtragem adaptativa, sem comprometer os requisitos temporais do sistema.</p>



<p class="wp-block-paragraph">As <strong>interfaces de comunicação</strong> desempenham um papel central no posicionamento do STM32V8 em aplicações modernas. Protocolos seriais de alta velocidade, combinados com suporte a comunicação determinística, tornam o dispositivo adequado para <strong>redes industriais</strong>, <strong>sistemas distribuídos</strong> e <strong>edge computing</strong>. Em aplicações conectadas, o alto desempenho do núcleo Cortex-M85 permite que pilhas de comunicação, criptografia e segurança sejam executadas em paralelo com tarefas de controle e processamento de sinais.</p>



<p class="wp-block-paragraph">Um aspecto particularmente relevante é a viabilidade prática de consolidar múltiplas funções em um único microcontrolador. Em projetos tradicionais, seria comum dividir responsabilidades entre um MCU de controle e um processador dedicado a processamento de sinais ou inferência de IA. Com o STM32V8, essa separação se torna desnecessária em muitos casos, reduzindo <strong>custo de hardware</strong>, <strong>consumo energético</strong>, <strong>complexidade de software</strong> e <strong>pontos potenciais de falha</strong>.</p>



<p class="wp-block-paragraph">Do ponto de vista de desenvolvimento, o STM32V8 se beneficia diretamente do ecossistema já consolidado da ST, incluindo <strong>STM32Cube</strong>, bibliotecas HAL e LL, suporte a <strong>RTOS</strong>, além de integração com ferramentas de depuração e profiling. Isso reduz significativamente a curva de aprendizado, permitindo que equipes que já dominam a família STM32 migrem para o STM32V8 sem ruptura conceitual, mesmo diante de uma arquitetura significativamente mais avançada.</p>



<p class="wp-block-paragraph">Em aplicações práticas, o STM32V8 se posiciona como uma plataforma ideal para <strong>manutenção preditiva</strong>, <strong>monitoramento inteligente</strong>, <strong>processamento de sinais vibroacústicos</strong>, <strong>edge AI industrial</strong>, <strong>instrumentação avançada</strong> e <strong>sistemas ciberfísicos</strong>. A capacidade de executar algoritmos complexos localmente, com baixa latência e alto grau de determinismo, atende diretamente às demandas atuais da Indústria 4.0 e de sistemas embarcados inteligentes.</p>



<p class="wp-block-paragraph">Na próxima seção, será apresentada uma <strong>comparação técnica objetiva entre o STM32V8 e o Renesas RA8M1</strong>, destacando semelhanças, diferenças arquiteturais e cenários em que cada plataforma se mostra mais adequada.</p>



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



<h2 class="wp-block-heading"><strong>Seção 6 – Comparação Técnica: STM32V8 versus Renesas RA8M1</strong></h2>



<p class="wp-block-paragraph">A comparação entre o <strong>STM32V8</strong>, da STMicroelectronics, e o <strong>Renesas RA8M1</strong> é particularmente relevante porque ambos são baseados no <strong>núcleo Arm Cortex-M85</strong> e se posicionam no segmento de <strong>microcontroladores de altíssimo desempenho</strong>. Apesar dessa similaridade fundamental, as duas plataformas adotam <strong>estratégias arquiteturais distintas</strong>, refletindo visões diferentes sobre escalabilidade, memória, eficiência energética e foco de aplicação.</p>



<p class="wp-block-paragraph">Do ponto de vista de <strong>núcleo e capacidade computacional</strong>, ambos utilizam o Cortex-M85 com suporte às extensões Helium (MVE), o que garante excelente desempenho em DSP e workloads de machine learning. No entanto, o STM32V8 se beneficia diretamente do processo de fabricação em <strong>18 nm FD-SOI</strong>, permitindo frequências mais elevadas e melhor controle de consumo dinâmico em comparação ao RA8M1, que é fabricado em um processo CMOS mais convencional. Na prática, isso favorece o STM32V8 em aplicações que exigem desempenho sustentado com controle térmico rigoroso.</p>



<p class="wp-block-paragraph">A diferença mais marcante entre as duas plataformas está no <strong>sistema de memória não volátil</strong>. O Renesas RA8M1 utiliza <strong>Flash embutida tradicional</strong>, complementada por uma quantidade significativa de SRAM. Essa abordagem é madura, amplamente conhecida e bem suportada por ferramentas, mas impõe limitações de latência e escalabilidade em altas frequências. O STM32V8, por outro lado, elimina a Flash e adota <strong>memória PCM</strong>, oferecendo menor latência de acesso, maior previsibilidade temporal e melhor adequação a nós tecnológicos avançados. Para aplicações em tempo real estrito, essa diferença é particularmente relevante.</p>



<p class="wp-block-paragraph">Em termos de <strong>arquitetura de execução</strong>, o STM32V8 apresenta vantagens claras na execução direta da memória não volátil (XIP) sem penalidades significativas, enquanto o RA8M1 pode exigir estratégias adicionais, como cache ou cópia seletiva de código para RAM, em aplicações mais exigentes. Isso impacta diretamente a complexidade do firmware e o esforço de otimização por parte do desenvolvedor.</p>



<p class="wp-block-paragraph">No campo da <strong>eficiência energética</strong>, ambos os dispositivos são projetados para aplicações embarcadas modernas, mas o uso de FD-SOI no STM32V8 introduz recursos adicionais, como <strong>body biasing dinâmico</strong>, que permitem ajustes finos entre desempenho e consumo em tempo de execução. O RA8M1 mantém uma abordagem mais tradicional, eficiente e confiável, porém com menor flexibilidade nesse aspecto específico.</p>



<p class="wp-block-paragraph">Do ponto de vista de <strong>ecossistema e maturidade</strong>, o RA8M1 se beneficia da forte integração com o <strong>Renesas Flexible Software Package (FSP)</strong>, oferecendo uma pilha de software bem estruturada e voltada para aplicações industriais e comerciais. O STM32V8, por sua vez, herda o vasto ecossistema <strong>STM32Cube</strong>, amplamente difundido, com suporte consolidado a RTOS, middleware e ferramentas de desenvolvimento, o que pode representar uma vantagem estratégica para equipes já familiarizadas com o universo STM32.</p>



<p class="wp-block-paragraph">Em síntese, o <strong>Renesas RA8M1</strong> se apresenta como uma plataforma robusta, madura e altamente capaz para aplicações industriais de alto desempenho, enquanto o <strong>STM32V8</strong> avança além, explorando novas tecnologias de fabricação e memória para atingir um nível superior de desempenho, previsibilidade e escalabilidade futura. A escolha entre as duas soluções dependerá diretamente dos requisitos do projeto, especialmente no que se refere a latência, consumo, longevidade tecnológica e complexidade de software aceitável.</p>



<p class="wp-block-paragraph">Na próxima e última seção, será apresentada a <strong>conclusão do artigo</strong>, seguida da <strong>lista de fontes utilizadas</strong>, conforme solicitado.</p>



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



<h2 class="wp-block-heading"><strong>Seção 7 – Conclusão e Fontes</strong></h2>



<h3 class="wp-block-heading"><strong>Conclusão</strong></h3>



<p class="wp-block-paragraph">O <strong>STM32V8</strong> representa um marco importante na evolução dos microcontroladores, não apenas dentro do portfólio da STMicroelectronics, mas no mercado de sistemas embarcados como um todo. Ao combinar o núcleo <strong>Arm Cortex-M85</strong> com um processo de fabricação avançado em <strong>18 nm FD-SOI</strong> e a adoção inédita de <strong>memória PCM</strong>, a ST redefine os limites tradicionais entre microcontroladores e microprocessadores de entrada. Essa abordagem permite alcançar níveis de desempenho, eficiência energética e previsibilidade temporal que antes exigiam arquiteturas mais complexas.</p>



<p class="wp-block-paragraph">Do ponto de vista técnico, o STM32V8 se destaca pela execução eficiente de <strong>DSP e inteligência artificial embarcada</strong>, suportada por extensões vetoriais Helium e por uma arquitetura de memória capaz de sustentar altas taxas de processamento sem os gargalos clássicos da Flash. Para o desenvolvedor, isso se traduz em projetos mais simples, com menor necessidade de otimizações manuais, cópias de código para RAM ou uso de dispositivos auxiliares.</p>



<p class="wp-block-paragraph">Na comparação com o <strong>Renesas RA8M1</strong>, fica evidente que ambas as plataformas ocupam o topo do segmento Cortex-M. Entretanto, o STM32V8 adota uma postura mais agressiva em termos de inovação tecnológica, priorizando escalabilidade futura, menor latência e maior flexibilidade energética. Já o RA8M1 se posiciona como uma solução madura, robusta e alinhada a arquiteturas tradicionais, o que pode ser uma vantagem em projetos que valorizam estabilidade e continuidade de design.</p>



<p class="wp-block-paragraph">Em aplicações práticas, o STM32V8 surge como uma plataforma especialmente atraente para <strong>automação industrial avançada</strong>, <strong>edge AI</strong>, <strong>manutenção preditiva</strong>, <strong>instrumentação inteligente</strong>, <strong>robótica</strong> e <strong>sistemas ciberfísicos</strong>, onde alto desempenho, determinismo e integração são requisitos fundamentais. Seu lançamento sinaliza uma tendência clara: o futuro dos microcontroladores passa pela convergência entre computação intensiva, eficiência energética e inteligência embarcada.</p>



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



<h3 class="wp-block-heading"><strong>Fontes Utilizadas</strong></h3>



<ol class="wp-block-list">
<li><strong>STMicroelectronics – Press Release</strong><br><em>ST unveils STM32V8 microcontroller with embedded phase-change memory on 18nm FD-SOI technology</em><br>Disponível em:<br><a href="https://newsroom.st.com/media-center/press-item.html/p4733.html">https://newsroom.st.com/media-center/press-item.html/p4733.html</a></li>



<li><strong>Renesas Electronics – RA8M1 Product Page</strong><br><em>RA8M1 – 480 MHz Arm Cortex-M85 MCU</em><br>Disponível em:<br><a href="https://www.renesas.com/en/products/ra8m1">https://www.renesas.com/en/products/ra8m1</a></li>
</ol><p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/stm32v8-o-novo-microcontrolador-da-st-com-cortex-m85-pcm-e-tecnologia-18-nm-fd-soi/">STM32V8: o novo microcontrolador da ST com Cortex-M85, PCM e tecnologia 18 nm FD-SOI</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1032</post-id>	</item>
		<item>
		<title>Como Funcionam os Fuse Bits (Option Bytes) nos Microcontroladores STM32: Parametrização e Segurança do Firmware</title>
		<link>https://mcu.tec.br/microcontroladores/stm32/como-funcionam-os-fuse-bits-option-bytes-nos-microcontroladores-stm32-parametrizacao-e-seguranca-do-firmware/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-funcionam-os-fuse-bits-option-bytes-nos-microcontroladores-stm32-parametrizacao-e-seguranca-do-firmware</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Sat, 13 Dec 2025 12:44:21 +0000</pubDate>
				<category><![CDATA[STM32]]></category>
		<category><![CDATA[bootloader STM32]]></category>
		<category><![CDATA[BOR]]></category>
		<category><![CDATA[fuse bits]]></category>
		<category><![CDATA[option bytes]]></category>
		<category><![CDATA[parametrização de microcontroladores]]></category>
		<category><![CDATA[PCROP]]></category>
		<category><![CDATA[proteção contra cópia]]></category>
		<category><![CDATA[proteção de firmware]]></category>
		<category><![CDATA[RDP]]></category>
		<category><![CDATA[segurança embarcada]]></category>
		<category><![CDATA[st-flash]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[STM32CubeProgrammer]]></category>
		<category><![CDATA[TrustZone]]></category>
		<category><![CDATA[watchdog]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=986</guid>

					<description><![CDATA[<p>Os microcontroladores STM32 utilizam Option Bytes como um sistema equivalente aos fuse bits tradicionais, permitindo configurar parâmetros essenciais de operação e segurança do firmware. Esses recursos controlam proteção de leitura, modos de boot, watchdogs, níveis de BROWN-OUT, TrustZone e outras funções críticas. Este artigo explica de forma didática o papel de cada Option Byte, seus usos práticos, como configurá-los com o STM32CubeProgrammer e como gravá-los via st-flash, garantindo maior segurança, confiabilidade e proteção intelectual em projetos embarcados.</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/como-funcionam-os-fuse-bits-option-bytes-nos-microcontroladores-stm32-parametrizacao-e-seguranca-do-firmware/">Como Funcionam os Fuse Bits (Option Bytes) nos Microcontroladores STM32: Parametrização e Segurança do Firmware</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading"><strong>1. Introdução ao Sistema de Fuse Bits em STM32</strong></h2>



<p class="wp-block-paragraph">Em microcontroladores AVR e PIC, o termo <strong>fuse bits</strong> refere-se a configurações permanentes que controlam parâmetros do chip, como fontes de clock e mecanismos de proteção.<br>Nos <strong>STM32</strong>, o equivalente funcional são os <strong>Option Bytes</strong>, valores gravados em áreas especiais da <strong>Flash</strong> ou do <strong>Flash System Memory</strong>, usados para definir comportamento de boot, níveis de proteção, watchdog, brown-out e recursos de segurança.</p>



<p class="wp-block-paragraph">Embora não sejam chamados literalmente de fuse bits, sua função é <strong>idêntica</strong>:<br>configurar <strong>parametrização estrutural</strong> e <strong>segurança do firmware</strong>, alterando características que o software comum <strong>não pode modificar livremente</strong>.</p>



<p class="wp-block-paragraph">Essas opções são fundamentais em projetos profissionais porque permitem:</p>



<ul class="wp-block-list">
<li>proteger a propriedade intelectual do firmware,</li>



<li>impedir gravações não autorizadas,</li>



<li>definir mecanismos de boot seguro,</li>



<li>reforçar a confiabilidade do sistema.</li>
</ul>



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



<h3 class="wp-block-heading"><strong>2. Estrutura dos Option Bytes nos STM32</strong></h3>



<p class="wp-block-paragraph">Os Option Bytes variam levemente entre famílias (F1, F4, G0, L0, H7 etc.), mas a estrutura típica inclui:</p>



<h4 class="wp-block-heading"><strong>2.1 RDP – Readout Protection Level (Proteção de Leitura)</strong></h4>



<p class="wp-block-paragraph">Controla a <strong>proteção contra cópia do firmware</strong>.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Nível</th><th>Significado</th></tr></thead><tbody><tr><td><strong>RDP Level 0</strong></td><td>Sem proteção. Pode ler e gravar a flash normalmente.</td></tr><tr><td><strong>RDP Level 1</strong></td><td>Impede leitura da Flash via debugger. Gravação ainda permitida, mas leitura é bloqueada.</td></tr><tr><td><strong>RDP Level 2</strong></td><td>Proteção total e irreversível. Impede leitura e impede retorno ao nível 0.</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><strong>Uso:</strong><br>Aplicado em produtos comerciais onde há risco de pirataria. A maior parte dos fabricantes usa <strong>Level 1</strong>.</p>



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



<h4 class="wp-block-heading"><strong>2.2 BOR – Brown-Out Reset (Níveis de Reset por Queda de Tensão)</strong></h4>



<p class="wp-block-paragraph">Configura o limite de tensão abaixo do qual o MCU deve reiniciar para evitar corrupção.</p>



<p class="wp-block-paragraph">Níveis típicos: <strong>OFF, 2.1V, 2.4V, 2.7V</strong>.</p>



<p class="wp-block-paragraph"><strong>Função:</strong><br>Evita operação instável quando a fonte cai momentaneamente.</p>



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



<h4 class="wp-block-heading"><strong>2.3 nBOOT0, nBOOT1 e BOOT_LOCK</strong></h4>



<p class="wp-block-paragraph">Controlam a lógica de boot:</p>



<ul class="wp-block-list">
<li><strong>nBOOT0 / nBOOT1:</strong> Selecionam se o MCU irá iniciar pela Flash, SRAM ou System Memory (bootloader da ST).</li>



<li><strong>BOOT_LOCK:</strong> Impede alterações nos bits de boot para fortalecer a segurança.</li>
</ul>



<p class="wp-block-paragraph"><strong>Uso comum:</strong><br>Permitir que o dispositivo inicialize sempre pela Flash e não aceite boot por RAM para evitar ataques.</p>



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



<h4 class="wp-block-heading"><strong>2.4 WWDG_SW e IWDG_SW (Watchdog em Hardware ou Software)</strong></h4>



<p class="wp-block-paragraph">Determinam se o watchdog é controlado:</p>



<ul class="wp-block-list">
<li><strong>por software</strong>, ou</li>



<li><strong>apenas por hardware</strong>, impedindo que o firmware o desative.</li>
</ul>



<p class="wp-block-paragraph"><strong>Uso:</strong><br>Aplicado em sistemas críticos onde segurança funcional exige watchdog sempre ativo.</p>



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



<h4 class="wp-block-heading"><strong>2.5 IWDG_STOP e IWDG_STDBY</strong></h4>



<p class="wp-block-paragraph">Definem se o <strong>Independent Watchdog</strong> deve continuar funcionando nos modos:</p>



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



<li>STANDBY</li>
</ul>



<p class="wp-block-paragraph"><strong>Uso:</strong><br>Sistemas que não podem “congelar” a supervisão durante redução de consumo.</p>



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



<h4 class="wp-block-heading"><strong>2.6 nRST_STOP e nRST_STDBY</strong></h4>



<p class="wp-block-paragraph">Controlam se a saída de reset deve ser acionada ao sair de STOP/STANDBY.</p>



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



<h4 class="wp-block-heading"><strong>2.7 PCROP (Proprietary Code Protection)</strong></h4>



<p class="wp-block-paragraph">Protege áreas específicas da Flash contra:</p>



<ul class="wp-block-list">
<li>leitura externa,</li>



<li>escrita,</li>



<li>apagamento.</li>
</ul>



<p class="wp-block-paragraph"><strong>Uso:</strong><br>Indicado quando há uma “biblioteca” proprietária dentro do firmware.</p>



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



<h3 class="wp-block-heading"><strong>2.8 Security Bit / TZEN (em MCUs com TrustZone)</strong></h3>



<p class="wp-block-paragraph">Em STM32L5, U5 e H5:</p>



<ul class="wp-block-list">
<li><strong>TZEN = TrustZone Enable</strong><br>Ativa a arquitetura segura (Secure/Non-Secure).</li>
</ul>



<p class="wp-block-paragraph"><strong>Uso:</strong><br>Gerenciamento de zonas seguras, criptografia, updates protegidos.</p>



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



<h1 class="wp-block-heading"><strong>3. Ferramentas para Configuração dos Option Bytes</strong></h1>



<h3 class="wp-block-heading"><strong>3.1 STM32CubeProgrammer (Método Oficial)</strong></h3>



<p class="wp-block-paragraph">Ferramenta gráfica da ST que permite:</p>



<ul class="wp-block-list">
<li>ler Option Bytes,</li>



<li>alterar valores,</li>



<li>editar níveis de RDP,</li>



<li>configurar BOR, watchdog, PCROP, TrustZone,</li>



<li>gravar firmware via SWD, JTAG, UART, USB DFU.</li>
</ul>



<p class="wp-block-paragraph">Interface intuitiva com abas dedicadas a cada Option Byte.</p>



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



<h3 class="wp-block-heading"><strong>3.2 ST-Link Utility (antiga, mas ainda usada)</strong></h3>



<p class="wp-block-paragraph">Ferramenta clássica para MCUs STM32F e STM32L.<br>Permite edição direta dos Option Bytes com rapidez.</p>



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



<h1 class="wp-block-heading"><strong>4. Gravando o Firmware e Option Bytes via st-flash (CLI)</strong></h1>



<p class="wp-block-paragraph">A ferramenta <strong>st-flash</strong>, parte do pacote <strong>stlink</strong>, permite gravação via linha de comando.</p>



<h3 class="wp-block-heading"><strong>4.1 Gravando firmware</strong></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>st-flash write firmware.bin 0x08000000
</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">st</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">flash</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">write</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">firmware</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">bin</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x08000000</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>4.2 Lendo Option Bytes</strong></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>st-flash read option_bytes.bin 0x1FFF7800 256
</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">st</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">flash</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">read</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">option_bytes</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">bin</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x1FFF7800</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">256</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>4.3 Gravando Option Bytes</strong></h3>



<p class="wp-block-paragraph">Os Option Bytes ficam em endereços especiais dependendo da família.<br>Após atualizar os OBs, o chip <strong>reinicia automaticamente</strong>, aplicando as novas configurações.</p>



<p class="wp-block-paragraph">st-flash também informa erros comuns como:</p>



<ul class="wp-block-list">
<li>tentativa de gravar OBs protegidos,</li>



<li>violação de RDP,</li>



<li>incompatibilidade com certos níveis de segurança.</li>
</ul>



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



<h1 class="wp-block-heading"><strong>5. Considerações de Segurança e Boas Práticas</strong></h1>



<ol class="wp-block-list">
<li><strong>Nunca aplique RDP Level 2 antes dos testes finais.</strong><br>É irreversível.</li>



<li><strong>Ative BOR em sistemas alimentados por baterias ou fontes ruidosas.</strong></li>



<li><strong>Habilite watchdog por hardware em sistemas críticos.</strong></li>



<li><strong>Use PCROP para proteger bibliotecas ou algoritmos proprietários.</strong></li>



<li><strong>Em MCUs com TrustZone, habilite TZEN apenas com particionamento seguro já definido.</strong></li>



<li><strong>Documente todos os Option Bytes usados no projeto.</strong><br>Isso evita perda de configurações em futuras versões.</li>
</ol>



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



<h1 class="wp-block-heading"><strong>6. Conclusão</strong></h1>



<p class="wp-block-paragraph">O sistema de “fuse bits”, representado pelos <strong>Option Bytes</strong>, é um dos pilares de segurança e parametrização nos microcontroladores STM32. Ele define desde o comportamento básico de boot até proteções avançadas como RDP, PCROP e TrustZone.<br>A correta configuração desses parâmetros, aliada a ferramentas como <strong>STM32CubeProgrammer</strong>, <strong>ST-Link Utility</strong> e <strong>st-flash</strong>, garante firmware seguro, protegido contra cópia, e aumenta a confiabilidade do sistema embarcado.</p><p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/como-funcionam-os-fuse-bits-option-bytes-nos-microcontroladores-stm32-parametrizacao-e-seguranca-do-firmware/">Como Funcionam os Fuse Bits (Option Bytes) nos Microcontroladores STM32: Parametrização e Segurança do Firmware</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">986</post-id>	</item>
		<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>TrustZone em Microcontroladores Cortex-M: Segurança por Hardware na Arquitetura ARMv8-M</title>
		<link>https://mcu.tec.br/microcontroladores/stm32/trustzone-em-microcontroladores-cortex-m-seguranca-por-hardware-na-arquitetura-armv8-m/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=trustzone-em-microcontroladores-cortex-m-seguranca-por-hardware-na-arquitetura-armv8-m</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Wed, 10 Dec 2025 11:46:07 +0000</pubDate>
				<category><![CDATA[STM32]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=977</guid>

					<description><![CDATA[<p>A TrustZone para microcontroladores Cortex-M introduz um modelo avançado de segurança por hardware dentro da arquitetura ARMv8-M, permitindo isolar código crítico do restante da aplicação em ambientes seguro e não seguro. Neste artigo, explore como a TrustZone funciona, quais núcleos Cortex-M oferecem suporte, os benefícios de implementar segurança embarcada nativa e como fabricantes como a STMicroelectronics utilizam esse recurso em linhas como STM32L5, U5, H5 e H7RS. Entenda também como dividir projetos entre domínios seguros, como configurar o particionamento no STM32CubeIDE e por que esse recurso é essencial para IoT, automação industrial e aplicações que exigem proteção robusta de firmware, chaves criptográficas e boot seguro.</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/trustzone-em-microcontroladores-cortex-m-seguranca-por-hardware-na-arquitetura-armv8-m/">TrustZone em Microcontroladores Cortex-M: Segurança por Hardware na Arquitetura ARMv8-M</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading"><strong>Introdução ao TrustZone em Microcontroladores Cortex-M</strong></h2>



<p class="wp-block-paragraph">O TrustZone é um mecanismo de segurança introduzido pela ARM para permitir que um único microcontrolador opere, simultaneamente, em <strong>dois domínios de execução isolados</strong>: um ambiente <strong>Seguro (Secure World)</strong> e outro <strong>Não Seguro (Non-Secure World)</strong>. O objetivo é tornar possível a execução de código sensível — como rotinas criptográficas, gerência de chaves, boot seguro e proteção de firmware — em uma região fortemente protegida, mesmo quando o restante da aplicação (pilhas de comunicação, drivers externos, interfaces ricas) roda em modo normal, sem privilégios especiais.</p>



<p class="wp-block-paragraph">Esse isolamento não é apenas conceitual; ele ocorre <strong>na própria arquitetura do processador</strong>, permitindo separar memória, periféricos e fluxos de execução. Assim, mesmo que uma vulnerabilidade atinja o lado não seguro (por exemplo, uma pilha TCP/IP, que costuma ser alvo frequente de ataques), o domínio seguro permanece protegido, evitando que partes críticas sejam comprometidas.</p>



<p class="wp-block-paragraph">No contexto dos microcontroladores, o TrustZone transformou a forma como desenhamos a segurança embarcada. Diferentemente de soluções externas — como chips de criptografia dedicados, secure elements ou processadores duplos — o TrustZone oferece um <strong>modelo integrado, leve e com baixo custo</strong>, ideal para produtos IoT, industriais e automotivos, onde segurança e eficiência energética são essenciais.</p>



<p class="wp-block-paragraph">Essa tecnologia está disponível apenas nos microcontroladores baseados na <strong>Arquitetura ARMv8-M</strong>, que trouxe extensões específicas para oferecer segurança por hardware sem adicionar complexidade excessiva ao pipeline do processador. A ARM desenvolveu dois perfis principais dessa arquitetura: um altamente seguro (arquitetura <strong>v8-M Security Extension</strong>) e outro otimizado para aplicações de tempo real, ambos podendo incorporar o TrustZone.</p>



<p class="wp-block-paragraph">Nos próximos capítulos, exploraremos em profundidade a arquitetura ARMv8-M dentro do contexto da TrustZone, quais núcleos Cortex-M suportam esse recurso, como as memórias são protegidas, exemplos com microcontroladores da STMicroelectronics e como projetar sistemas embarcados realmente seguros usando esses recursos.</p>



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



<h2 class="wp-block-heading"><strong>TrustZone e a Arquitetura ARMv8-M</strong></h2>



<p class="wp-block-paragraph">A introdução do TrustZone nos microcontroladores ARM ocorreu com a <strong>arquitetura ARMv8-M</strong>, que foi especialmente projetada para atender sistemas embarcados onde segurança e tempo real precisam coexistir. Ao contrário da TrustZone para processadores Cortex-A, voltada para sistemas complexos como smartphones e SBCs (Single Board Computers), a versão para Cortex-M foi completamente redesenhada para garantir baixa latência, simplicidade de configuração e compatibilidade com aplicações típicas de microcontroladores.</p>


<div class="wp-block-image">
<figure class="alignright size-full"><img decoding="async" width="208" height="242" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-14.png" alt="" class="wp-image-978"/></figure>
</div>


<p class="wp-block-paragraph">A ARMv8-M introduz um mecanismo de particionamento baseado em hardware capaz de dividir tanto a <strong>memória Flash e SRAM</strong> quanto os <strong>periféricos</strong> entre o mundo Seguro e o Não Seguro. Essa divisão é controlada principalmente pelo componente <strong>SAU (Security Attribution Unit)</strong> e pode ser complementada pelo <strong>IDAU (Implementation-Defined Attribution Unit)</strong>, que depende de cada fabricante de microcontrolador. A combinação de ambos define, de maneira determinística, quais regiões podem ser acessadas por cada domínio de execução. Assim, o processador pode garantir que um código considerado “não seguro” jamais consiga ler uma chave criptográfica, manipular um bootloader protegido ou sobrescrever blocos críticos da aplicação.</p>



<p class="wp-block-paragraph">Dentro dessa arquitetura, o processador mantém <strong>dois contextos paralelos</strong>, cada um com seu próprio stack pointer (PSP_NS e PSP_S para Non-Secure e Secure, respectivamente). A comutação entre eles é assistida por instruções dedicadas e ocorre com latência extremamente baixa — característica essencial para preservar o comportamento de sistemas de tempo real. Além disso, funções seguras podem ser expostas por meio de “<strong>Secure Gateways</strong>”, que criam pontos controlados de entrada para o mundo não seguro, permitindo que a aplicação acesse serviços de segurança sem violar o isolamento.</p>



<p class="wp-block-paragraph">A ARMv8-M existe em dois perfis principais relacionados à TrustZone:</p>



<ul class="wp-block-list">
<li><strong>ARMv8-M Baseline</strong> — destinado a núcleos menores (como Cortex-M23), mantém compatibilidade com Cortex-M0/M0+ e ainda oferece TrustZone, mas com um conjunto de instruções mais compacto.</li>



<li><strong>ARMv8-M Mainline</strong> — adotado por núcleos como Cortex-M33 e Cortex-M35P, integra TrustZone com recursos adicionais, como DSP, otimizações para desempenho e suporte para aplicações críticas de segurança (inclusive resistência a ataques físicos no caso do Cortex-M35P).</li>
</ul>



<p class="wp-block-paragraph">A presença da TrustZone permite construir sistemas embarcados onde rotinas sensíveis podem residir em um domínio protegido, enquanto o restante da aplicação — interfaces ricas, protocolos de comunicação, modems, conectividade — opera de forma independente. Essa separação reduz enormemente a superfície de ataque e viabiliza projetos mais robustos conforme exigido por padrões de segurança modernos, como PSA Certified, IoT Security Foundation e requisitos automotivos.</p>



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



<h2 class="wp-block-heading"><strong>Núcleos Cortex-M que Suportam TrustZone</strong></h2>



<p class="wp-block-paragraph">A presença do TrustZone está diretamente vinculada à adoção da <strong>arquitetura ARMv8-M</strong>, que introduz o particionamento seguro/não-seguro no nível do hardware. Assim, apenas alguns núcleos Cortex-M possuem esse recurso; outros, mesmo que modernos, não oferecem suporte ao TrustZone.</p>



<p class="wp-block-paragraph">A seguir, apresentamos os principais núcleos Cortex-M com suporte ao TrustZone, incluindo suas características no contexto de segurança embarcada:</p>



<h3 class="wp-block-heading"><strong>Cortex-M23 (ARMv8-M Baseline)</strong></h3>



<p class="wp-block-paragraph">É o sucessor filosófico do Cortex-M0+, voltado para consumo ultrabaixo e aplicações simples, porém agora incorporando TrustZone. Apesar de mais modesto em desempenho, ele permite a construção de dispositivos IoT extremamente eficientes que possam armazenar chaves criptográficas e executar boot seguro sem necessidade de componentes externos.</p>



<h3 class="wp-block-heading"><strong>Cortex-M33 (ARMv8-M Mainline)</strong></h3>



<p class="wp-block-paragraph">É o núcleo mais difundido com TrustZone e representa a evolução direta do Cortex-M4. Ele combina DSP (Digital Signal Processing), opções de FPU (Floating Point Unit), excelente desempenho por watt e um ecossistema amplo. O Cortex-M33 costuma ser o ponto de partida para MCUs IoT industriais, automotivos e de comunicação segura.</p>



<h3 class="wp-block-heading"><strong>Cortex-M35P (ARMv8-M Mainline + Proteções Físicas)</strong></h3>



<p class="wp-block-paragraph">Destinado a aplicações com requisitos de proteção anticlonagem e resistência a ataques físicos, como terminais de pagamento, medidores certificados e dispositivos financeiros. Além da TrustZone, ele inclui contramedidas embutidas contra <em>fault injection</em>, análise de energia (SPA/DPA) e leitura física do barramento interno.</p>



<h3 class="wp-block-heading"><strong>Cortex-M55 (ARMv8.1-M)</strong></h3>



<p class="wp-block-paragraph">Apesar de ser mais associado a aplicações de AI embarcada e alto desempenho, seu conjunto arquitetural também incorpora a noção de ambientes seguros herdados da ARMv8-M. Ele trabalha com <em>Helium</em> (extensões vetoriais avançadas) e normalmente aparece em SoCs mais complexos, mas ainda dentro da família Cortex-M.</p>



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



<h3 class="wp-block-heading"><strong>Núcleos Cortex-M que <em>não</em> suportam TrustZone</strong></h3>



<p class="wp-block-paragraph">Para clareza, os seguintes <strong>não possuem TrustZone</strong>:</p>



<ul class="wp-block-list">
<li>Cortex-M0 / M0+</li>



<li>Cortex-M1</li>



<li>Cortex-M3</li>



<li>Cortex-M4</li>



<li>Cortex-M7</li>



<li>Cortex-M33 <em>sem</em> extensões de segurança ativadas pelo fabricante (raro, mas possível)</li>



<li>Cortex-M55 com configuração sem Security Extension (dependente do integrador)</li>
</ul>



<p class="wp-block-paragraph">Ou seja, mesmo que o núcleo suporte TrustZone, <strong>o fabricante do microcontrolador precisa habilitá-la no silício</strong>, na documentação e na ferramenta de desenvolvimento.</p>



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



<h3 class="wp-block-heading"><strong>Resumo técnico</strong></h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Núcleo</th><th>Arquitetura</th><th>TrustZone</th><th>Perfil</th></tr></thead><tbody><tr><td>Cortex-M23</td><td>ARMv8-M Baseline</td><td>Sim</td><td>Ultra baixo consumo, IoT básico</td></tr><tr><td>Cortex-M33</td><td>ARMv8-M Mainline</td><td>Sim</td><td>IoT industrial, segurança avançada</td></tr><tr><td>Cortex-M35P</td><td>ARMv8-M Mainline</td><td>Sim</td><td>Alta segurança física</td></tr><tr><td>Cortex-M55</td><td>ARMv8.1-M</td><td>Sim (dependente do integrador)</td><td>IA embarcada, DSP/Helium</td></tr></tbody></table></figure>



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



<h2 class="wp-block-heading"><strong>Benefícios, Importância e Modelo de Uso da TrustZone</strong></h2>



<p class="wp-block-paragraph">A introdução da TrustZone no ecossistema dos microcontroladores Cortex-M representa uma mudança profunda na forma como se constrói segurança embarcada. Em vez de confiar exclusivamente em barreiras de software — que podem ser burladas se houver estouro de pilha, execução de código injetado ou falhas em protocolos — agora o sistema conta com <strong>proteção por hardware</strong>, integrada ao pipeline e às unidades de controle do processador. Esse tipo de isolamento reduz significativamente a superfície de ataque e ajuda a garantir que um defeito no sistema operacional, no driver ou na pilha de rede não comprometa o núcleo crítico da aplicação.</p>



<p class="wp-block-paragraph">Do ponto de vista arquitetural, a TrustZone permite isolar rotinas que lidam com informações sensíveis, tais como <strong>gerenciamento de chaves criptográficas, validação de firmware, cálculo de assinaturas digitais, inicialização segura (Secure Boot) e autenticação de dispositivos</strong>, assegurando que essas operações só possam ser executadas dentro do ambiente seguro. Além disso, esse domínio privilegiado controla totalmente quais recursos são acessíveis pelo ambiente não seguro, criando um modelo claro de fronteiras e responsabilidades. Isso é crucial em aplicações conectadas, onde uma vulnerabilidade em protocolos como Wi-Fi, Bluetooth, USB ou TCP/IP poderia, sem o TrustZone, comprometer todo o dispositivo.</p>



<p class="wp-block-paragraph">Nos sistemas embarcados modernos, a importância desse recurso ultrapassa a camada técnica. Com a proliferação de dispositivos IoT e o aumento dos ataques direcionados a equipamentos industriais, de automação e infraestrutura, normas internacionais como IEC 62443, PSA Certified e ETSI EN 303 645 passaram a exigir mecanismos robustos de segurança. A TrustZone facilita a conformidade com esses padrões, pois permite implementar <strong>Root of Trust confiável</strong>, armazenar segredos de forma segura e realizar boot verificado — tudo dentro de um único microcontrolador, reduzindo custos e aumentando a viabilidade de produtos mais seguros para o mercado.</p>



<p class="wp-block-paragraph">O uso correto da TrustZone segue uma filosofia clara:<br><strong>apenas o código estritamente necessário deve residir no mundo seguro</strong>.<br>Isso evita que o domínio crítico se torne grande demais, reduzindo a probabilidade de erros e mantendo a superfície de ataque mínima. A maior parte da aplicação — comunicação, interface de usuário, lógica de negócio — deve rodar no mundo não seguro, que chama funções seguras através de <em>Secure Gateways</em>. Desse modo, cria-se uma organização modular onde o ambiente seguro funciona como um “microkernel criptográfico” protegendo o sistema.</p>



<p class="wp-block-paragraph">Na prática, a TrustZone melhora:</p>



<ul class="wp-block-list">
<li><strong>Confiabilidade</strong>: falhas no lado não seguro não derrubam ou comprometem o domínio seguro.</li>



<li><strong>Integridade</strong>: código sensível não pode ser alterado remotamente.</li>



<li><strong>Confidencialidade</strong>: chaves e dados críticos nunca escapam para a RAM não segura.</li>



<li><strong>Resistência a ataques físicos e remotos</strong>: exploração de vulnerabilidades torna-se mais difícil.</li>



<li><strong>Atualizações seguras</strong>: firmware pode ser validado antes da execução.</li>
</ul>



<p class="wp-block-paragraph">Esse conjunto de benefícios torna a TrustZone indispensável para qualquer dispositivo que precise operar de forma segura em ambientes conectados — desde sensores IoT até controladores industriais, gateways, equipamentos médicos, sistemas automotivos, medidores inteligentes, dispositivos de pagamento e aplicações de defesa.</p>



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



<h2 class="wp-block-heading"><strong>Microcontroladores STM32 com TrustZone e Exemplos Práticos de Utilização</strong></h2>



<p class="wp-block-paragraph">A STMicroelectronics foi uma das primeiras fabricantes a adotar a arquitetura ARMv8-M com TrustZone em suas linhas de microcontroladores. Isso resultou na criação de famílias especificamente projetadas para aplicações seguras, conectadas e com requisitos de certificação. Os dispositivos STM32 compatíveis com TrustZone utilizam majoritariamente o núcleo <strong>Cortex-M33</strong>, que agrega desempenho, DSP, opções de FPU e o particionamento seguro/não seguro.</p>



<h3 class="wp-block-heading"><strong>Famílias STM32 com suporte à TrustZone</strong></h3>



<p class="wp-block-paragraph">Atualmente, os principais grupos de MCUs da ST que implementam TrustZone são:</p>



<h4 class="wp-block-heading"><strong>1. STM32L5 Series — Foco em baixo consumo + segurança</strong></h4>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img loading="lazy" decoding="async" width="300" height="206" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-18.png" alt="" class="wp-image-981" style="width:396px;height:auto"/></figure>
</div>


<p class="wp-block-paragraph">Baseados em Cortex-M33, são otimizados para aplicações IoT alimentadas a bateria que ainda assim precisam de mecanismos fortes de proteção. Eles incluem:</p>



<ul class="wp-block-list">
<li>TrustZone for ARMv8-M</li>



<li>Secure Boot + Secure Firmware Update (SBSFU)</li>



<li>Hardware cryptography (AES, PKA, SHA-256 etc.)</li>



<li>Proteção contra leitura e escrita de Flash</li>
</ul>



<p class="wp-block-paragraph"><strong>Modelos comuns:</strong></p>



<ul class="wp-block-list">
<li>STM32L552, STM32L562</li>
</ul>



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



<h4 class="wp-block-heading"><strong>2. STM32U5 Series — Ultra-Low Power de nova geração com segurança reforçada</strong></h4>


<div class="wp-block-image">
<figure class="alignright size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="631" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-17-1024x631.png" alt="" class="wp-image-980" style="aspect-ratio:1.6228454131071333;width:476px;height:auto" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-17-1024x631.png 1024w, https://mcu.tec.br/wp-content/uploads/2025/12/image-17-300x185.png 300w, https://mcu.tec.br/wp-content/uploads/2025/12/image-17-768x473.png 768w, https://mcu.tec.br/wp-content/uploads/2025/12/image-17.png 1080w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p class="wp-block-paragraph">Também baseados em Cortex-M33, porém com melhorias em eficiência energética e mais recursos criptográficos. São ideais para dispositivos vestíveis, sensores inteligentes e aplicações avançadas de IoT.</p>



<p class="wp-block-paragraph"><strong>Modelos com TrustZone:</strong></p>



<ul class="wp-block-list">
<li>STM32U535, STM32U545</li>



<li>STM32U575, STM32U585</li>
</ul>



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



<h4 class="wp-block-heading"><strong>3. STM32H5 Series — Desempenho alto e segurança nativa</strong></h4>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img loading="lazy" decoding="async" width="600" height="415" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-16.png" alt="" class="wp-image-979" style="aspect-ratio:1.4457964093851876;width:432px;height:auto" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-16.png 600w, https://mcu.tec.br/wp-content/uploads/2025/12/image-16-300x208.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></figure>
</div>


<p class="wp-block-paragraph">Linha destinada a aplicações industriais e de automação que exigem performance maior. Mantêm o núcleo Cortex-M33 com TrustZone e agregam o novo ecossistema <strong>STM32Trust TEE</strong> (Trusted Execution Environment).</p>



<p class="wp-block-paragraph"><strong>Modelos conhecidos:</strong></p>



<ul class="wp-block-list">
<li>STM32H533, STM32H563, STM32H573</li>
</ul>



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



<h3 class="wp-block-heading"><strong>Como a TrustZone é utilizada na prática nos STM32</strong></h3>



<p class="wp-block-paragraph">A programação com TrustZone em um STM32 baseia-se na divisão do projeto em dois ambientes:</p>



<ol class="wp-block-list">
<li><strong>Secure Project</strong> — contém:
<ul class="wp-block-list">
<li>Bootloader seguro</li>



<li>Inicialização da SAU/IDAU</li>



<li>Configurações de particionamento da Flash e SRAM</li>



<li>Drivers seguros (opcional)</li>



<li>Funções de serviço expostas via <em>Secure Gateways</em> (SG)</li>
</ul>
</li>



<li><strong>Non-Secure Project</strong> — contém:
<ul class="wp-block-list">
<li>Aplicação principal</li>



<li>Pilhas de comunicação (Wi-Fi, BLE, TCP/IP, USB etc.)</li>



<li>Interface com sensores</li>



<li>UI, lógica de controle, tarefas secundárias</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">O CubeMX/CubeIDE fornece um fluxo semiautomático para configurar TrustZone:</p>



<ol class="wp-block-list">
<li>Seleciona-se um microcontrolador com TrustZone.</li>



<li>No painel “Security”, define-se:
<ul class="wp-block-list">
<li>quais regiões da Flash serão Secure/Non-Secure</li>



<li>quais periféricos serão protegidos</li>



<li>quais interrupções são seguras ou não seguras</li>
</ul>
</li>



<li>O CubeIDE gera automaticamente <strong>dois projetos</strong>:
<ul class="wp-block-list">
<li><code>Project_S</code> (Secure)</li>



<li><code>Project_NS</code> (Non-Secure)</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">O desenvolvedor define, então, funções marcadas 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>__attribute__((cmse_nonsecure_entry))
uint32_t Secure_Add(uint32_t a, uint32_t b)
{
    return a + b;
}
</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">__attribute__</span><span style="color: #D8DEE9FF">((</span><span style="color: #D8DEE9">cmse_nonsecure_entry</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Secure_Add</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</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: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b</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 função passa a ser chamada do lado não seguro como um <em>funcionário público do mundo seguro</em>, acessível mas rigidamente controlado.</p>



<p class="wp-block-paragraph">Do lado não seguro, a chamada é feita por meio de ponteiros segurizados:</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>typedef uint32_t (*func_ns_add_t)(uint32_t, uint32_t);
func_ns_add_t ns_add = (func_ns_add_t)((uint32_t)Secure_Add | 0x1U);

uint32_t result = ns_add(10, 20);
</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">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">uint32_t</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">func_ns_add_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">uint32_t</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">func_ns_add_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ns_add</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">func_ns_add_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">Secure_Add</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> 0</span><span style="color: #D8DEE9">x1U</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">result</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ns_add</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">10</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">20</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Observe o bit menos significativo setado, que indica ao processador que a função pertence ao domínio seguro e deve atravessar o gateway de forma validada.</p>



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



<h3 class="wp-block-heading"><strong>Exemplos típicos de uso em aplicações reais</strong></h3>



<ul class="wp-block-list">
<li><strong>Boot Seguro (SBSFU):</strong> valida assinatura digital antes da inicialização do firmware.</li>



<li><strong>Proteção de Propriedade Intelectual:</strong> código seguro permanece inacessível, mesmo se atacantes extraírem a Flash não segura.</li>



<li><strong>Gerenciamento de Chaves Criptográficas:</strong> a chave nunca deixa o domínio seguro.</li>



<li><strong>Gateways IoT e automação industrial:</strong> pilhas de rede rodam no lado não seguro; segurança permanece intacta em caso de ataque.</li>



<li><strong>Pagamentos, medição inteligente e sensores médicos:</strong> ambientes críticos isolados de elementos expostos ao usuário.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>Conclusão</strong></h2>



<p class="wp-block-paragraph">A introdução da TrustZone nos microcontroladores baseados na arquitetura ARMv8-M representa uma das evoluções mais significativas no campo da segurança embarcada dos últimos anos. Em um mundo onde dispositivos IoT se conectam a redes públicas, interagem com sistemas industriais e tratam dados sensíveis, torna-se indispensável contar com um mecanismo sólido de isolamento interno. E é exatamente isso que a TrustZone oferece: uma separação rigorosa entre ambientes de execução, construída diretamente no hardware do processador, com latências mínimas e sem a necessidade de componentes externos adicionais.</p>



<p class="wp-block-paragraph">Ao dividir o sistema entre domínios seguro e não seguro, a TrustZone permite proteger bootloaders, rotinas criptográficas, chaves, tabelas de autenticação e qualquer outro código crítico, reduzindo a superfície de ataque e aumentando a resiliência do dispositivo contra falhas e invasões. O restante da aplicação pode continuar funcionando de forma flexível e independente, inclusive operando pilhas complexas como BLE, TCP/IP, USB ou protocolos industriais. Esse modelo favorece tanto a estabilidade quanto a conformidade com normas de segurança internacionais, tornando o TrustZone um recurso essencial para produtos que precisam de certificação.</p>



<p class="wp-block-paragraph">A STMicroelectronics incorporou essa tecnologia em várias linhas de microcontroladores, como STM32L5, STM32U5, STM32H5 e STM32H7RS, trazendo ao mercado soluções que combinam segurança robusta, baixo consumo e grande capacidade de processamento. Ferramentas como o STM32CubeIDE simplificam o processo de particionamento seguro/não seguro, oferecendo ao desenvolvedor um ambiente prático e acessível para implementar desde simples funções protegidas até sistemas complexos envolvendo boot seguro, atualização autenticada e gerenciamento de chaves.</p>



<p class="wp-block-paragraph">Em síntese, o TrustZone não é apenas um recurso opcional, mas sim um <strong>pilar moderno para o desenvolvimento seguro</strong>, permitindo que a mesma MCU atue simultaneamente como um ambiente confiável e um ambiente de aplicação, de maneira eficiente, modular e escalável. À medida que novos produtos embarcados surgem com demandas crescentes de conectividade e proteção de dados, o domínio dessa tecnologia torna-se fundamental para engenheiros, arquitetos de sistemas e desenvolvedores de firmware que desejam construir soluções realmente confiáveis.</p>



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/trustzone-em-microcontroladores-cortex-m-seguranca-por-hardware-na-arquitetura-armv8-m/">TrustZone em Microcontroladores Cortex-M: Segurança por Hardware na Arquitetura ARMv8-M</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">977</post-id>	</item>
		<item>
		<title>Como Ler e Escrever Dados pela UART no STM32F411RE: Guia Completo com STM32CubeMX</title>
		<link>https://mcu.tec.br/microcontroladores/stm32/como-ler-e-escrever-dados-pela-uart-no-stm32f411re-guia-completo-com-stm32cubemx/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-ler-e-escrever-dados-pela-uart-no-stm32f411re-guia-completo-com-stm32cubemx</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 23:00:46 +0000</pubDate>
				<category><![CDATA[STM32]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=972</guid>

					<description><![CDATA[<p>Este tutorial completo ensina, passo a passo, como configurar, enviar e receber dados pela UART no microcontrolador STM32F411RE utilizando o STM32CubeMX e a placa Nucleo-F411RE. O conteúdo aborda desde a configuração inicial no CubeMX, transmissão bloqueante e não bloqueante, recepção por polling e interrupção, até boas práticas avançadas como uso de DMA, buffers circulares, modularização do código e cuidados elétricos. Ideal para estudantes, profissionais de firmware e engenheiros embarcados que desejam implementar comunicação serial robusta, didática e confiável, com exemplos práticos, callbacks, funções utilitárias e dicas que refletem aplicações reais no ambiente STM32.</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/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> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">A UART (Universal Asynchronous Receiver/Transmitter) é um dos blocos periféricos mais usados em microcontroladores STM32 para depuração, comunicação com PCs, módulos Bluetooth, GPS, entre outros. Na prática, é “a porta serial” clássica, só que implementada diretamente dentro do microcontrolador, permitindo enviar e receber bytes de forma assíncrona, usando poucos pinos.</p>



<p class="wp-block-paragraph">Neste tutorial vamos usar como referência a placa <strong>Nucleo STM32F411RE</strong>, que traz o microcontrolador <strong>STM32F411RE</strong> e já possui uma interface <strong>ST-LINK/V2-1</strong> que expõe uma porta serial virtual (Virtual COM Port) via USB. Isso é perfeito para testes, porque você só precisa de um cabo USB conectado ao PC e um terminal serial (PuTTY, TeraTerm, minicom, etc.) para enxergar os dados enviados pelo <code>printf</code> ou por funções que escrevem na UART, e também para enviar comandos de volta ao microcontrolador.</p>



<p class="wp-block-paragraph">O foco aqui é mostrar, de forma didática e minuciosa, como:</p>



<ul class="wp-block-list">
<li><strong>Configurar a UART no STM32CubeMX</strong> (usando o CubeIDE ou o CubeMX standalone);</li>



<li><strong>Enviar dados pela UART</strong> (modo bloqueante e não bloqueante);</li>



<li><strong>Receber dados pela UART</strong> com:
<ul class="wp-block-list">
<li>Polling (consulta ativa);</li>



<li>Interrupção (callback <code>HAL_UART_RxCpltCallback</code>);</li>



<li>Um pequeno “buffer” de recepção para montar strings/comandos.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">Ao final, você terá uma aplicação completa rodando na Nucleo STM32F411RE, capaz de:</p>



<ul class="wp-block-list">
<li>Enviar mensagens de texto para o PC (por exemplo, mensagens de debug);</li>



<li>Receber caracteres ou comandos vindos do terminal serial;</li>



<li>Fazer um “eco” dos dados recebidos (o clássico “echo server” na UART);</li>



<li>Servir de base para protocolos mais complexos (menus, comandos AT, etc.).</li>
</ul>



<h3 class="wp-block-heading">Visão geral do hardware usado</h3>



<ul class="wp-block-list">
<li><strong>Placa</strong>: NUCLEO-F411RE</li>



<li><strong>UART usada</strong>: normalmente <strong>USART2</strong>, mapeada pelos jumpers da placa para o ST-LINK (Virtual COM Port).</li>



<li><strong>Conexão com o PC</strong>:
<ul class="wp-block-list">
<li>Cabo USB ligado ao conector ST-LINK da Nucleo.</li>



<li>No PC, aparecerá uma porta COM (Windows) ou <code>/dev/ttyACM*</code> / <code>/dev/ttyUSB*</code> (Linux) correspondente.</li>
</ul>
</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Importante:</strong> A UART física (pinos PA2/PA3 na Nucleo F411RE, em geral) já está ligada internamente ao ST-LINK. Em muitos casos não é necessário conectar fios extras para fazer depuração via serial: basta configurar a USART correta no CubeMX e abrir o terminal no PC.</p>
</blockquote>



<h2 class="wp-block-heading">2. Configurando a UART no STM32CubeMX para a Nucleo STM32F411RE</h2>



<p class="wp-block-paragraph">Nesta seção vamos configurar a <strong>USART2</strong>, que é a interface serial já conectada ao ST-LINK e que aparece no PC como uma porta serial virtual. Esse é o caminho padrão para depuração via UART no NUCLEO-F411RE.</p>



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



<h1 class="wp-block-heading">2.1 Selecionando a UART correta no CubeMX</h1>



<ol class="wp-block-list">
<li>Abra o <strong>STM32CubeIDE</strong> e crie um novo projeto para a <strong>NUCLEO-F411RE</strong>.</li>



<li>Na aba <strong>Pinout &amp; Configuration</strong>, localize a categoria <strong>Connectivity</strong> → <strong>USART2</strong>.</li>



<li>Clique em <strong>USART2</strong> e selecione <strong>Asynchronous</strong>.</li>
</ol>



<p class="wp-block-paragraph">O CubeMX automaticamente habilitará os pinos:</p>



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



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



<p class="wp-block-paragraph">Esses pinos já estão roteados para o ST-LINK, permitindo enviar e receber dados via USB.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="799" height="688" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-21.png" alt="" class="wp-image-990" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-21.png 799w, https://mcu.tec.br/wp-content/uploads/2025/12/image-21-300x258.png 300w, https://mcu.tec.br/wp-content/uploads/2025/12/image-21-768x661.png 768w" sizes="(max-width: 799px) 100vw, 799px" /></figure>



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



<h1 class="wp-block-heading">2.2 Configurando parâmetros da UART</h1>



<p class="wp-block-paragraph">Com a USART2 selecionada, abra seu painel de configurações:</p>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img loading="lazy" decoding="async" width="531" height="419" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-22.png" alt="" class="wp-image-991" style="aspect-ratio:1.2673557120643921;width:411px;height:auto" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-22.png 531w, https://mcu.tec.br/wp-content/uploads/2025/12/image-22-300x237.png 300w" sizes="(max-width: 531px) 100vw, 531px" /></figure>
</div>


<h3 class="wp-block-heading">• Baud rate</h3>



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



<li>Rápido, estável e amplamente suportado por terminais seriais.</li>
</ul>



<h3 class="wp-block-heading">• Palavra de dados (Word Length)</h3>



<ul class="wp-block-list">
<li><strong>8 Bits</strong> (padrão universal e ideal para ASCII).</li>
</ul>



<h3 class="wp-block-heading">• Paridade (Parity)</h3>



<ul class="wp-block-list">
<li><strong>None</strong> (sem paridade).</li>
</ul>



<h3 class="wp-block-heading">• Bits de parada (Stop Bits)</h3>



<ul class="wp-block-list">
<li><strong>1 Stop Bit</strong>.</li>
</ul>



<h3 class="wp-block-heading">• Modo</h3>



<ul class="wp-block-list">
<li><strong>TX and RX</strong> (necessário tanto para enviar quanto para receber).</li>
</ul>



<h3 class="wp-block-heading">• Hardware Flow Control</h3>



<ul class="wp-block-list">
<li><strong>None</strong> (a Nucleo não implementa RTS/CTS no ST-LINK).</li>
</ul>



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



<h1 class="wp-block-heading">2.3 Configurando as interrupções (NVIC)</h1>



<p class="wp-block-paragraph">Como iremos utilizar recepção por interrupção (mais robusta que polling), precisamos ativá-las:</p>


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


<ol class="wp-block-list">
<li>No painel da USART2, clique na aba <strong>NVIC Settings</strong>.</li>



<li>Marque: <strong>USART2 global interrupt</strong>.</li>



<li>Prioridade recomendada:
<ul class="wp-block-list">
<li><strong>Preemption Priority:</strong> 0</li>



<li><strong>Sub Priority:</strong> 0</li>
</ul>
</li>
</ol>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Ponto para inserir imagem 3 (Configurar NVIC da USART2)</strong></p>
</blockquote>



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



<h1 class="wp-block-heading">2.4 Clock e velocidade da UART</h1>



<p class="wp-block-paragraph">A UART usa como referência o clock do barramento APB1. GARANTA que:</p>


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


<ol class="wp-block-list">
<li>No menu <strong>Clock Configuration</strong>:
<ul class="wp-block-list">
<li>APB1 esteja configurado para <strong>50 MHz</strong> ou <strong>42 MHz</strong> (valores usuais no F411).</li>
</ul>
</li>



<li>O cubemx indicará se o baud rate pode ser gerado com boa precisão.</li>
</ol>



<p class="wp-block-paragraph">Se a precisão for baixa (&lt;2%), o CubeMX exibirá um alerta. Ajuste o clock se necessário.</p>



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



<h1 class="wp-block-heading">2.5 Geração do Código</h1>



<p class="wp-block-paragraph">Quando tudo estiver configurado:</p>



<ol class="wp-block-list">
<li>Clique em <strong>Project Manager</strong> → confirme o nome do projeto.</li>



<li>Selecione <strong>HAL</strong> como driver.</li>



<li>Clique em <strong>GENERATE CODE</strong>.</li>
</ol>



<p class="wp-block-paragraph">O CubeIDE criará arquivos importantes:</p>



<ul class="wp-block-list">
<li><strong>usart.c</strong> → contém <code>MX_USART2_UART_Init()</code>, definições do handle <code>huart2</code>, etc.</li>



<li><strong>usart.h</strong> → exposições das funções e do handle.</li>



<li>Inicialização da UART será chamada automaticamente dentro de <code>main.c</code> pela função <code>MX_USART2_UART_Init()</code>.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Ponto para inserir imagem 5 (Tela de Generate Code)</strong></p>
</blockquote>



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



<h1 class="wp-block-heading">2.6 Confirmando a inicialização no main.c</h1>



<p class="wp-block-paragraph">Após gerar o código, abra o arquivo <strong>main.c</strong> e verifique:</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_GPIO_Init();
    MX_USART2_UART_Init();   // &lt;-- UART inicializada aqui

    while (1)
    {
    }
}
</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_GPIO_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">MX_USART2_UART_Init</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">// &lt;-- UART inicializada aqui</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: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">E veja o handle da UART definido em <code>usart.c</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>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">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"/>



<h1 class="wp-block-heading">2.7 Teste rápido da UART (primeiro envio)</h1>



<p class="wp-block-paragraph">Antes mesmo de escrever as funções detalhadas, podemos testar a 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>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">Abra o terminal serial (115200, 8N1) no PC, reset a placa, e confirme se a mensagem aparece.</p>



<p class="wp-block-paragraph">Se aparecer, <strong>a UART está configurada corretamente</strong>.</p>



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



<h2 class="wp-block-heading">3. Enviando dados pela UART no STM32F411RE</h2>



<p class="wp-block-paragraph">Agora que a USART2 está configurada no CubeMX, vamos ver na prática como <strong>transmitir dados</strong>. Vamos começar pelo modo mais simples (bloqueante) e depois comentar alternativas.</p>



<p class="wp-block-paragraph">Vou assumir sempre:</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 "usart.h"   // gera o handle huart2
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: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">usart.h</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">// gera o handle huart2</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></code></pre></div>



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



<h3 class="wp-block-heading">3.1. Conceito rápido: transmissão bloqueante vs não bloqueante</h3>



<p class="wp-block-paragraph">Na HAL temos basicamente três famílias de funções para TX:</p>



<ul class="wp-block-list">
<li><strong>Bloqueante:</strong><br><code>HAL_UART_Transmit(&amp;huart2, pData, Size, Timeout);</code><br>A função só retorna quando:
<ul class="wp-block-list">
<li>Todos os bytes foram enviados, ou</li>



<li>O tempo de <code>Timeout</code> estourou.</li>
</ul>
</li>



<li><strong>Por interrupção:</strong><br><code>HAL_UART_Transmit_IT(&amp;huart2, pData, Size);</code><br>A função retorna “rápido”, e o envio acontece em background.<br>Quando termina, a HAL chama o callback <code>HAL_UART_TxCpltCallback()</code>.</li>



<li><strong>Por DMA:</strong><br><code>HAL_UART_Transmit_DMA(&amp;huart2, pData, Size);</code><br>Similar ao IT, mas usando DMA. Ideal para grandes volumes de dados.<br>(Vou citar aqui, mas podemos deixar o uso detalhado para uma seção futura, se você quiser.)</li>
</ul>



<p class="wp-block-paragraph">Para debug e exemplos simples, <strong>o bloqueante é o mais direto</strong> e suficiente.</p>



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



<h3 class="wp-block-heading">3.2. Primeiro exemplo: “Hello, UART!” (modo bloqueante)</h3>



<p class="wp-block-paragraph">No <code>main.c</code>, após a inicialização, podemos mandar uma mensagem a cada segundo:</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 "usart.h"

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART2_UART_Init();

    uint8_t msg[] = "Hello, UART!\r\n";

    while (1)
    {
        HAL_UART_Transmit(&amp;huart2,
                          msg,
                          sizeof(msg) - 1,  // sem o '\0'
                          HAL_MAX_DELAY);   // espera o tempo que precisar

        HAL_Delay(1000); // 1 segundo
    }
}
</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: #ECEFF4">&quot;</span><span style="color: #A3BE8C">usart.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<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_GPIO_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">MX_USART2_UART_Init</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: #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">Hello, UART!</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</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">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>
<span class="line"><span style="color: #D8DEE9FF">                          </span><span style="color: #D8DEE9">msg</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// sem o &#39;\0&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">                          </span><span style="color: #D8DEE9">HAL_MAX_DELAY</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">// espera o tempo que precisar</span></span>
<span class="line"></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</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">Abra o terminal serial (115200, 8N1) e você deve ver a mensagem sendo impressa a cada segundo.</p>



<p class="wp-block-paragraph"><strong>Pontos importantes:</strong></p>



<ul class="wp-block-list">
<li><code>sizeof(msg) - 1</code>: envia só até o <code>\n</code>, sem incluir o byte nulo final.</li>



<li><code>HAL_MAX_DELAY</code>: faz a função esperar até o fim da transmissão (modo bem simples para debug).</li>



<li>Esse padrão é muito usado para mensagens curtas de status.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Ponto para inserir imagem 6:</strong> captura do terminal exibindo <code>"Hello, UART!"</code>.</p>
</blockquote>



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



<h3 class="wp-block-heading">3.3. Função utilitária para enviar strings (<code>Serial_SendString</code>)</h3>



<p class="wp-block-paragraph">Na prática, é comum criar uma função de conveniência para enviar strings ASCII (<code>char *</code>).</p>



<p class="wp-block-paragraph">Você pode colocá-la, por exemplo, no final de <code>usart.c</code> ou em um módulo <code>serial.c</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>#include "usart.h"
#include &lt;string.h>

/**
 * @brief Envia uma string ASCII terminada em '\0' pela USART2 (bloqueante).
 */
void Serial_SendString(const char *str)
{
    if (str == NULL)
        return;

    HAL_UART_Transmit(&amp;huart2,
                      (uint8_t *)str,
                      strlen(str),
                      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">usart.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">string</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: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Envia uma string ASCII terminada em &#39;\0&#39; pela USART2 (bloqueante).</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Serial_SendString</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">str</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">str</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return;</span></span>
<span class="line"></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>
<span class="line"><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">str</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                      </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">str</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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">Uso em <code>main.c</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>int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART2_UART_Init();

    Serial_SendString("Sistema iniciado...\r\n");

    while (1)
    {
        Serial_SendString("Loop principal rodando.\r\n");
        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_GPIO_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">MX_USART2_UART_Init</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">Serial_SendString</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>
<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">Serial_SendString</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Loop principal rodando.</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">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">Vantagens:</p>



<ul class="wp-block-list">
<li>Você não precisa ficar calculando <code>sizeof(...) - 1</code> toda hora.</li>



<li>Facilita a criação de logs e mensagens de debug.</li>
</ul>



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



<h3 class="wp-block-heading">3.4. Enviando buffers binários (não só texto)</h3>



<p class="wp-block-paragraph">Nem sempre você quer mandar texto; muitas vezes vai mandar <strong>dados binários</strong> (por exemplo, struct, amostras de ADC, etc.). O uso é o mesmo, apenas com um <code>uint8_t *</code> e um tamanho:</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 Serial_SendBuffer(uint8_t *buffer, uint16_t length)
{
    if (buffer == NULL || length == 0)
        return;

    HAL_UART_Transmit(&amp;huart2, buffer, length, 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: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Serial_SendBuffer</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: #D8DEE9">buffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">length</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">buffer</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">length</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: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return;</span></span>
<span class="line"></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">buffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">length</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">Exemplo de uso:</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 data&#91;4&#93; = {0xDE, 0xAD, 0xBE, 0xEF};
Serial_SendBuffer(data, sizeof(data));
</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">data</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #B48EAD">0xDE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0xAD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0xBE</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0xEF</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">Serial_SendBuffer</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">data</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">data</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 terminal “puro” você verá caracteres estranhos, pois não são ASCII, mas do ponto de vista da camada física tudo está correto.</p>



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



<h3 class="wp-block-heading">3.5. Transmissão por interrupção (<code>HAL_UART_Transmit_IT</code>)</h3>



<p class="wp-block-paragraph">Quando você começa a mandar mensagens mais longas e quer <strong>não travar o CPU</strong> durante o envio, a versão por interrupção faz sentido.</p>



<h4 class="wp-block-heading">3.5.1. Buffer global e flag de estado</h4>



<p class="wp-block-paragraph">No <code>main.c</code> ou em um módulo próprio:</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 "usart.h"
#include &lt;string.h>

uint8_t txBuffer&#91;64&#93;;
volatile uint8_t txBusy = 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: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">usart.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">string</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">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">txBuffer</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: #D8DEE9">volatile</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">txBusy</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></code></pre></div>



<h4 class="wp-block-heading">3.5.2. Função para enviar string de forma não bloqueante</h4>



<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>HAL_StatusTypeDef Serial_SendString_IT(const char *str)
{
    if (str == NULL)
        return HAL_ERROR;

    if (txBusy)   // ainda está transmitindo algo
        return HAL_BUSY;

    size_t len = strlen(str);
    if (len > sizeof(txBuffer))
        len = sizeof(txBuffer); // truncar se for muito grande

    memcpy(txBuffer, str, len);

    txBusy = 1;

    return HAL_UART_Transmit_IT(&amp;huart2, txBuffer, 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">HAL_StatusTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Serial_SendString_IT</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">str</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">str</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NULL</span><span style="color: #D8DEE9FF">)</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">HAL_ERROR</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">txBusy</span><span style="color: #D8DEE9FF">)   </span><span style="color: #616E88">// ainda está transmitindo algo</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">HAL_BUSY</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">size_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">str</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txBuffer</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txBuffer</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// truncar se for muito grande</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memcpy</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">txBuffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">str</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</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: #D8DEE9">txBusy</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</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: #88C0D0">HAL_UART_Transmit_IT</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">txBuffer</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</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>



<h4 class="wp-block-heading">3.5.3. Callback de fim de transmissão</h4>



<p class="wp-block-paragraph">A HAL chama esse callback automaticamente ao terminar o envio:</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 HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
        txBusy = 0; // libera para próxima transmissão
    }
}
</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">HAL_UART_TxCpltCallback</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">UART_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">huart</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">huart</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">Instance</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USART2</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: #D8DEE9">txBusy</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 style="color: #D8DEE9FF"> </span><span style="color: #616E88">// libera para próxima transmissão</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>



<h4 class="wp-block-heading">3.5.4. Uso no <code>main</code></h4>



<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_GPIO_Init();
    MX_USART2_UART_Init();

    Serial_SendString_IT("Inicio não bloqueante...\r\n");

    while (1)
    {
        if (!txBusy)
        {
            Serial_SendString_IT("Outra mensagem via IT.\r\n");
        }

        // Aqui seu código principal roda enquanto a UART transmite em background
        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: #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_GPIO_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">MX_USART2_UART_Init</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">Serial_SendString_IT</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Inicio não bloqueante...</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>
<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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9">txBusy</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">Serial_SendString_IT</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Outra mensagem via IT.</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: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Aqui seu código principal roda enquanto a UART transmite em background</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: #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"><strong>Observações importantes:</strong></p>



<ul class="wp-block-list">
<li>Não chame <code>Serial_SendString_IT</code> novamente enquanto <code>txBusy == 1</code>, ou os dados podem se misturar.</li>



<li>Esse padrão é o mesmo que o artigo da ST usa para RX: um buffer global + callback para notificar fim da operação. (<a href="https://wiki.st.com/stm32mcu/wiki/Getting_started_with_UART?utm_source=chatgpt.com">STMicroelectronics</a>)</li>



<li>Para sistemas maiores, normalmente se implementa uma fila (queue) de mensagens ou um ring buffer para TX.</li>
</ul>



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



<h3 class="wp-block-heading">3.6. Quando considerar DMA para transmissão</h3>



<p class="wp-block-paragraph">De forma resumida:</p>



<ul class="wp-block-list">
<li><strong>Mensagens curtas, debug, comandos esporádicos:</strong><br><code>HAL_UART_Transmit</code> (bloqueante) é mais do que suficiente e muito simples.</li>



<li><strong>Mensagens médias que não podem travar o CPU, mas não são contínuas:</strong><br><code>HAL_UART_Transmit_IT</code>.</li>



<li><strong>Streams contínuos ou muito longos (telemetria, logs pesados, etc.):</strong><br><code>HAL_UART_Transmit_DMA</code> + um buffer circular costuma ser a melhor solução.</li>
</ul>



<p class="wp-block-paragraph">Se quiser, podemos dedicar uma seção futura só a TX por DMA.</p>



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



<h2 class="wp-block-heading">4. Lendo dados pela UART usando <em>polling</em> (HAL_UART_Receive)</h2>



<p class="wp-block-paragraph">Vamos começar a recepção de dados pela forma mais simples: <strong>polling</strong>. Ou seja, o código “espera” (bloqueia) até que um ou mais bytes cheguem e só então continua a execução.</p>



<p class="wp-block-paragraph">A função principal da HAL para isso é:</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>HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart,
                                   uint8_t *pData,
                                   uint16_t Size,
                                   uint32_t Timeout);
</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">HAL_StatusTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_UART_Receive</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">UART_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">huart</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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: #D8DEE9">pData</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                   </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Size</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">Timeout</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<ul class="wp-block-list">
<li><code>huart</code> → normalmente <code>&amp;huart2</code>.</li>



<li><code>pData</code> → ponteiro para o buffer onde os dados recebidos serão armazenados.</li>



<li><code>Size</code> → quantidade de bytes a receber.</li>



<li><code>Timeout</code> → tempo máximo de espera em milissegundos.</li>
</ul>



<p class="wp-block-paragraph">Se os <code>Size</code> bytes chegarem antes do timeout, a função retorna <code>HAL_OK</code>.<br>Se o tempo estourar, retorna <code>HAL_TIMEOUT</code>.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Importante:</strong> Em polling, o <strong>processador fica parado</strong> esperando a UART. Então essa abordagem é boa para testes simples, menus que só fazem algo quando o usuário digita, ou para sistemas muito pequenos. Para aplicações mais reativas, usaremos interrupção (próxima seção).</p>
</blockquote>



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



<h3 class="wp-block-heading">4.1. Exemplo simples: eco de um único caractere</h3>



<p class="wp-block-paragraph">Vamos fazer o clássico <strong>echo</strong>: tudo o que chega é enviado de volta. Isso ajuda a testar se TX e RX estão OK.</p>



<p class="wp-block-paragraph">No <code>main.c</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>#include "main.h"
#include "usart.h"

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART2_UART_Init();

    uint8_t rxByte;

    // Mensagem inicial
    uint8_t msg[] = "Digite qualquer coisa: eu irei ecoar.\r\n";
    HAL_UART_Transmit(&amp;huart2, msg, sizeof(msg) - 1, HAL_MAX_DELAY);

    while (1)
    {
        // Espera um byte chegar (sem limite de tempo)
        if (HAL_UART_Receive(&amp;huart2, &amp;rxByte, 1, HAL_MAX_DELAY) == HAL_OK)
        {
            // Ecoa o mesmo byte de volta
            HAL_UART_Transmit(&amp;huart2, &amp;rxByte, 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: #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: #ECEFF4">&quot;</span><span style="color: #A3BE8C">usart.h</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span>
<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_GPIO_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">MX_USART2_UART_Init</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: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Mensagem inicial</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><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">Digite qualquer coisa: eu irei ecoar.</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: #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">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: #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>
<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: #ECEFF4">        </span><span style="color: #616E88">// Espera um byte chegar (sem limite de tempo)</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">HAL_UART_Receive</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</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 style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_OK</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: #ECEFF4">            </span><span style="color: #616E88">// Ecoa o mesmo byte de volta</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</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: #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></code></pre></div>



<p class="wp-block-paragraph">Abra o terminal serial, digite caracteres: eles devem aparecer de volta na tela (às vezes duplicados visualmente se o terminal também ecoar localmente). Desative o <em>local echo</em> no terminal se quiser ver apenas o eco do microcontrolador.</p>



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



<h3 class="wp-block-heading">4.2. Recebendo uma “linha” de texto até <code>\r</code> ou <code>\n</code></h3>



<p class="wp-block-paragraph">Na prática, você geralmente quer receber <strong>comandos</strong> (por exemplo, <code>LED ON</code>, <code>PWM 100</code>, etc.), que chegam em forma de texto terminados com Enter (<code>\r</code> e/ou <code>\n</code>). Vamos montar um exemplo simples que:</p>



<ol class="wp-block-list">
<li>Lê caracteres um a um.</li>



<li>Guarda em um buffer.</li>



<li>Quando encontrar <code>\r</code> ou <code>\n</code>, considera que a “linha” terminou.</li>



<li>Ecoa a linha completa e limpa o buffer.</li>
</ol>



<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 "usart.h"
#include &lt;string.h>

#define RX_LINE_BUFFER_SIZE   64

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART2_UART_Init();

    uint8_t rxByte;
    uint8_t rxLine&#91;RX_LINE_BUFFER_SIZE&#93;;
    uint16_t rxIndex = 0;

    const char *startMsg = "Digite um comando e pressione ENTER:\r\n";
    HAL_UART_Transmit(&amp;huart2, (uint8_t *)startMsg, strlen(startMsg), HAL_MAX_DELAY);

    while (1)
    {
        // Aguarda um byte (sem timeout, bloqueante)
        if (HAL_UART_Receive(&amp;huart2, &amp;rxByte, 1, HAL_MAX_DELAY) == HAL_OK)
        {
            // Se receber \r ou \n, considera fim de linha
            if (rxByte == '\r' || rxByte == '\n')
            {
                // Fecha a string
                rxLine&#91;rxIndex&#93; = '\0';

                // Se houver algo no buffer, processa
                if (rxIndex > 0)
                {
                    const char *prefix = "\r\nVoce digitou: ";
                    HAL_UART_Transmit(&amp;huart2,
                                      (uint8_t *)prefix,
                                      strlen(prefix),
                                      HAL_MAX_DELAY);

                    HAL_UART_Transmit(&amp;huart2,
                                      rxLine,
                                      rxIndex,
                                      HAL_MAX_DELAY);

                    const char *suffix = "\r\nDigite outro comando:\r\n";
                    HAL_UART_Transmit(&amp;huart2,
                                      (uint8_t *)suffix,
                                      strlen(suffix),
                                      HAL_MAX_DELAY);

                    // Aqui é onde você chamaria uma função para interpretar o comando:
                    // Processar_Comando((char *)rxLine);

                    // Limpa índice para próxima linha
                    rxIndex = 0;
                }
            }
            else
            {
                // Armazena o byte no buffer se há espaço
                if (rxIndex &lt; RX_LINE_BUFFER_SIZE - 1)
                {
                    rxLine&#91;rxIndex++&#93; = rxByte;

                    // (Opcional) ecoa o caractere para feedback imediato
                    HAL_UART_Transmit(&amp;huart2, &amp;rxByte, 1, HAL_MAX_DELAY);
                }
                else
                {
                    // Buffer cheio: descarta e avisa
                    const char *overflowMsg =
                        "\r\n&#91;ERRO&#93; Linha muito longa, descartada.\r\n";
                    HAL_UART_Transmit(&amp;huart2,
                                      (uint8_t *)overflowMsg,
                                      strlen(overflowMsg),
                                      HAL_MAX_DELAY);
                    rxIndex = 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: #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: #ECEFF4">&quot;</span><span style="color: #A3BE8C">usart.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">string</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: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">RX_LINE_BUFFER_SIZE</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">64</span></span>
<span class="line"></span>
<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_GPIO_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">MX_USART2_UART_Init</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: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxLine</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">RX_LINE_BUFFER_SIZE</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">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxIndex</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>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *startMsg </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Digite um comando e pressione ENTER:</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: #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">startMsg</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">startMsg</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>
<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: #ECEFF4">        </span><span style="color: #616E88">// Aguarda um byte (sem timeout, bloqueante)</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">HAL_UART_Receive</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</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 style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_OK</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: #ECEFF4">            </span><span style="color: #616E88">// Se receber \r ou \n, considera fim de linha</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">rxByte</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\r</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxByte</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&#39;</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: #ECEFF4">                </span><span style="color: #616E88">// Fecha a string</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #D8DEE9">rxLine</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">rxIndex</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\0</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">                </span><span style="color: #616E88">// Se houver algo no buffer, processa</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">rxIndex</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</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">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *prefix </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">Voce digitou: </span><span style="color: #ECEFF4">&quot;</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>
<span class="line"><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">prefix</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                      </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">prefix</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<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>
<span class="line"><span style="color: #D8DEE9FF">                                      </span><span style="color: #D8DEE9">rxLine</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                      </span><span style="color: #D8DEE9">rxIndex</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *suffix </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">Digite outro comando:</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: #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>
<span class="line"><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">suffix</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                      </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">suffix</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<span class="line"><span style="color: #ECEFF4">                    </span><span style="color: #616E88">// Aqui é onde você chamaria uma função para interpretar o comando:</span></span>
<span class="line"><span style="color: #ECEFF4">                    </span><span style="color: #616E88">// Processar_Comando((char *)rxLine);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">                    </span><span style="color: #616E88">// Limpa índice para próxima linha</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #D8DEE9">rxIndex</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: #ECEFF4">}</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">else</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 style="color: #616E88">// Armazena o byte no buffer se há espaço</span></span>
<span class="line"><span style="color: #D8DEE9FF">                </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">rxIndex</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">RX_LINE_BUFFER_SIZE</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</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: #D8DEE9">rxLine</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">rxIndex</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">rxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">                    </span><span style="color: #616E88">// (Opcional) ecoa o caractere para feedback imediato</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</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: #ECEFF4">}</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: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">                    </span><span style="color: #616E88">// Buffer cheio: descarta e avisa</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">char</span><span style="color: #D8DEE9FF"> *overflowMsg </span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9FF">                        </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;ERRO&#93; Linha muito longa, descartada.</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: #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>
<span class="line"><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">overflowMsg</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                      </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">overflowMsg</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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">rxIndex</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: #ECEFF4">}</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: #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">Esse padrão (buffer de linha + fim em <code>\r</code>/<code>\n</code>) é <strong>exatamente a base</strong> de interfaces de comando em UART (menus de terminal, CLI serial, comandos AT etc.).</p>



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



<h3 class="wp-block-heading">4.3. Usando <em>timeout</em> para não travar o sistema</h3>



<p class="wp-block-paragraph">O uso de <code>HAL_MAX_DELAY</code> torna a função bloqueante “para sempre”, o que pode ser ruim se o seu programa tiver outras tarefas importantes para fazer em paralelo.</p>



<p class="wp-block-paragraph">Você pode usar um timeout finito, por exemplo 10 ms, e testar o retorno:</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 rxByte;

HAL_StatusTypeDef status = HAL_UART_Receive(&amp;huart2,
                                            &amp;rxByte,
                                            1,
                                            10); // 10 ms

if (status == HAL_OK)
{
    // Chegou algum dado
    HAL_UART_Transmit(&amp;huart2, &amp;rxByte, 1, HAL_MAX_DELAY);
}
else if (status == HAL_TIMEOUT)
{
    // Não chegou nada nesse intervalo; toque a vida normalmente
    // Atualize sensores, rode outras tarefas, etc.
}
else
{
    // Outros erros de UART (framing, overrun, etc.)
    const char *err = "&#91;ERRO&#93; UART Receive falhou.\r\n";
    HAL_UART_Transmit(&amp;huart2, (uint8_t *)err, strlen(err), 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">rxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">HAL_StatusTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">status</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_UART_Receive</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">huart2</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                            </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                            </span><span style="color: #B48EAD">1</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                            </span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// 10 ms</span></span>
<span class="line"></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">status</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_OK</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">// Chegou algum dado</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">rxByte</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: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">status</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL_TIMEOUT</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">// Não chegou nada nesse intervalo; toque a vida normalmente</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Atualize sensores, rode outras tarefas, etc.</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #81A1C1">else</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Outros erros de UART (framing, overrun, etc.)</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">char</span><span style="color: #D8DEE9FF"> *err </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">&#91;ERRO&#93; UART Receive falhou.</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: #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">err</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">err</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">Esse esquema já melhora a responsividade: o laço principal não fica parado indefinidamente esperando dados.</p>



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



<h3 class="wp-block-heading">4.4. Limitações do polling e motivação para interrupções</h3>



<p class="wp-block-paragraph"><strong>Problemas do polling puro:</strong></p>



<ul class="wp-block-list">
<li>Se você usar <code>HAL_MAX_DELAY</code>, o loop principal só “acorda” quando chega dado. Ótimo para aplicações tipo “terminal interativo” simples, mas ruim quando há outras tarefas a executar (por exemplo, ler sensores, controlar motores).</li>



<li>Mesmo com timeouts pequenos, você fica chamando <code>HAL_UART_Receive</code> repetidamente. Isso consome CPU sem necessidade se os dados chegam esporadicamente.</li>



<li>Se vários bytes chegam enquanto o código está fazendo outra coisa (sem chamar <code>HAL_UART_Receive</code>), você pode ter <strong>overrun</strong> ou perda de dados se não tratar corretamente.</li>
</ul>



<p class="wp-block-paragraph">Por isso, para aplicações robustas, é comum usar:</p>



<ul class="wp-block-list">
<li><strong>Recepção por interrupção (<code>HAL_UART_Receive_IT</code>) com um buffer de 1 byte</strong> que é realimentado a cada callback, ou</li>



<li><strong>Recepção por DMA</strong> em buffers circulares, dependendo do volume de dados.</li>
</ul>



<p class="wp-block-paragraph">Essas estratégias são justamente o núcleo do artigo de referência da ST e serão a base da próxima seção.</p>



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



<h2 class="wp-block-heading">5. Recebendo dados pela UART com interrupção (HAL_UART_Receive_IT)</h2>



<p class="wp-block-paragraph">Agora vamos para o “jeito certo” de receber dados em aplicações reais: <strong>interrupção</strong>.<br>A ideia é simples e poderosa:</p>



<ul class="wp-block-list">
<li>A UART gera uma <strong>interrupção</strong> sempre que um byte chega.</li>



<li>No callback da HAL, você:
<ul class="wp-block-list">
<li>Lê esse byte;</li>



<li>Armazena num buffer maior;</li>



<li>Toma alguma decisão (ecoar, montar comando, etc.);</li>



<li>Agenda a <strong>próxima recepção</strong> com <code>HAL_UART_Receive_IT</code>.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">Assim, a CPU fica livre para fazer outras coisas no <code>while(1)</code> e só é interrompida quando realmente chega dado na UART.</p>



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



<h3 class="wp-block-heading">5.1. Estrutura básica da recepção por interrupção</h3>



<p class="wp-block-paragraph">Vamos montar uma estrutura típica:</p>



<ul class="wp-block-list">
<li>Um buffer de 1 byte para a chamada de <code>HAL_UART_Receive_IT</code>.</li>



<li>Um buffer maior de linha ou de comando.</li>



<li>Flags e índices globais para sinalizar “linha pronta”.</li>
</ul>



<p class="wp-block-paragraph">No <code>main.c</code> ou em um módulo <code>serial.c</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>#include "usart.h"
#include &lt;string.h>

#define RX_BUFFER_SIZE        64

// Byte único usado pela HAL para recepção via IT
uint8_t uartRxByte;

// Buffer maior para montar uma linha/comando
uint8_t uartRxBuffer&#91;RX_BUFFER_SIZE&#93;;
volatile uint16_t uartRxIndex = 0;
volatile uint8_t uartLineReady = 0;   // flag de "linha completa"
</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">usart.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">string</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: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">RX_BUFFER_SIZE</span><span style="color: #D8DEE9FF">        </span><span style="color: #B48EAD">64</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// Byte único usado pela HAL para recepção via IT</span></span>
<span class="line"><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uartRxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">// Buffer maior para montar uma linha/comando</span></span>
<span class="line"><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uartRxBuffer</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">RX_BUFFER_SIZE</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">volatile</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uartRxIndex</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: #D8DEE9">volatile</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uartLineReady</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 style="color: #D8DEE9FF">   </span><span style="color: #616E88">// flag de &quot;linha completa&quot;</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">5.2. Iniciando a recepção no <code>main</code></h3>



<p class="wp-block-paragraph">No <code>main()</code> depois de inicializar tudo, iniciamos <strong>uma primeira recepção</strong> de 1 byte:</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_GPIO_Init();
    MX_USART2_UART_Init();

    const char *startMsg = "UART RX por interrupcao iniciada.\r\n";
    HAL_UART_Transmit(&amp;huart2,
                      (uint8_t *)startMsg,
                      strlen(startMsg),
                      HAL_MAX_DELAY);

    // Inicia recepcao de 1 byte via interrupcao
    HAL_UART_Receive_IT(&amp;huart2, &amp;uartRxByte, 1);

    while (1)
    {
        // Se uma linha completa foi recebida:
        if (uartLineReady)
        {
            uartLineReady = 0;

            // Garante que o buffer termine em '\0'
            uartRxBuffer&#91;uartRxIndex&#93; = '\0';

            const char *prefix = "\r\n&#91;IT&#93; Linha recebida: ";
            HAL_UART_Transmit(&amp;huart2,
                              (uint8_t *)prefix,
                              strlen(prefix),
                              HAL_MAX_DELAY);

            HAL_UART_Transmit(&amp;huart2,
                              uartRxBuffer,
                              uartRxIndex,
                              HAL_MAX_DELAY);

            const char *suffix = "\r\nDigite outra linha:\r\n";
            HAL_UART_Transmit(&amp;huart2,
                              (uint8_t *)suffix,
                              strlen(suffix),
                              HAL_MAX_DELAY);

            // Aqui você chamaria o parser de comando:
            // Processar_Comando((char *)uartRxBuffer);

            // Zera índice para próxima linha
            uartRxIndex = 0;
        }

        // Seu código principal roda livremente aqui:
        // - Atualizar sensores
        // - Controlar motores
        // - Ler outros periféricos, etc.
    }
}
</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_GPIO_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">MX_USART2_UART_Init</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">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *startMsg </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">UART RX por interrupcao iniciada.</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: #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>
<span class="line"><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">startMsg</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                      </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">startMsg</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Inicia recepcao de 1 byte via interrupcao</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_UART_Receive_IT</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">uartRxByte</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</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: #ECEFF4">        </span><span style="color: #616E88">// Se uma linha completa foi recebida:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uartLineReady</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: #D8DEE9">uartLineReady</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>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// Garante que o buffer termine em &#39;\0&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">uartRxBuffer</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">uartRxIndex</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\0</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *prefix </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;IT&#93; Linha recebida: </span><span style="color: #ECEFF4">&quot;</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>
<span class="line"><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">prefix</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                              </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">prefix</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<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>
<span class="line"><span style="color: #D8DEE9FF">                              </span><span style="color: #D8DEE9">uartRxBuffer</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                              </span><span style="color: #D8DEE9">uartRxIndex</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *suffix </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">Digite outra linha:</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: #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>
<span class="line"><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">suffix</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                              </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">suffix</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// Aqui você chamaria o parser de comando:</span></span>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// Processar_Comando((char *)uartRxBuffer);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">            </span><span style="color: #616E88">// Zera índice para próxima linha</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">uartRxIndex</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: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Seu código principal roda livremente aqui:</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// - Atualizar sensores</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// - Controlar motores</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// - Ler outros periféricos, etc.</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">Repare que o <code>while(1)</code> não chama nenhuma função de recepção.<br>A recepção real acontece <strong>no callback de interrupção</strong>, que veremos agora.</p>



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



<h3 class="wp-block-heading">5.3. Callback <code>HAL_UART_RxCpltCallback</code>: núcleo da lógica de RX</h3>



<p class="wp-block-paragraph">A HAL chama automaticamente <code>HAL_UART_RxCpltCallback()</code> quando a recepção iniciada por <code>HAL_UART_Receive_IT</code> termina (no nosso caso, sempre que chega 1 byte).</p>



<p class="wp-block-paragraph">Implemente esse callback em <code>stm32f4xx_it.c</code> ou em <code>main.c</code> (onde preferir, desde que tenha o protótipo certo):</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 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
        uint8_t received = uartRxByte;

        // Exemplo opcional: eco imediato do caracter
        HAL_UART_Transmit(&amp;huart2, &amp;received, 1, HAL_MAX_DELAY);

        // Verifica se é fim de linha (ENTER)
        if (received == '\r' || received == '\n')
        {
            // Marca que uma linha completa foi recebida
            if (uartRxIndex > 0)  // ignora ENTERs vazios
            {
                uartLineReady = 1;
            }
        }
        else
        {
            // Armazena no buffer se ainda houver espaço
            if (uartRxIndex &lt; RX_BUFFER_SIZE - 1)
            {
                uartRxBuffer&#91;uartRxIndex++&#93; = received;
            }
            else
            {
                // Buffer lotado: descarta e sinaliza erro (opcional)
                const char *overflowMsg =
                    "\r\n&#91;ERRO&#93; Buffer RX lotado, descartando.\r\n";
                HAL_UART_Transmit(&amp;huart2,
                                  (uint8_t *)overflowMsg,
                                  strlen(overflowMsg),
                                  HAL_MAX_DELAY);
                uartRxIndex = 0;
            }
        }

        // Reagenda a recepcao de mais 1 byte
        HAL_UART_Receive_IT(&amp;huart2, &amp;uartRxByte, 1);
    }
}
</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">HAL_UART_RxCpltCallback</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">UART_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">huart</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">huart</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">Instance</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USART2</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: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">received</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uartRxByte</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Exemplo opcional: eco imediato do caracter</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">received</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>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Verifica se é fim de linha (ENTER)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">received</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\r</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">||</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">received</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&#39;</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: #ECEFF4">            </span><span style="color: #616E88">// Marca que uma linha completa foi recebida</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uartRxIndex</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)  </span><span style="color: #616E88">// ignora ENTERs vazios</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: #D8DEE9">uartLineReady</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</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: #D8DEE9FF">        </span><span style="color: #81A1C1">else</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 style="color: #616E88">// Armazena no buffer se ainda houver espaço</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uartRxIndex</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">RX_BUFFER_SIZE</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</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: #D8DEE9">uartRxBuffer</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">uartRxIndex</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">received</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: #81A1C1">else</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 style="color: #616E88">// Buffer lotado: descarta e sinaliza erro (opcional)</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">char</span><span style="color: #D8DEE9FF"> *overflowMsg </span><span style="color: #81A1C1">=</span></span>
<span class="line"><span style="color: #D8DEE9FF">                    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;ERRO&#93; Buffer RX lotado, descartando.</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: #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>
<span class="line"><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">overflowMsg</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                                  </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">overflowMsg</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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">uartRxIndex</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: #ECEFF4">}</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Reagenda a recepcao de mais 1 byte</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">HAL_UART_Receive_IT</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">uartRxByte</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</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"><strong>Pontos críticos:</strong></p>



<ol class="wp-block-list">
<li><strong>Sempre reagendar a recepção</strong> ao final do callback: <code>HAL_UART_Receive_IT(&amp;huart2, &amp;uartRxByte, 1);</code> Se esquecer essa linha, você recebe apenas o primeiro byte e depois nunca mais.</li>



<li>Nunca faça um loop demorado dentro do callback.<br>O callback deve ser <strong>curto e objetivo</strong>: copiar o byte, atualizar índice/flags e reagendar RX.</li>



<li>A flag <code>uartLineReady</code> é lida no <code>while(1)</code> e pode sinalizar que algo está pronto para processamento mais pesado <strong>fora</strong> da interrupção.</li>
</ol>



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



<h3 class="wp-block-heading">5.4. Tratando erros de UART com callback de erro (opcional mas recomendado)</h3>



<p class="wp-block-paragraph">Além de <code>RxCplt</code>, a HAL também chama <code>HAL_UART_ErrorCallback</code> em caso de:</p>



<ul class="wp-block-list">
<li><strong>Overrun</strong> (chega outro byte antes de você ler o anterior);</li>



<li><strong>Framing error</strong> (problemas de sincronismo);</li>



<li><strong>Noise</strong> etc.</li>
</ul>



<p class="wp-block-paragraph">Podemos colocar algo 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>void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
        const char *errMsg = "\r\n&#91;ERRO&#93; UART2 - ErrorCallback.\r\n";
        HAL_UART_Transmit(&amp;huart2,
                          (uint8_t *)errMsg,
                          strlen(errMsg),
                          HAL_MAX_DELAY);

        // Limpa estados de recepcao, se for o caso
        uartRxIndex = 0;
        uartLineReady = 0;

        // Reagenda recepcao
        HAL_UART_Receive_IT(&amp;huart2, &amp;uartRxByte, 1);
    }
}
</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">HAL_UART_ErrorCallback</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">UART_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">huart</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">huart</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">Instance</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">USART2</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">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *errMsg </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;ERRO&#93; UART2 - ErrorCallback.</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: #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>
<span class="line"><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">errMsg</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                          </span><span style="color: #88C0D0">strlen</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">errMsg</span><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><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>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Limpa estados de recepcao, se for o caso</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">uartRxIndex</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">uartLineReady</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>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Reagenda recepcao</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">HAL_UART_Receive_IT</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">uartRxByte</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</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">Isso ajuda a não “morrer” silenciosamente em casos de erro.</p>



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



<h3 class="wp-block-heading">5.5. Interpretando comandos recebidos (exemplo simples)</h3>



<p class="wp-block-paragraph">Vamos supor que você queira três comandos via UART:</p>



<ul class="wp-block-list">
<li><code>LED ON</code> → acende um LED na placa.</li>



<li><code>LED OFF</code> → apaga o LED.</li>



<li><code>STATUS</code> → imprime uma mensagem dizendo se o LED está ligado ou apagado.</li>
</ul>



<p class="wp-block-paragraph">Crie uma função simples de parser, por exemplo em <code>main.c</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>void Processar_Comando(const char *cmd)
{
    if (strcmp(cmd, "LED ON") == 0)
    {
        HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
        const char *resp = "\r\n&#91;OK&#93; LED ligado.\r\n";
        HAL_UART_Transmit(&amp;huart2, (uint8_t *)resp, strlen(resp), HAL_MAX_DELAY);
    }
    else if (strcmp(cmd, "LED OFF") == 0)
    {
        HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
        const char *resp = "\r\n&#91;OK&#93; LED desligado.\r\n";
        HAL_UART_Transmit(&amp;huart2, (uint8_t *)resp, strlen(resp), HAL_MAX_DELAY);
    }
    else if (strcmp(cmd, "STATUS") == 0)
    {
        GPIO_PinState state = HAL_GPIO_ReadPin(LD2_GPIO_Port, LD2_Pin);
        const char *respOn  = "\r\n&#91;STATUS&#93; LED esta LIGADO.\r\n";
        const char *respOff = "\r\n&#91;STATUS&#93; LED esta DESLIGADO.\r\n";

        if (state == GPIO_PIN_SET)
            HAL_UART_Transmit(&amp;huart2, (uint8_t *)respOn, strlen(respOn), HAL_MAX_DELAY);
        else
            HAL_UART_Transmit(&amp;huart2, (uint8_t *)respOff, strlen(respOff), HAL_MAX_DELAY);
    }
    else
    {
        const char *resp = "\r\n&#91;ERRO&#93; Comando desconhecido.\r\n";
        HAL_UART_Transmit(&amp;huart2, (uint8_t *)resp, strlen(resp), 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: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Processar_Comando</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">cmd</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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">strcmp</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">cmd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">LED ON</span><span style="color: #ECEFF4">&quot;</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: #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_GPIO_WritePin</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LD2_GPIO_Port</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LD2_Pin</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">GPIO_PIN_SET</span><span style="color: #D8DEE9FF">)</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">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;OK&#93; LED ligado.</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: #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">resp</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">resp</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: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">strcmp</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">cmd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">LED OFF</span><span style="color: #ECEFF4">&quot;</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: #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_GPIO_WritePin</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LD2_GPIO_Port</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LD2_Pin</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">GPIO_PIN_RESET</span><span style="color: #D8DEE9FF">)</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">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;OK&#93; LED desligado.</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: #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">resp</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">resp</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: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #88C0D0">strcmp</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">cmd</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">STATUS</span><span style="color: #ECEFF4">&quot;</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: #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: #D8DEE9">GPIO_PinState</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">state</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">HAL_GPIO_ReadPin</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">LD2_GPIO_Port</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LD2_Pin</span><span style="color: #D8DEE9FF">)</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">char</span><span style="color: #D8DEE9FF"> *respOn  </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;STATUS&#93; LED esta LIGADO.</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: #D8DEE9FF">        </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *respOff </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;STATUS&#93; LED esta DESLIGADO.</span><span style="color: #EBCB8B">\r\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">state</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">GPIO_PIN_SET</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 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">respOn</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">respOn</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: #81A1C1">else</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">respOff</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">respOff</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: #81A1C1">else</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">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">char</span><span style="color: #D8DEE9FF"> *resp </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\r\n</span><span style="color: #A3BE8C">&#91;ERRO&#93; Comando desconhecido.</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: #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">resp</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">resp</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: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">E no <code>while(1)</code> (reaproveitando o código da seção 5.2):</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>if (uartLineReady)
{
    uartLineReady = 0;
    uartRxBuffer&#91;uartRxIndex&#93; = '\0';

    // Chama o parser
    Processar_Comando((char *)uartRxBuffer);

    // Redefine para próxima linha
    uartRxIndex = 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: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uartLineReady</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">uartLineReady</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">uartRxBuffer</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">uartRxIndex</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #EBCB8B">\0</span><span style="color: #ECEFF4">&#39;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Chama o parser</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">Processar_Comando</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: #D8DEE9FF">)</span><span style="color: #D8DEE9">uartRxBuffer</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">// Redefine para próxima linha</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uartRxIndex</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: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Agora você tem um mini “terminal de comandos” via UART, completamente assíncrono:</p>



<ul class="wp-block-list">
<li>O microcontrolador pode rodar outras tarefas no <code>while(1)</code>.</li>



<li>Os bytes são recebidos em background por interrupção.</li>



<li>Quando uma linha é fechada com ENTER, o comando é interpretado.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Ponto para inserir imagem 10:</strong> terminal mostrando <code>LED ON</code>, <code>LED OFF</code>, <code>STATUS</code> e respostas.</p>
</blockquote>



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



<h3 class="wp-block-heading">5.6. Resumo do fluxo RX por interrupção</h3>



<ol class="wp-block-list">
<li>Configura USART2 no CubeMX (TX/RX, NVIC habilitado).</li>



<li>Gera o código, verifica <code>MX_USART2_UART_Init()</code>.</li>



<li>Cria:
<ul class="wp-block-list">
<li><code>uartRxByte</code> (buffer de 1 byte);</li>



<li><code>uartRxBuffer[]</code> (buffer maior);</li>



<li>Índice <code>uartRxIndex</code> e flag <code>uartLineReady</code>.</li>
</ul>
</li>



<li>Inicia <code>HAL_UART_Receive_IT(&amp;huart2, &amp;uartRxByte, 1);</code> no <code>main()</code>.</li>



<li>Implementa <code>HAL_UART_RxCpltCallback</code>:
<ul class="wp-block-list">
<li>Copia <code>uartRxByte</code> para <code>uartRxBuffer</code>;</li>



<li>Detecta <code>\r</code>/<code>\n</code>;</li>



<li>Atualiza índice/flags;</li>



<li>Reagenda <code>HAL_UART_Receive_IT(...)</code>.</li>
</ul>
</li>



<li>No <code>while(1)</code>, verifica <code>uartLineReady</code> e processa o comando.</li>
</ol>



<p class="wp-block-paragraph">Com isso, você tem uma base sólida para qualquer protocolo simples baseado em texto ou mesmo binário (adaptando o parser).</p>



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



<h2 class="wp-block-heading">6. Boas práticas, extensões e organização avançada para UART no STM32F411RE</h2>



<p class="wp-block-paragraph">Nesta seção final do tutorial, consolidaremos o conhecimento e ampliaremos para cenários reais de engenharia embarcada, abordando:</p>



<ul class="wp-block-list">
<li>Boas práticas essenciais para evitar perda de dados e travamentos.</li>



<li>Quando usar <strong>DMA</strong>, buffers circulares (ring buffers) e filas (queues).</li>



<li>Estratégias de modularização do código para projetos maiores.</li>



<li>Cuidados elétricos e físicos ao trabalhar com UART.</li>



<li>Finalização do tutorial.</li>
</ul>



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



<h1 class="wp-block-heading">6.1. Boas práticas essenciais</h1>



<h3 class="wp-block-heading">6.1.1. Reagendar sempre o <code>HAL_UART_Receive_IT</code></h3>



<p class="wp-block-paragraph">Esse é o erro mais comum de iniciantes:</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>HAL_UART_Receive_IT(&amp;huart2, &amp;uartRxByte, 1);
</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">HAL_UART_Receive_IT</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: #81A1C1">&amp;</span><span style="color: #D8DEE9">uartRxByte</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Se faltar isso no final do callback, sua UART vai “parar de receber” após o primeiro byte.</strong><br>No fluxo de recepção por interrupção, essa linha é obrigatória.</p>



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



<h3 class="wp-block-heading">6.1.2. Mantenha o callback curto e livre de delays</h3>



<p class="wp-block-paragraph">Nunca faça:</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>HAL_Delay(100);
processamento_pesado();
calculo_matricial();
</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">HAL_Delay</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 style="color: #88C0D0">processamento_pesado</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">calculo_matricial</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">O callback deve <strong>simplesmente</strong>:</p>



<ul class="wp-block-list">
<li>ler o byte recebido,</li>



<li>salvar no buffer,</li>



<li>ajustar índices e flags,</li>



<li>reagendar a recepção.</li>
</ul>



<p class="wp-block-paragraph">Todo o processamento pesado deve ocorrer no <code>while(1)</code> ou em tasks de RTOS.</p>



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



<h3 class="wp-block-heading">6.1.3. Proteja buffers globais se houver múltiplos contextos</h3>



<p class="wp-block-paragraph">Se você estiver rodando FreeRTOS ou outro sistema multitarefa:</p>



<ul class="wp-block-list">
<li>Use <strong>mutex</strong> para escrever em buffers compartilhados.</li>



<li>Ou use um <strong>queue</strong> para comunicação UART → tarefa de parser.</li>
</ul>



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



<h3 class="wp-block-heading">6.1.4. Use timeouts realistas nos modos bloqueantes</h3>



<p class="wp-block-paragraph"><code>HAL_MAX_DELAY</code> é aceitável para testes, mas ruim em aplicações reais.<br>Se você precisa manter o sistema reativo, use timeouts pequenos e teste o retorno.</p>



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



<h3 class="wp-block-heading">6.1.5. Trate o callback de erro</h3>



<p class="wp-block-paragraph">Erros de framing, overrun e noise podem acontecer em ambientes ruidosos.<br>Tenha sempre:</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 HAL_UART_ErrorCallback(...)
</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">HAL_UART_ErrorCallback</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">para reinicializar buffers e reagendar recepção.</p>



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



<h1 class="wp-block-heading">6.2. Quando usar DMA e buffers circulares (ring buffers)</h1>



<h3 class="wp-block-heading">6.2.1. DMA: ideal para fluxos contínuos e altos volumes</h3>



<p class="wp-block-paragraph">A DMA libera totalmente a CPU durante a recepção ou transmissão, útil quando:</p>



<ul class="wp-block-list">
<li>Recebe grandes volumes de dados (por exemplo, GPS NMEA, telemetria, logs extensos).</li>



<li>Envia pacotes longos com alta frequência.</li>



<li>Há risco de perda de bytes se o callback de interrupção for lento.</li>
</ul>



<p class="wp-block-paragraph">Com DMA, você pode usar <strong>double buffering</strong> ou <strong>ring buffers</strong> para processar dados de forma eficiente.</p>



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



<h3 class="wp-block-heading">6.2.2. Buffer circular (ring buffer)</h3>



<p class="wp-block-paragraph">Para RX contínuo, uma abordagem profissional é:</p>



<ul class="wp-block-list">
<li>Criar um buffer circular grande (por exemplo, 256 ou 512 bytes).</li>



<li>A DMA grava nele continuamente.</li>



<li>Um ponteiro de leitura (<code>readIndex</code>) processa os dados conforme chegam.</li>



<li>A DMA apenas avança o ponteiro de escrita (<code>writeIndex</code>).</li>
</ul>



<p class="wp-block-paragraph">Essa técnica é usada em sistemas onde a UART não pode perder nenhum dado.</p>



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



<h3 class="wp-block-heading">6.2.3. Comparação dos métodos de RX</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Método</th><th>Vantagens</th><th>Desvantagens</th></tr></thead><tbody><tr><td><strong>Polling</strong></td><td>Simples; ideal para menus</td><td>Travamento do CPU; risco de perda de dados</td></tr><tr><td><strong>Interrupção (IT)</strong></td><td>Rápido; seguro; ideal para comandos</td><td>Requer cuidado com buffers e callbacks</td></tr><tr><td><strong>DMA</strong></td><td>Máxima eficiência; ideal para grandes fluxos</td><td>Mais complexo; exige ring buffer</td></tr></tbody></table></figure>



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



<h1 class="wp-block-heading">6.3. Organização modular do código</h1>



<p class="wp-block-paragraph">Em projetos maiores, não é prático manter todo o código UART em <code>main.c</code>.<br>A recomendação é separar em módulos:</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>Core/Src/usart.c        ← inicialização gerada pela HAL
Core/Inc/usart.h

Core/Src/serial.c       ← funções Serial_SendString, Processar_Comando, callbacks
Core/Inc/serial.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: #D8DEE9">Core</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Src</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">usart</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">c</span><span style="color: #D8DEE9FF">        ← </span><span style="color: #D8DEE9">inicialização</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gerada</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pela</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">HAL</span></span>
<span class="line"><span style="color: #D8DEE9">Core</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Inc</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">usart</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">Core</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Src</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">serial</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">c</span><span style="color: #D8DEE9FF">       ← </span><span style="color: #D8DEE9">funções</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Serial_SendString</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Processar_Comando</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">callbacks</span></span>
<span class="line"><span style="color: #D8DEE9">Core</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">Inc</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">serial</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Estrutura sugerida no <code>serial.h</code></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>#ifndef SERIAL_H
#define SERIAL_H

#include &lt;stdint.h>

void Serial_Init(void);
void Serial_SendString(const char *str);
void Serial_Process(void);   // chamada no while(1)
void Processar_Comando(const char *cmd);

#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">ifndef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SERIAL_H</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">SERIAL_H</span></span>
<span class="line"></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">stdint</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: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Serial_Init</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Serial_SendString</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">str</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Serial_Process</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: #D8DEE9FF">   </span><span style="color: #616E88">// chamada no while(1)</span></span>
<span class="line"><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Processar_Comando</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">cmd</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: #D8DEE9">endif</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">No <code>serial.c</code></h3>



<ul class="wp-block-list">
<li>Implementa as funções de transmissão.</li>



<li>Implementa o callback <code>HAL_UART_RxCpltCallback</code>.</li>



<li>Implementa parsers e tratamento de erros.</li>
</ul>



<h3 class="wp-block-heading">No <code>main.c</code></h3>



<p class="wp-block-paragraph">Fica apenas:</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>Serial_Init();

while (1)
{
    Serial_Process();
    // outras tarefas
}
</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">Serial_Init</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"></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">Serial_Process</span><span style="color: #D8DEE9FF">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// outras tarefas</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 mantém o código do projeto limpo e facilita testes unitários e reutilização.</p>



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



<h1 class="wp-block-heading">6.4. Cuidados elétricos ao usar UART externamente</h1>



<p class="wp-block-paragraph">Embora a Nucleo tenha conversão USB <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> UART embutida, quando você usar UART em conectores externos, observe:</p>



<h3 class="wp-block-heading">6.4.1. Tensão dos sinais</h3>



<p class="wp-block-paragraph">O STM32F411RE opera em <strong>3.3V</strong>.</p>



<ul class="wp-block-list">
<li>Nunca conecte diretamente uma UART em <strong>5V</strong>.</li>



<li>Use conversores de nível (level shifters) se necessário.</li>
</ul>



<h3 class="wp-block-heading">6.4.2. GND comum</h3>



<p class="wp-block-paragraph">Sempre conecte o <strong>GND</strong> do dispositivo externo ao GND do STM32.</p>



<h3 class="wp-block-heading">6.4.3. Comprimento dos cabos</h3>



<p class="wp-block-paragraph">Cabos muito longos (&gt;2m) podem introduzir:</p>



<ul class="wp-block-list">
<li>Ruídos</li>



<li>Cross-talk</li>



<li>Desalinhamento de clock serial</li>
</ul>



<p class="wp-block-paragraph">Para cabos longos, considere RS485.</p>



<h3 class="wp-block-heading">6.4.4. Ruído e indução</h3>



<p class="wp-block-paragraph">Ambientes industriais exigem:</p>



<ul class="wp-block-list">
<li>Cabos blindados</li>



<li>Filtros EMI</li>



<li>Evitar passar UART próximo a motores e trilhos de potência</li>
</ul>



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



<h1 class="wp-block-heading">6.5. Checklist final do UART para STM32</h1>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> UART configurada no CubeMX<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Interrupção habilitada na NVIC<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Buffer de 1 byte para RX via IT<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Reagendar recepção automaticamente<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Parser de comandos isolado<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Código modularizado<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2714.png" alt="✔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Testado com terminal serial no PC</p>



<p class="wp-block-paragraph">Com isso, você tem uma UART profissional, robusta e escalável.</p><p>The post <a href="https://mcu.tec.br/microcontroladores/stm32/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> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">972</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 loading="lazy" 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>
		<item>
		<title>Construindo um Servidor Web Embarcado com STM32F429ZI e Azure RTOS NetX Duo</title>
		<link>https://mcu.tec.br/microcontroladores/construindo-um-servidor-web-embarcado-com-stm32f429zi-e-azure-rtos-netx-duo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=construindo-um-servidor-web-embarcado-com-stm32f429zi-e-azure-rtos-netx-duo</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 03 Oct 2025 21:08:21 +0000</pubDate>
				<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[STM32]]></category>
		<category><![CDATA[Azure RTOS]]></category>
		<category><![CDATA[DHCP STM32]]></category>
		<category><![CDATA[IoT com STM32]]></category>
		<category><![CDATA[LED controle web]]></category>
		<category><![CDATA[memória flash STM32]]></category>
		<category><![CDATA[microcontrolador ARM]]></category>
		<category><![CDATA[NetX Duo]]></category>
		<category><![CDATA[programação embarcada]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[servidor HTTP embarcado]]></category>
		<category><![CDATA[servidor web microcontrolador]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[STM32CubeProgrammer]]></category>
		<category><![CDATA[STM32F429ZI]]></category>
		<category><![CDATA[ThreadX]]></category>
		<category><![CDATA[WebServer STM32]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=844</guid>

					<description><![CDATA[<p>Aprenda passo a passo como transformar a placa STM32F429ZI em um servidor web embarcado utilizando o Azure RTOS NetX Duo. Este guia didático explica desde os conceitos básicos, como o funcionamento de um RTOS e de um servidor HTTP, até os detalhes práticos de gravação de arquivos na memória flash com o STM32CubeProgrammer. Ideal para iniciantes que desejam compreender como sistemas embarcados podem hospedar páginas HTML e interagir com navegadores, tornando-se soluções completas em IoT e automação.</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/construindo-um-servidor-web-embarcado-com-stm32f429zi-e-azure-rtos-netx-duo/">Construindo um Servidor Web Embarcado com STM32F429ZI e Azure RTOS NetX Duo</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1 class="wp-block-heading">Introdução ao Projeto Nx_WebServer no STM32F429ZI</h1>



<p class="wp-block-paragraph">A aplicação <strong>Nx_WebServer</strong> é um exemplo prático que demonstra como construir um servidor web embarcado utilizando o <strong>Azure RTOS NetX Duo</strong> em conjunto com a placa <strong>STM32F429ZI-Nucleo</strong>. Esse exemplo é particularmente útil porque reúne, em um único projeto, conceitos fundamentais de sistemas embarcados modernos: uso de um <strong>RTOS</strong> (Sistema Operacional de Tempo Real), pilha de rede embarcada, sistema de arquivos em memória flash e a disponibilização de serviços através de um <strong>WebServer HTTP</strong>.</p>



<p class="wp-block-paragraph">Para um iniciante, pode ser difícil compreender como tudo isso se conecta, por isso este artigo tem como objetivo explicar, de forma <strong>didática e detalhada</strong>, cada uma das etapas e conceitos envolvidos. Além de mostrar como carregar e executar o exemplo, também apresentaremos os fundamentos do que é o <strong>NetX Duo</strong>, o papel de um <strong>servidor HTTP</strong> e por que ferramentas como o <strong>STM32CubeProgrammer</strong> devem ser usadas corretamente — inclusive pela linha de comando — para garantir 100% de sucesso na gravação do conteúdo.</p>



<p class="wp-block-paragraph">No decorrer do artigo, você aprenderá:</p>



<ul class="wp-block-list">
<li>O que é o <strong>Azure RTOS NetX Duo</strong> e por que ele é utilizado neste projeto.</li>



<li>Como funciona um <strong>servidor HTTP</strong> embarcado e qual a diferença entre páginas estáticas e dinâmicas.</li>



<li>O papel das <strong>threads</strong> criadas no exemplo (AppMainThread e AppWebServerThread).</li>



<li>A importância da correta preparação da memória flash, incluindo a gravação do arquivo de conteúdo web.</li>



<li>Como interpretar os comportamentos esperados e os sinais de erro durante a execução.</li>



<li>Dicas para iniciantes compreenderem como o RTOS gerencia recursos como memória, temporização e comunicação de rede.</li>
</ul>



<p class="wp-block-paragraph">A partir dessa visão, mesmo um leitor leigo poderá entender como uma simples placa de desenvolvimento pode se transformar em um <strong>servidor web funcional</strong>, capaz de exibir páginas HTML diretamente de sua memória interna e até mesmo interagir com o usuário, por exemplo, acionando o LED verde da placa através de um navegador.</p>



<h1 class="wp-block-heading">O que é o Azure RTOS NetX Duo e sua Função no Projeto</h1>



<p class="wp-block-paragraph">Para compreender o funcionamento do <strong>Nx_WebServer</strong>, é essencial primeiro entender o que é o <strong>Azure RTOS NetX Duo</strong>. Trata-se de uma <strong>pilha de protocolos de rede TCP/IP</strong> projetada especificamente para sistemas embarcados. Diferente de sistemas operacionais completos, como Linux ou Windows, em que a pilha de rede já faz parte do núcleo, no mundo dos microcontroladores é necessário integrar uma biblioteca que permita ao dispositivo se comunicar em redes Ethernet ou Wi-Fi.</p>



<p class="wp-block-paragraph">O NetX Duo é chamado de “Duo” porque implementa tanto o <strong>IPv4</strong> quanto o <strong>IPv6</strong>, garantindo compatibilidade com redes atuais e futuras. Ele é otimizado para rodar em dispositivos com recursos limitados, como microcontroladores STM32, oferecendo:</p>



<ul class="wp-block-list">
<li><strong>Baixo consumo de memória e processamento</strong></li>



<li><strong>Confiabilidade em tempo real</strong>, essencial em aplicações críticas</li>



<li><strong>Escalabilidade</strong>, permitindo adicionar ou remover recursos de acordo com a necessidade</li>
</ul>



<p class="wp-block-paragraph">Dentro do projeto Nx_WebServer, o NetX Duo é responsável por todo o gerenciamento da comunicação em rede. É ele quem:</p>



<ul class="wp-block-list">
<li>Cria e administra a instância de IP (<code>NX_IP</code>) usada pela placa.</li>



<li>Configura protocolos de suporte, como <strong>ARP</strong> (Address Resolution Protocol), <strong>ICMP</strong> (Internet Control Message Protocol), <strong>UDP</strong> e <strong>TCP</strong>.</li>



<li>Controla o <strong>cliente DHCP</strong>, que negocia automaticamente um endereço IP com o roteador ou servidor da rede local.</li>
</ul>



<p class="wp-block-paragraph">Em outras palavras, sem o NetX Duo, a placa STM32 não conseguiria sequer obter um endereço IP para se comunicar na rede. Ele funciona como a “cola” que conecta o hardware da placa ao mundo da Internet.</p>



<p class="wp-block-paragraph">Um aspecto importante é que o NetX Duo foi projetado para rodar em conjunto com o <strong>ThreadX</strong>, o RTOS (Real-Time Operating System) do qual falaremos mais adiante. Essa integração é fundamental porque permite que tarefas de rede sejam executadas de forma <strong>concorrente</strong>, sem travar outras funções do sistema. Por exemplo, enquanto o servidor HTTP responde a uma requisição de página, outras threads podem continuar monitorando sensores, gravando em memória ou atualizando o display.</p>



<p class="wp-block-paragraph">Em resumo:<br>O NetX Duo é o <strong>coração da conectividade de rede</strong> neste exemplo. Ele transforma o STM32 em um dispositivo capaz de se comportar como qualquer outro nó de rede, participando de trocas de pacotes, comunicação cliente-servidor e, especificamente, como <strong>servidor HTTP embarcado</strong>.</p>



<h1 class="wp-block-heading">O que é um Servidor HTTP Embarcado e Como Funciona no STM32</h1>



<p class="wp-block-paragraph">Um <strong>servidor HTTP</strong> é um programa capaz de responder a requisições feitas por um navegador (como Google Chrome, Firefox ou Edge). Quando digitamos um endereço como <code>http://192.168.0.10/index.html</code>, o navegador envia uma solicitação (request) ao servidor, que responde com o arquivo correspondente (response), normalmente uma página em formato <strong>HTML</strong>.</p>



<p class="wp-block-paragraph">No mundo dos computadores convencionais, esses servidores costumam ser softwares robustos como <strong>Apache</strong>, <strong>Nginx</strong> ou <strong>IIS</strong>, rodando em máquinas com sistemas operacionais completos. Porém, em sistemas embarcados como o <strong>STM32F429ZI</strong>, a situação é diferente: o servidor precisa ser <strong>leve, rápido e econômico em memória</strong>, ao mesmo tempo em que oferece funcionalidades básicas para interação com o usuário.</p>



<p class="wp-block-paragraph">O <strong>Nx_WebServer</strong> mostra exatamente isso: como transformar a placa STM32 em um servidor web simples, mas funcional. No exemplo:</p>



<ul class="wp-block-list">
<li>Os arquivos HTML, imagens ou scripts são gravados diretamente na <strong>memória flash</strong> do microcontrolador.</li>



<li>O servidor HTTP, criado com a biblioteca do <strong>NetX Duo</strong>, responde a requisições de navegadores conectados à mesma rede.</li>



<li>Páginas como <strong>index.html</strong> e <strong>dashboard.html</strong> podem ser acessadas digitando o IP da placa no navegador.</li>
</ul>



<h3 class="wp-block-heading">Páginas Estáticas e Dinâmicas</h3>



<p class="wp-block-paragraph">Um ponto importante é a diferença entre <strong>páginas estáticas</strong> e <strong>páginas dinâmicas</strong>:</p>



<ul class="wp-block-list">
<li><strong>Estáticas:</strong> São arquivos prontos, como <code>index.html</code>, que apenas exibem informações fixas (texto, imagens).</li>



<li><strong>Dinâmicas:</strong> São geradas ou modificadas em tempo real pelo servidor. No exemplo do Nx_WebServer, a página <strong>dashboard.html</strong> é dinâmica, porque permite <strong>interagir com a placa</strong> – o usuário pode, por exemplo, clicar em um botão para acender ou apagar o LED verde da Nucleo, e a ação é refletida imediatamente no hardware.</li>
</ul>



<h3 class="wp-block-heading">Threads no Servidor</h3>



<p class="wp-block-paragraph">O servidor HTTP embarcado funciona através de <strong>threads</strong> criadas pelo RTOS ThreadX:</p>



<ul class="wp-block-list">
<li>A <strong>AppMainThread</strong> inicia a rede, aguarda a obtenção de um endereço IP via DHCP e, quando tudo está pronto, libera a execução do servidor.</li>



<li>A <strong>AppWebServerThread</strong> é responsável por abrir o sistema de arquivos na flash e iniciar o servidor HTTP.</li>
</ul>



<p class="wp-block-paragraph">Essa separação é essencial porque permite que o sistema seja <strong>multitarefa</strong>, garantindo que cada função (rede, servidor, controle de LED, etc.) tenha o seu espaço de execução ordenado pelo RTOS.</p>



<h3 class="wp-block-heading">Benefício para o Usuário</h3>



<p class="wp-block-paragraph">Na prática, o que o usuário vê é simples:</p>



<ol class="wp-block-list">
<li>Conecta a placa à rede.</li>



<li>Descobre o endereço IP no terminal serial.</li>



<li>Digita esse IP no navegador.</li>



<li>Visualiza páginas hospedadas dentro do próprio microcontrolador.</li>
</ol>



<p class="wp-block-paragraph">Isso transforma o <strong>STM32F429ZI</strong> em um <strong>servidor web portátil e independente</strong>, sem precisar de um computador externo para entregar as páginas.</p>



<h1 class="wp-block-heading">O Papel das Threads AppMainThread e AppWebServerThread</h1>



<p class="wp-block-paragraph">O funcionamento do <strong>Nx_WebServer</strong> depende diretamente da coordenação entre duas threads principais criadas pelo <strong>ThreadX</strong>, o sistema operacional de tempo real que organiza a execução das tarefas. Essas threads são como “linhas de trabalho” independentes que, juntas, mantêm a aplicação em funcionamento estável e responsivo.</p>



<h3 class="wp-block-heading">AppMainThread – Inicialização e Rede</h3>



<p class="wp-block-paragraph">A primeira thread criada é a <strong>AppMainThread</strong>, responsável por preparar o ambiente de rede e dar início ao funcionamento do sistema. Ela é configurada para iniciar automaticamente assim que o kernel do ThreadX é carregado.</p>



<p class="wp-block-paragraph">Dentro dessa thread, as principais ações realizadas são:</p>



<ol class="wp-block-list">
<li><strong>Inicialização do cliente DHCP</strong> – permite que a placa obtenha automaticamente um endereço IP da rede local, evitando a necessidade de configurar manualmente.</li>



<li><strong>Aguardando resolução de IP</strong> – a thread permanece em espera até que o endereço IP seja corretamente atribuído. Esse passo é essencial, pois sem IP não há comunicação de rede possível.</li>



<li><strong>Ativação da AppWebServerThread</strong> – quando a rede está pronta, a AppMainThread “acorda” a thread do servidor web, garantindo que o HTTP Server só comece a funcionar quando a conectividade estiver estabelecida.</li>
</ol>



<p class="wp-block-paragraph">Em resumo, a <strong>AppMainThread</strong> é responsável pela fase de <strong>configuração e preparação da rede</strong>, funcionando como um “porteiro” que só libera o servidor quando tudo está em ordem.</p>



<h3 class="wp-block-heading">AppWebServerThread – O Servidor HTTP</h3>



<p class="wp-block-paragraph">A segunda thread, chamada <strong>AppWebServerThread</strong>, é criada mas não inicia de imediato. Ela depende da autorização da AppMainThread para começar, respeitando a ordem correta de inicialização.</p>



<p class="wp-block-paragraph">As funções principais dessa thread são:</p>



<ol class="wp-block-list">
<li><strong>Abrir o driver da memória flash</strong> – é nessa memória que os arquivos HTML e outros conteúdos foram gravados previamente, como veremos mais adiante.</li>



<li><strong>Iniciar o servidor HTTP</strong> – cria a instância do servidor e começa a escutar por requisições vindas dos navegadores.</li>



<li><strong>Processar requisições</strong> – cada vez que um cliente acessa uma página (<code>index.html</code>, <code>dashboard.html</code>, etc.), a requisição é passada para o <strong>webserver_request_notify_callback</strong>, que decide como responder.
<ul class="wp-block-list">
<li>Se o arquivo for estático (como <code>index.html</code>), o conteúdo é apenas enviado de volta.</li>



<li>Se for dinâmico (como no caso do controle do LED), a resposta é adaptada ao comando solicitado.</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">Assim, a <strong>AppWebServerThread</strong> é o coração da aplicação, transformando a placa em um <strong>servidor funcional</strong> que pode ser acessado de qualquer navegador da rede local.</p>



<h3 class="wp-block-heading">Coordenação entre as Threads</h3>



<p class="wp-block-paragraph">A separação em duas threads garante que a aplicação seja <strong>robusta e modular</strong>:</p>



<ul class="wp-block-list">
<li>Uma thread cuida da <strong>rede e inicialização</strong>.</li>



<li>A outra cuida do <strong>servidor HTTP</strong>.</li>
</ul>



<p class="wp-block-paragraph">Essa divisão evita erros comuns em sistemas embarcados, como tentar iniciar um serviço de rede antes de ter um endereço IP válido. Além disso, permite que cada parte do sistema seja ajustada ou expandida no futuro sem comprometer o funcionamento das demais.</p>



<h1 class="wp-block-heading">Preparando a Memória Flash com o STM32CubeProgrammer</h1>



<p class="wp-block-paragraph">Um dos pontos mais importantes para o funcionamento do <strong>Nx_WebServer</strong> é garantir que os arquivos web (páginas HTML, imagens e scripts) estejam gravados corretamente na memória flash do <strong>STM32F429ZI</strong>. Sem esse passo, mesmo que o servidor HTTP seja iniciado com sucesso, não haverá conteúdo para enviar ao navegador.</p>



<h3 class="wp-block-heading">O papel do STM32CubeProgrammer</h3>



<p class="wp-block-paragraph">O <strong>STM32CubeProgrammer</strong> é a ferramenta oficial da STMicroelectronics para gravação de firmwares, configuração de memória e depuração básica em microcontroladores STM32. Embora ele possua uma interface gráfica, no caso do <strong>Nx_WebServer</strong> a recomendação é utilizar a <strong>linha de comando</strong>.</p>



<p class="wp-block-paragraph">Isso porque a execução via <strong>CLI (Command Line Interface)</strong> garante:</p>



<ol class="wp-block-list">
<li><strong>Precisão absoluta no endereço de gravação</strong> – evita erros ao selecionar o ponto inicial da memória flash.</li>



<li><strong>Automação</strong> – o mesmo comando pode ser repetido sempre que necessário, sem depender de cliques manuais.</li>



<li><strong>Compatibilidade com tutoriais e exemplos</strong> – a própria ST fornece os comandos prontos para uso, facilitando a reprodução dos resultados.</li>
</ol>



<h3 class="wp-block-heading">O comando essencial</h3>



<p class="wp-block-paragraph">Para gravar o conteúdo web na memória flash, deve-se executar no terminal:</p>



<pre class="wp-block-code"><code>&lt;INSTALL_PATH&gt;STM32CubeProgrammer\bin\STM32_Programmer_CLI.exe -c port=swd -w &lt;INSTALL_PATH&gt;web_content\web_demo.bin 0x08100000 -v
</code></pre>



<p class="wp-block-paragraph">Explicando cada parte:</p>



<ul class="wp-block-list">
<li><strong><code>&lt;INSTALL_PATH></code></strong> → caminho onde o STM32CubeProgrammer foi instalado.</li>



<li><strong><code>STM32_Programmer_CLI.exe</code></strong> → executável da versão de linha de comando.</li>



<li><strong><code>-c port=swd</code></strong> → indica que a conexão com a placa será feita via <strong>SWD (Serial Wire Debug)</strong>, o protocolo padrão para gravação em STM32.</li>



<li><strong><code>-w &lt;arquivo> &lt;endereço></code></strong> → grava o arquivo binário especificado no endereço de memória desejado.
<ul class="wp-block-list">
<li><code>&lt;arquivo></code> → no caso, <code>web_demo.bin</code>, que contém as páginas web.</li>



<li><code>&lt;endereço></code> → <code>0x08100000</code>, local da flash reservado para armazenar os arquivos web.</li>
</ul>
</li>



<li><strong><code>-v</code></strong> → ativa a verificação após a gravação, garantindo que o conteúdo foi escrito corretamente.</li>
</ul>



<h3 class="wp-block-heading">Importância de seguir o processo corretamente</h3>



<p class="wp-block-paragraph">Muitos erros relatados por iniciantes acontecem porque:</p>



<ul class="wp-block-list">
<li>O arquivo binário não foi gravado no endereço correto.</li>



<li>A gravação foi feita apenas pelo IDE, sem incluir os arquivos web.</li>



<li>Não houve a etapa de verificação após a gravação.</li>
</ul>



<p class="wp-block-paragraph">Por isso, insistimos: <strong>use sempre o STM32CubeProgrammer pela linha de comando</strong>, como mostrado acima, para garantir <strong>100% de sucesso</strong>.</p>



<p class="wp-block-paragraph">Ao final dessa etapa, a memória flash da placa conterá não apenas o firmware principal, mas também o sistema de arquivos com as páginas HTML. Isso permite que, ao digitar o IP da placa no navegador, o conteúdo seja carregado corretamente.</p>



<h1 class="wp-block-heading">Comportamentos Esperados e Sinais de Erro</h1>



<p class="wp-block-paragraph">Depois de gravar corretamente o firmware e o conteúdo web na memória flash do <strong>STM32F429ZI</strong>, é importante saber o que observar para confirmar que tudo está funcionando como deveria. O projeto <strong>Nx_WebServer</strong> foi projetado para dar ao usuário <strong>indicações claras de sucesso ou falha</strong>, tanto pelo terminal serial quanto pelos LEDs da placa.</p>



<h3 class="wp-block-heading">Comportamento de Sucesso</h3>



<p class="wp-block-paragraph">Quando o servidor HTTP é iniciado com sucesso, os seguintes sinais aparecem:</p>



<ol class="wp-block-list">
<li><strong>Endereço IP exibido no terminal</strong>
<ul class="wp-block-list">
<li>Assim que o DHCP atribui um IP válido à placa, o endereço é mostrado na saída serial.</li>



<li>Exemplo: <code>Board IP address: 192.168.0.105</code></li>



<li>Esse é o endereço que você deve digitar no navegador.</li>
</ul>
</li>



<li><strong>Páginas acessíveis via navegador</strong>
<ul class="wp-block-list">
<li>Ao abrir o navegador e digitar <code>http://&lt;IP>/index.html</code>, a <strong>página inicial</strong> deve ser carregada.</li>



<li>Ao acessar <code>http://&lt;IP>/dashboard.html</code>, você verá a <strong>página de controle</strong>.</li>
</ul>
</li>



<li><strong>Interação com a placa</strong>
<ul class="wp-block-list">
<li>Na página <strong>dashboard</strong>, é possível interagir com a placa, por exemplo, ligando ou desligando o LED verde.</li>



<li>Também são exibidas informações do <strong>ThreadX</strong> e do <strong>NetX Duo</strong>, demonstrando a integração entre o RTOS e a pilha de rede.</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">Esses três sinais confirmam que todo o sistema – firmware, pilha de rede, servidor HTTP e arquivos web – está funcionando corretamente.</p>



<h3 class="wp-block-heading">Comportamento de Erro</h3>



<p class="wp-block-paragraph">Caso algo não tenha sido configurado ou gravado corretamente, os sintomas mais comuns são:</p>



<ol class="wp-block-list">
<li><strong>LED verde apagado</strong>
<ul class="wp-block-list">
<li>Se o servidor HTTP não foi inicializado corretamente, o LED verde da placa permanece desligado.</li>



<li>Esse é o sinal mais direto de falha na execução.</li>
</ul>
</li>



<li><strong>Páginas não carregam no navegador</strong>
<ul class="wp-block-list">
<li>Se ao digitar o IP no navegador não houver resposta, pode significar:
<ul class="wp-block-list">
<li>O arquivo <code>web_demo.bin</code> não foi gravado no endereço correto (<code>0x08100000</code>).</li>



<li>O servidor HTTP não foi inicializado.</li>



<li>A rede não atribuiu um IP válido à placa (falha do DHCP).</li>
</ul>
</li>
</ul>
</li>



<li><strong>Mensagens de erro no terminal</strong>
<ul class="wp-block-list">
<li>Algumas falhas podem ser identificadas nas mensagens exibidas pela porta serial, como erro ao abrir a flash ou falha na inicialização do servidor.</li>
</ul>
</li>
</ol>



<h3 class="wp-block-heading">A importância dos testes iniciais</h3>



<p class="wp-block-paragraph">Esses sinais de sucesso ou falha servem como guia rápido para depuração. Se algo não estiver funcionando, a primeira verificação deve ser:</p>



<ul class="wp-block-list">
<li>O <strong>firmware</strong> foi carregado corretamente?</li>



<li>O <strong>arquivo web_demo.bin</strong> foi gravado no endereço exato?</li>



<li>A placa obteve um <strong>endereço IP válido</strong> da rede?</li>



<li>O <strong>LED verde</strong> indicou o estado esperado?</li>
</ul>



<p class="wp-block-paragraph">Com essas checagens simples, mesmo um usuário iniciante consegue identificar o que precisa ser corrigido.</p>



<h1 class="wp-block-heading">Ajustes e Dicas de Uso do ThreadX</h1>



<p class="wp-block-paragraph">O <strong>ThreadX</strong> é o sistema operacional de tempo real (RTOS) utilizado no projeto <strong>Nx_WebServer</strong>. Ele é responsável por organizar a execução das threads, gerenciar recursos de memória e garantir que as tarefas mais críticas recebam atenção no momento certo. Para que a aplicação funcione corretamente e seja expansível, é necessário conhecer alguns detalhes importantes sobre seu funcionamento.</p>



<h3 class="wp-block-heading">O Tempo Base do Sistema</h3>



<p class="wp-block-paragraph">O ThreadX utiliza o <strong>SysTick</strong> (um temporizador do processador ARM Cortex-M) como sua referência de tempo. Isso significa que:</p>



<ul class="wp-block-list">
<li>Por padrão, o ThreadX é configurado com <strong>100 ticks por segundo</strong>, ou seja, cada tick equivale a 10 ms.</li>



<li>Esse valor impacta diretamente chamadas de espera (<code>sleep</code>, <code>timeout</code>) dentro do sistema.</li>



<li>Caso o desenvolvedor deseje alterar essa taxa, é necessário modificar o arquivo <code>tx_user.h</code>, ajustando o valor <code>TX_TIMER_TICKS_PER_SECOND</code>.</li>
</ul>



<p class="wp-block-paragraph">É importante manter consistência: ao alterar esse parâmetro, deve-se também atualizar o arquivo de inicialização em assembly (<code>tx_initialize_low_level.s</code>), garantindo que o tempo do kernel e o tempo real estejam alinhados.</p>



<h3 class="wp-block-heading">Cuidados Durante a Inicialização</h3>



<p class="wp-block-paragraph">Durante o processo de inicialização do kernel, o ThreadX <strong>desabilita todas as interrupções</strong> para evitar comportamentos inesperados. Isso significa que chamadas a funções de hardware (como HAL ou BSP) <strong>não devem ser feitas</strong> diretamente dentro da função <code>tx_application_define()</code>.</p>



<p class="wp-block-paragraph">Essa função deve ser utilizada apenas para <strong>criar recursos do ThreadX</strong>, como:</p>



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



<li>Semáforos</li>



<li>Filas de mensagens</li>



<li>Memórias pool</li>
</ul>



<p class="wp-block-paragraph">Qualquer chamada ao hardware deve ser feita dentro das <strong>threads de aplicação</strong>, depois que o sistema já está em execução.</p>



<h3 class="wp-block-heading">Memória Dinâmica e Linker Script</h3>



<p class="wp-block-paragraph">Outro ponto importante é a <strong>memória utilizada pelo ThreadX</strong>. Quando se opta por usar alocação dinâmica, o RTOS precisa receber um ponteiro para a primeira região de memória livre em RAM. Para isso, o arquivo de linkagem deve ser ajustado:</p>



<ul class="wp-block-list">
<li><strong>No STM32CubeIDE</strong>: adicionar uma nova seção no linker script (<code>.ld</code>), como no exemplo:</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>._threadx_heap : 
{
  . = ALIGN(8); 
  __RAM_segment_used_end__ = .; 
  . = . + 64K; 
  . = ALIGN(8); 
} >RAM_D1 AT> RAM_D1</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: #ECEFF4">.</span><span style="color: #D8DEE9">_threadx_heap</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: #ECEFF4">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ALIGN</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">8</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">__RAM_segment_used_end__</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</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 style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> 64</span><span style="color: #D8DEE9">K</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 style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ALIGN</span><span style="color: #D8DEE9FF">(</span><span style="color: #B48EAD">8</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 style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9">RAM_D1</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AT</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">RAM_D1</span></span></code></pre></div>



<p class="wp-block-paragraph">  Nesse caso, foi reservado um heap de <strong>64 KB</strong> para o ThreadX.</p>



<ul class="wp-block-list">
<li>O local dessa seção deve ficar entre <code>.bss</code> e <code>._user_heap_stack</code>, para evitar conflitos de memória.</li>



<li>O arquivo <code>tx_initialize_low_level.s</code> também deve ser modificado para habilitar o uso de memória dinâmica, ativando a flag <code>USE_DYNAMIC_MEMORY_ALLOCATION</code>.</li>
</ul>



<p class="wp-block-paragraph">Essas alterações garantem que o RTOS tenha uma área de memória segura para alocação de objetos e buffers durante a execução da aplicação.</p>



<h3 class="wp-block-heading">Por que isso é importante?</h3>



<p class="wp-block-paragraph">Sem os ajustes corretos, a aplicação pode apresentar falhas sutis, como:</p>



<ul class="wp-block-list">
<li>Travamentos aleatórios</li>



<li>Falta de memória para criar threads adicionais</li>



<li>Erros no uso de timers ou timeouts</li>
</ul>



<p class="wp-block-paragraph">Ao entender como o ThreadX organiza o tempo e a memória, o desenvolvedor ganha maior controle sobre a aplicação e evita problemas difíceis de rastrear.</p>



<h1 class="wp-block-heading">Ambiente de Hardware e Software Necessário</h1>



<p class="wp-block-paragraph">Para executar o projeto <strong>Nx_WebServer</strong> com sucesso, é fundamental preparar tanto o <strong>hardware</strong> quanto o <strong>software</strong> de forma adequada. Essa preparação garante que a aplicação rode sem problemas e que o usuário consiga acompanhar os logs e testar o servidor HTTP de forma prática.</p>



<h3 class="wp-block-heading">Hardware Utilizado</h3>



<p class="wp-block-paragraph">O exemplo foi desenvolvido e validado especificamente para a placa:</p>



<ul class="wp-block-list">
<li><strong>STM32F429ZI-Nucleo</strong> (referência MB1137 B-01).</li>
</ul>



<p class="wp-block-paragraph">Características relevantes dessa placa:</p>



<ul class="wp-block-list">
<li>Microcontrolador <strong>STM32F429ZI</strong> com núcleo ARM Cortex-M4.</li>



<li>Conector Ethernet disponível para integração em rede local.</li>



<li>LEDs e botões de usuário, que podem ser usados para testes interativos (ex.: acender o LED verde via navegador).</li>



<li>Interface <strong>ST-LINK</strong> integrada, que permite gravação e depuração sem a necessidade de ferramentas adicionais.</li>
</ul>



<p class="wp-block-paragraph">Embora o exemplo seja voltado para essa placa, ele pode ser adaptado a outros microcontroladores STM32 compatíveis, desde que possuam recursos de rede e memória flash suficientes.</p>



<h3 class="wp-block-heading">Comunicação Serial</h3>



<p class="wp-block-paragraph">Durante a execução, a placa envia informações pela interface <strong>USART3</strong>, que serve como um terminal de depuração. Para visualizar essas informações, é necessário conectar a placa a um computador via USB e abrir um terminal serial (como PuTTY, Tera Term ou o terminal do STM32CubeIDE).</p>



<p class="wp-block-paragraph">A configuração correta da porta serial é:</p>



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



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



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



<li><strong>Paridade</strong>: Nenhuma (None)</li>



<li><strong>Controle de fluxo</strong>: Nenhum</li>
</ul>



<p class="wp-block-paragraph">Esses parâmetros garantem que as mensagens (como o endereço IP atribuído pelo DHCP) sejam exibidas de forma legível.</p>



<h3 class="wp-block-heading">Software Necessário</h3>



<ol class="wp-block-list">
<li><strong>STM32CubeIDE</strong> ou outra ferramenta de compilação suportada.
<ul class="wp-block-list">
<li>Responsável por compilar e carregar o firmware do projeto.</li>
</ul>
</li>



<li><strong>STM32CubeProgrammer</strong>
<ul class="wp-block-list">
<li>Usado para gravar o arquivo de conteúdo web (<code>web_demo.bin</code>) na memória flash.</li>



<li>Recomenda-se utilizar a versão <strong>CLI (linha de comando)</strong>, como explicado na seção anterior.</li>
</ul>
</li>



<li><strong>Navegador Web</strong> (Chrome, Firefox, Edge ou outro).
<ul class="wp-block-list">
<li>Necessário para acessar as páginas hospedadas pelo microcontrolador.</li>
</ul>
</li>



<li><strong>Cliente de terminal serial</strong>
<ul class="wp-block-list">
<li>Permite monitorar mensagens da aplicação em tempo real.</li>
</ul>
</li>
</ol>



<h3 class="wp-block-heading">Ambiente de Rede</h3>



<p class="wp-block-paragraph">A placa precisa estar conectada a uma rede local com acesso a um <strong>servidor DHCP</strong> (geralmente fornecido pelo roteador doméstico ou corporativo). Sem DHCP, será necessário configurar manualmente o endereço IP no código.</p>



<p class="wp-block-paragraph">Com esse ambiente devidamente configurado, o usuário terá todos os recursos para compilar, gravar e executar o projeto, podendo visualizar tanto o funcionamento interno pelo terminal quanto o acesso externo via navegador.</p>



<h1 class="wp-block-heading">Passo a Passo para Colocar a Aplicação em Funcionamento</h1>



<p class="wp-block-paragraph">Agora que já entendemos os conceitos fundamentais, os recursos do RTOS e a configuração de hardware e software, podemos partir para o <strong>guia prático</strong> de execução do projeto <strong>Nx_WebServer</strong>. A seguir está o passo a passo completo para que até um iniciante consiga reproduzir o funcionamento do servidor web embarcado.</p>



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



<h3 class="wp-block-heading">1. Preparar o Projeto</h3>



<p class="wp-block-paragraph">Abra sua IDE favorita (recomendado <strong>STM32CubeIDE</strong>) e carregue o projeto de exemplo do <strong>Nx_WebServer</strong>. Esse projeto já vem configurado para a placa <strong>STM32F429ZI-Nucleo</strong>, facilitando a compilação.</p>



<p class="wp-block-paragraph">Compile o código para gerar o binário do firmware principal.</p>



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



<h3 class="wp-block-heading">2. Gravar o Conteúdo Web na Flash</h3>



<p class="wp-block-paragraph">Além do firmware, é necessário gravar os arquivos web que serão servidos pelo microcontrolador. Esses arquivos estão reunidos em um binário chamado <code>web_demo.bin</code>.</p>



<p class="wp-block-paragraph">Use o <strong>STM32CubeProgrammer (CLI)</strong> e execute o seguinte comando 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>&lt;INSTALL_PATH>STM32CubeProgrammer\bin\STM32_Programmer_CLI.exe -c port=swd -w &lt;INSTALL_PATH>web_content\web_demo.bin 0x08100000 -v
</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">&lt;</span><span style="color: #8FBCBB">INSTALL_PATH</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">STM32CubeProgrammer\bin\STM32_Programmer_CLI.exe -c port=swd -w </span><span style="color: #81A1C1">&lt;</span><span style="color: #8FBCBB">INSTALL_PATH</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">web_content\web_demo.bin 0x08100000 -v</span></span>
<span class="line"></span></code></pre></div>



<ul class="wp-block-list">
<li>Esse comando grava o conteúdo na memória flash a partir do endereço <code>0x08100000</code>.</li>



<li>O parâmetro <code>-v</code> garante a verificação, confirmando que os dados foram gravados corretamente.</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Atenção:</strong> Esse passo é obrigatório. Sem os arquivos web na flash, o servidor não terá páginas para enviar ao navegador.</p>
</blockquote>



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



<h3 class="wp-block-heading">3. Carregar o Firmware</h3>



<p class="wp-block-paragraph">Com o conteúdo web gravado, volte para a IDE e carregue o <strong>firmware do projeto Nx_WebServer</strong> na placa STM32F429ZI. Esse firmware contém toda a lógica do RTOS, do NetX Duo e do servidor HTTP.</p>



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



<h3 class="wp-block-heading">4. Conectar à Rede</h3>



<p class="wp-block-paragraph">Ligue a placa à rede local usando o cabo Ethernet. Certifique-se de que o roteador ou switch forneça endereços IP via <strong>DHCP</strong>.</p>



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



<h3 class="wp-block-heading">5. Monitorar a Porta Serial</h3>



<p class="wp-block-paragraph">Abra um terminal serial no computador, configurado da seguinte forma:</p>



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



<li>8 bits de dados, 1 stop bit, sem paridade, sem controle de fluxo.</li>
</ul>



<p class="wp-block-paragraph">Ao inicializar, a placa exibirá mensagens no terminal, incluindo o <strong>endereço IP atribuído</strong> pelo DHCP.</p>



<p class="wp-block-paragraph">Exemplo:</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>Board IP address: 192.168.0.105
</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">Board</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">IP</span><span style="color: #D8DEE9FF"> address</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">192.168</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0.105</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">6. Acessar pelo Navegador</h3>



<p class="wp-block-paragraph">No computador conectado à mesma rede, abra o navegador e digite o endereço IP informado no terminal:</p>



<ul class="wp-block-list">
<li>Para a página inicial: <code>http://&lt;IP>/index.html</code></li>



<li>Para a página de controle (dashboard): <code>http://&lt;IP>/dashboard.html</code></li>
</ul>



<p class="wp-block-paragraph">Se tudo estiver correto, as páginas serão exibidas.</p>



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



<h3 class="wp-block-heading">7. Interagir com o Sistema</h3>



<p class="wp-block-paragraph">Na página <strong>dashboard</strong>, você poderá interagir diretamente com a placa:</p>



<ul class="wp-block-list">
<li>Alternar o estado do <strong>LED verde</strong>.</li>



<li>Visualizar informações sobre o <strong>ThreadX</strong> e o <strong>NetX Duo</strong> em tempo real.</li>
</ul>



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



<h3 class="wp-block-heading">8. Verificar Sinais de Erro</h3>



<p class="wp-block-paragraph">Caso algo dê errado:</p>



<ul class="wp-block-list">
<li>Se o <strong>LED verde</strong> não acender, significa que o servidor HTTP não foi inicializado.</li>



<li>Se o navegador não carregar a página, confira se o arquivo <code>web_demo.bin</code> foi gravado corretamente no endereço indicado.</li>



<li>Se o terminal não mostrar um IP válido, verifique a conexão de rede e o DHCP.</li>
</ul>



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



<p class="wp-block-paragraph">Com esse passo a passo, a placa STM32F429ZI passa a funcionar como um <strong>servidor web completo</strong>, servindo páginas HTML e permitindo interação via navegador, tudo de forma embarcada.</p>



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/microcontroladores/construindo-um-servidor-web-embarcado-com-stm32f429zi-e-azure-rtos-netx-duo/">Construindo um Servidor Web Embarcado com STM32F429ZI e Azure RTOS NetX Duo</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">844</post-id>	</item>
	</channel>
</rss>
