<?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/tags/stm32/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Sun, 15 Feb 2026 14:26:27 +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>Filtro notch discreto (notch IIR) e média sincronizada (sync averaging)</title>
		<link>https://mcu.tec.br/algoritimos/filstros/filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 24 Feb 2026 14:23:52 +0000</pubDate>
				<category><![CDATA[Filstros]]></category>
		<category><![CDATA[ADC DMA microcontrolador]]></category>
		<category><![CDATA[análise de sinais repetitivos]]></category>
		<category><![CDATA[Biquad]]></category>
		<category><![CDATA[biquad digital]]></category>
		<category><![CDATA[DSP em microcontroladores]]></category>
		<category><![CDATA[encoder sincronização]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[filtro digital]]></category>
		<category><![CDATA[filtro digital em C]]></category>
		<category><![CDATA[filtro notch IIR]]></category>
		<category><![CDATA[firmware tempo real]]></category>
		<category><![CDATA[média sincronizada]]></category>
		<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[processamento de sinais]]></category>
		<category><![CDATA[processamento digital de sinais embarcados]]></category>
		<category><![CDATA[remoção de 60Hz]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[SNR em sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[synchronous averaging]]></category>
		<category><![CDATA[tempo real]]></category>
		<category><![CDATA[zero crossing]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1356</guid>

					<description><![CDATA[<p>Fechando a ideia: o notch discreto e a média sincronizada resolvem problemas parecidos (melhorar a qualidade do sinal), mas por “mecanismos” bem diferentes, e isso muda totalmente quando cada um é a melhor escolha. O notch é a ferramenta certa quando você conhece uma frequência indesejada bem definida e relativamente estável e quer arrancá-la do sinal com o mínimo de impacto no restante do espectro. Em firmware, isso costuma ser “hum” de 50/60 Hz, tons de chaveamento, ou uma ressonância estreita que aparece como pico bem localizado. O ponto crítico é que o notch é tão bom quanto a precisão do seu (f_0) e a escolha de (Q): se a interferência varia de frequência, um notch muito estreito deixa passar; se você alarga demais, começa a “machucar” conteúdo útil perto de (f_0). Além disso, como é um IIR, você precisa cuidar de estabilidade numérica e do formato de implementação (a forma direta II transposta tende a ser mais robusta em ponto flutuante e também costuma ser a melhor porta de entrada para depois migrar para ponto fixo).</p>
<p>Já a média sincronizada não é “um filtro de frequência” no sentido clássico; ela é uma técnica de extração por coerência: tudo que está alinhado com o período de referência fica mais forte, e o que não está alinhado tende a desaparecer. Por isso ela é superior quando o sinal útil é repetitivo e você tem um marcador de fase confiável, como encoder em máquina rotativa, o próprio PWM em conversores/inversores, ou zero-cross da rede. O ganho prático é enorme porque ela aumenta SNR sem precisar “inventar” um modelo espectral do ruído, mas ela também tem uma fragilidade: se o sincronismo for ruim (jitter, período variável, marcador inconsistente) a média “borrará” a forma de onda e pode até criar artefatos que parecem sinal real. Em projetos de rede elétrica, por exemplo, se você fixa (N) como “amostras por ciclo” sem acompanhar a variação real da frequência, a média começa a perder fase ao longo dos ciclos; nesse caso, ou você mede o período e ajusta (N) dinamicamente, ou você reamostra o ciclo para um grid fixo antes de acumular.</p>
<p>Na prática, em pipeline embarcado, uma combinação muito comum é usar notch primeiro para remover uma interferência tonal forte e depois usar média sincronizada para revelar a forma repetitiva de interesse com ruído bem mais baixo. Isso funciona especialmente bem quando a interferência não é coerente com o período que você está usando para sincronizar; se for coerente, a média pode reforçar a interferência, e aí o notch vira praticamente obrigatório antes. Se o seu sistema estiver no limite de CPU, o notch custa um número fixo e pequeno de multiplicações por amostra, enquanto a média sincronizada pode custar pouco por amostra mas “cobra” um custo por período quando você atualiza a forma média; dá para manter determinismo atualizando médias de forma incremental, ou reduzindo taxa, ou usando buffers e processamento em tarefa de menor prioridade.</p>
<p>Se você me disser qual é o seu caso (por exemplo: remover 60 Hz do ADC de shunt, ou extrair assinatura de vibração sincronizada com encoder, ou limpar ripple de PWM), eu adapto os coeficientes, a estratégia de sincronismo e o código para um cenário mais “pé no chão” com ADC+DMA, saturação, e versão em ponto fixo (Q31) pronta para rodar liso em Cortex-M.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/filstros/filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging/">Filtro notch discreto (notch IIR) e média sincronizada (sync averaging)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Em sistemas embarcados, “tirar uma frequência específica do sinal” costuma aparecer em dois cenários muito práticos: remover uma interferência estreita e persistente (por exemplo, 50/60 Hz de rede, ou um tom de comutação) e aumentar SNR (relação sinal-ruído) quando o fenômeno de interesse é repetitivo e existe uma referência de fase (por exemplo, rotação com encoder, comutação PWM, ou zero-cross da rede). O filtro notch discreto resolve muito bem o primeiro caso porque ele cria uma atenuação profunda numa frequência central (f_0) com pouca alteração do resto do espectro. Já a média sincronizada resolve muito bem o segundo porque ela soma ciclos “alinhados” no tempo/fase, reforçando o componente coerente e cancelando ruído não correlacionado e componentes que não encaixam exatamente naquele período.</p>



<p class="wp-block-paragraph">Quando o firmware precisa ser previsível (tempo real), o desenho do filtro não é só “matemático”: você escolhe estruturas e limites para garantir custo computacional constante, estado pequeno e estabilidade numérica, principalmente se você for para ponto fixo ou tiver ADC+DMA alimentando o pipeline. (Essa preocupação de arquitetura e previsibilidade é típica de projetos de tempo real.)</p>



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



<h2 class="wp-block-heading">1) Notch discreto: o “biquad” que apaga uma frequência</h2>



<p class="wp-block-paragraph">Um notch digital clássico pode ser implementado como um biquad IIR (segunda ordem) com zeros exatamente na frequência que você quer cancelar e polos próximos, controlando a largura do “buraco” via fator de qualidade (Q). Quanto maior o (Q), mais estreito é o notch (ótimo para interferência tonal estável), mas maior a sensibilidade a variação de (f_0) e a quantização dos coeficientes. Em termos práticos: para hum de rede em 60 Hz, se o sinal tiver variação de frequência (rede oscilando, ou a interferência “escorregando”), um (Q) alto demais pode deixar “vazar” parte do ruído. Para tom de comutação de um inversor ou fonte chaveada, se o clock for estável, dá para usar (Q) alto e atacar de forma cirúrgica.</p>



<p class="wp-block-paragraph">O biquad notch mais comum pode ser escrito como:</p>



<p class="wp-block-paragraph">\[<br>H(z)=\frac{1 &#8211; 2\cos(\omega_0)z^{-1} + z^{-2}}{1 &#8211; 2r\cos(\omega_0)z^{-1} + r^2 z^{-2}}<br>\]



<p class="wp-block-paragraph">onde \(\omega_0=2\pi f_0/F_s\) e (r) controla a “proximidade” dos polos aos zeros (quanto mais perto de 1, mais estreito e mais profundo). Uma ligação prática entre (r) e (Q) é aproximar a largura de banda por \(BW \approx f_0/Q\) e usar \(r \approx e^{-\pi BW/F_s}\). Isso funciona muito bem para firmware porque você calcula coeficientes uma vez (ou quando \(f_0\) muda) e o processamento por amostra fica constante.</p>



<h3 class="wp-block-heading">Código em C: biquad notch (float) com inicialização por \(F_s, f_0, Q\)</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>#include &lt;math.h>
#include &lt;stdint.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

typedef struct {
    // Coeficientes normalizados (a0 = 1)
    float b0, b1, b2;
    float a1, a2;

    // Estados (forma direta II transposta)
    float z1, z2;
} NotchBiquad;

/**
 * @brief Inicializa um filtro notch IIR (biquad) em forma direta II transposta.
 * @param f     Ponteiro para a estrutura do filtro.
 * @param Fs    Frequência de amostragem (Hz).
 * @param f0    Frequência central do notch (Hz).
 * @param Q     Fator de qualidade (adimensional). Ex.: 10..50 típicos.
 *
 * Observação prática:
 *  - Q maior => notch mais estreito, mais sensível a variações de f0 e quantização.
 *  - Q menor => notch mais largo, remove mais “vizinhança” de frequências.
 */
static inline void notch_init(NotchBiquad *f, float Fs, float f0, float Q)
{
    const float w0 = 2.0f * (float)M_PI * (f0 / Fs);

    // Largura de banda aproximada (Hz)
    const float BW = f0 / Q;

    // Polo raio r (aprox.) -> define a largura do notch
    const float r = expf(-(float)M_PI * (BW / Fs));

    const float c = cosf(w0);

    // Numerador (zeros no círculo unitário em ±w0)
    const float b0 = 1.0f;
    const float b1 = -2.0f * c;
    const float b2 = 1.0f;

    // Denominador (polos em raio r)
    const float a0 = 1.0f;
    const float a1 = -2.0f * r * c;
    const float a2 = r * r;

    // Normaliza por a0 (a0=1 aqui, mas mantemos o padrão)
    f->b0 = b0 / a0;
    f->b1 = b1 / a0;
    f->b2 = b2 / a0;
    f->a1 = a1 / a0;
    f->a2 = a2 / a0;

    f->z1 = 0.0f;
    f->z2 = 0.0f;
}

/**
 * @brief Processa 1 amostra pelo biquad notch (DF-II Transposta).
 * @param f Estrutura do filtro.
 * @param x Amostra de entrada.
 * @return  Amostra filtrada.
 */
static inline float notch_process(NotchBiquad *f, float x)
{
    // DF-II transposta:
    // y = b0*x + z1
    // z1 = b1*x - a1*y + z2
    // z2 = b2*x - a2*y
    const float y = (f->b0 * x) + f->z1;
    const float z1 = (f->b1 * x) - (f->a1 * y) + f->z2;
    const float z2 = (f->b2 * x) - (f->a2 * y);

    f->z1 = z1;
    f->z2 = z2;
    return y;
}
</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: #81A1C1">&lt;</span><span style="color: #D8DEE9">math</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">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: #D8DEE9FF">#</span><span style="color: #D8DEE9">ifndef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">M_PI</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">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.14159265358979323846</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">endif</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Coeficientes normalizados (a0 = 1)</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">b0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b2</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">a1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a2</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Estados (forma direta II transposta)</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">z1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">z2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NotchBiquad</span><span style="color: #81A1C1">;</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"> Inicializa um filtro notch IIR (biquad) em forma direta II transposta.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">f</span><span style="color: #616E88">     Ponteiro para a estrutura do filtro.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">Fs</span><span style="color: #616E88">    Frequência de amostragem (Hz).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">f0</span><span style="color: #616E88">    Frequência central do notch (Hz).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">Q</span><span style="color: #616E88">     Fator de qualidade (adimensional). Ex.: 10..50 típicos.</span></span>
<span class="line"><span style="color: #616E88"> *</span></span>
<span class="line"><span style="color: #616E88"> * Observação prática:</span></span>
<span class="line"><span style="color: #616E88"> *  - Q maior =&gt; notch mais estreito, mais sensível a variações de f0 e quantização.</span></span>
<span class="line"><span style="color: #616E88"> *  - Q menor =&gt; notch mais largo, remove mais “vizinhança” de frequências.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">notch_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NotchBiquad</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Fs</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Q</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">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> w0 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 2</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Fs</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">// Largura de banda aproximada (Hz)</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"> BW </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Q</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Polo raio r (aprox.) -&gt; define a largura do notch</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"> r </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">expf</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">BW</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Fs</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">float</span><span style="color: #D8DEE9FF"> c </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">cosf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">w0</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">// Numerador (zeros no círculo unitário em ±w0)</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"> b0 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 1</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 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"> b1 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">2</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</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"> b2 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 1</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">// Denominador (polos em raio r)</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"> a0 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 1</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 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"> a1 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">2</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</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"> a2 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">r</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Normaliza por a0 (a0=1 aqui, mas mantemos o padrão)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">b0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">b1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">b2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">a1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">a2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</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 style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</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 style="color: #ECEFF4">}</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"> Processa 1 amostra pelo biquad notch (DF-II Transposta).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">f</span><span style="color: #616E88"> Estrutura do filtro.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">x</span><span style="color: #616E88"> Amostra de entrada.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">return</span><span style="color: #616E88">  Amostra filtrada.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">notch_process</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NotchBiquad</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</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">// DF-II transposta:</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// y = b0*x + z1</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// z1 = b1*x - a1*y + z2</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// z2 = b2*x - a2*y</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"> y </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">b0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z1</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"> z1 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">b1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">a1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z2</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"> z2 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">b2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">a2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</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">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">z1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">z2</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">y</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"><strong>Melhores usos do notch:</strong> quando você conhece (ou mede) a frequência indesejada e ela é estreita, relativamente estável e você quer preservar quase tudo ao redor. Em instrumentação, isso aparece em leitura de shunt/ADC contaminada por rede; em áudio, hum; em controle, ressonância mecânica estreita (desde que não destrua margem de fase indevidamente); em eletrônica de potência, uma componente tonal em corrente/tensão.</p>



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



<h2 class="wp-block-heading">2) Média sincronizada: “soma coerente” alinhada à fase</h2>



<p class="wp-block-paragraph">A média sincronizada (às vezes chamada de synchronous averaging, time synchronous averaging) não é “só uma média móvel”. A sacada é que você escolhe uma janela exatamente igual a um período do fenômeno repetitivo (ou múltiplos inteiros) e reinicia/alinha essa janela usando um evento de referência: um zero-cross, um pulso de encoder, um índice, ou um marcador derivado do PWM. Se você tem (N) amostras por período e faz uma média sobre (K) períodos alinhados, o componente que se repete com a mesma fase soma e cresce proporcionalmente, enquanto ruído aleatório cai como (\sqrt{K}) no RMS. Além disso, componentes que não “encaixam” naquele período tendem a se cancelar.</p>



<p class="wp-block-paragraph">Em termos de filtro, isso se comporta como um filtro tipo comb (pente) extremamente eficiente para rejeitar tudo que não é coerente com o período escolhido. A diferença para um notch é que você não está mirando uma única frequência: você está favorecendo toda a forma de onda repetitiva no domínio do tempo, desde que sincronizada.</p>



<h3 class="wp-block-heading">Código em C: média sincronizada por períodos (com referência externa)</h3>



<p class="wp-block-paragraph">A seguir vai uma implementação simples (e bem útil) para firmware: você acumula amostras de cada posição dentro do período e, a cada período completo, você atualiza a média. Isso é perfeito quando você tem um “gatilho de início de período” (por exemplo, interrupção de índice do encoder ou zero-cross).</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 &lt;stdint.h>
#include &lt;string.h>

typedef struct {
    uint16_t N;          // amostras por período
    uint16_t idx;        // posição atual no período &#91;0..N-1&#93;
    uint32_t K;          // quantos períodos já acumulados (limite/controle externo)

    // Buffers de acumulação (use int64 se seu range for grande)
    int64_t *acc;        // soma por posição
    int32_t *avg;        // média por posição (resultado)
} SyncAvg;

/**
 * @brief Inicializa a média sincronizada.
 * @param s       Estrutura.
 * @param acc     Buffer de acumulação de tamanho N (int64_t).
 * @param avg     Buffer de saída média de tamanho N (int32_t).
 * @param N       Amostras por período.
 */
static inline void syncavg_init(SyncAvg *s, int64_t *acc, int32_t *avg, uint16_t N)
{
    s->N = N;
    s->idx = 0;
    s->K = 0;
    s->acc = acc;
    s->avg = avg;

    memset(s->acc, 0, (size_t)N * sizeof(int64_t));
    memset(s->avg, 0, (size_t)N * sizeof(int32_t));
}

/**
 * @brief Deve ser chamado quando ocorre o "marcador" de início de período (ex.: zero-cross ou índice do encoder).
 *        Isso força alinhamento de fase.
 */
static inline void syncavg_period_reset(SyncAvg *s)
{
    s->idx = 0;
}

/**
 * @brief Alimenta a média sincronizada com uma amostra do ADC já alinhada ao relógio de amostragem.
 * @param s Estrutura.
 * @param x Amostra (ex.: ADC já convertido para int32).
 *
 * Funcionamento:
 *  - A cada amostra, acumula na posição idx.
 *  - Ao completar N amostras, fecha um período e atualiza avg[].
 *  - A referência de fase vem de syncavg_period_reset() (externa).
 */
static inline void syncavg_push_sample(SyncAvg *s, int32_t x)
{
    s->acc&#91;s->idx&#93; += (int64_t)x;
    s->idx++;

    if (s->idx >= s->N) {
        s->idx = 0;
        s->K++;

        // Atualiza a média inteira por posição (custo O(N) por período).
        // Se N for grande e seu MCU for apertado, dá para atualizar de forma incremental.
        for (uint16_t i = 0; i &lt; s->N; i++) {
            s->avg&#91;i&#93; = (int32_t)(s->acc&#91;i&#93; / (int64_t)s->K);
        }
    }
}
</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: #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 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">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </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">N</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">          </span><span style="color: #616E88">// amostras por período</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">idx</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// posição atual no período &#91;0..N-1&#93;</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">K</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">          </span><span style="color: #616E88">// quantos períodos já acumulados (limite/controle externo)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Buffers de acumulação (use int64 se seu range for grande)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">acc</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// soma por posição</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">avg</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// média por posição (resultado)</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #81A1C1">;</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"> Inicializa a média sincronizada.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">s</span><span style="color: #616E88">       Estrutura.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">acc</span><span style="color: #616E88">     Buffer de acumulação de tamanho N (int64_t).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">avg</span><span style="color: #616E88">     Buffer de saída média de tamanho N (int32_t).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">N</span><span style="color: #616E88">       Amostras por período.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">syncavg_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">acc</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">avg</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">N</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">N</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">N</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">K</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">avg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">avg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">size_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">N</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">int64_t</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">avg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">size_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">N</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">int32_t</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>
<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"> Deve ser chamado quando ocorre o &quot;marcador&quot; de início de período (ex.: zero-cross ou índice do encoder).</span></span>
<span class="line"><span style="color: #616E88"> *        Isso força alinhamento de fase.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">syncavg_period_reset</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">s</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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>
<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"> Alimenta a média sincronizada com uma amostra do ADC já alinhada ao relógio de amostragem.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">s</span><span style="color: #616E88"> Estrutura.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">x</span><span style="color: #616E88"> Amostra (ex.: ADC já convertido para int32).</span></span>
<span class="line"><span style="color: #616E88"> *</span></span>
<span class="line"><span style="color: #616E88"> * Funcionamento:</span></span>
<span class="line"><span style="color: #616E88"> *  - A cada amostra, acumula na posição idx.</span></span>
<span class="line"><span style="color: #616E88"> *  - Ao completar N amostras, fecha um período e atualiza avg[].</span></span>
<span class="line"><span style="color: #616E88"> *  - A referência de fase vem de syncavg_period_reset() (externa).</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">syncavg_push_sample</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">x</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">N</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">K</span><span style="color: #81A1C1">++;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Atualiza a média inteira por posição (custo O(N) por período).</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Se N for grande e seu MCU for apertado, dá para atualizar de forma incremental.</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</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: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">N</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">avg</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">K</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"><strong>Melhores usos da média sincronizada:</strong> quando existe um evento/clock de referência que define o período do fenômeno e você quer extrair o comportamento repetitivo com máxima imunidade a ruído. Isso aparece em análise vibroacústica sincronizada com rotação (encoder), em medição de ripple sincronizada com PWM, em leitura de sinais biomédicos quando há marcador, e em sistemas de potência quando você quer “ver” a forma média ao longo de ciclos de rede sem ser enganado por ruído ou eventos transientes fora de fase.</p>



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



<h2 class="wp-block-heading">3) Exemplo prático combinando os dois: remover hum e depois reforçar a forma repetitiva</h2>



<p class="wp-block-paragraph">Em pipeline real, é comum usar notch primeiro para derrubar uma interferência tonal forte e, em seguida, média sincronizada para aumentar SNR do que restou (principalmente se o sinal útil é repetitivo e você tem referência). A ordem pode inverter dependendo do caso: se a interferência também for coerente com o mesmo período, a média pode reforçá-la, então o notch antes costuma ser mais seguro.</p>



<p class="wp-block-paragraph">Abaixo, um esqueleto de uso. Imagine ADC a 4 kHz, hum em 60 Hz, e você quer fazer média sincronizada por ciclo de 60 Hz usando zero-cross (logo \(N \approx 4000/60 \approx 66\) amostras por ciclo; na prática você ajusta para manter N inteiro e usar PLL/medição de período se a rede variar).</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 &lt;stdio.h>

// Reaproveita NotchBiquad e SyncAvg já definidos acima.

#define FS_HZ        4000.0f
#define NOTCH_F0_HZ  60.0f
#define NOTCH_Q      25.0f

#define N_SAMPLES_PER_PERIOD  66  // exemplo (depende do seu sincronismo real)

static int64_t acc_buf&#91;N_SAMPLES_PER_PERIOD&#93;;
static int32_t avg_buf&#91;N_SAMPLES_PER_PERIOD&#93;;

int main(void)
{
    NotchBiquad notch;
    notch_init(&amp;notch, FS_HZ, NOTCH_F0_HZ, NOTCH_Q);

    SyncAvg s;
    syncavg_init(&amp;s, acc_buf, avg_buf, N_SAMPLES_PER_PERIOD);

    // Exemplo: loop de aquisição (mock)
    for (int n = 0; n &lt; 20000; n++) {
        // Em firmware real: x_raw vem do ADC (DMA buffer), e zero-cross chama syncavg_period_reset(&amp;s)
        int32_t x_raw = (int32_t)(1000 * sinf(2.0f * (float)M_PI * 10.0f * (n / FS_HZ))); // sinal útil 10 Hz
        x_raw += (int32_t)(300 * sinf(2.0f * (float)M_PI * 60.0f * (n / FS_HZ)));        // hum 60 Hz

        // Notch (float) -> converte de volta para int32
        float y_notch = notch_process(&amp;notch, (float)x_raw);
        int32_t y = (int32_t)y_notch;

        // Evento externo de sincronismo: aqui é só demonstração (a cada N amostras)
        if ((n % N_SAMPLES_PER_PERIOD) == 0) {
            syncavg_period_reset(&amp;s);
        }

        // Média sincronizada
        syncavg_push_sample(&amp;s, y);

        // Quando s.K aumenta, avg_buf contém a forma média por período
        if (s.K > 0 &amp;&amp; (n % (N_SAMPLES_PER_PERIOD * 20)) == 0) {
            printf("K=%lu, avg&#91;0&#93;=%ld, avg&#91;10&#93;=%ld\n",
                   (unsigned long)s.K, (long)avg_buf&#91;0&#93;, (long)avg_buf&#91;10&#93;);
        }
    }

    return 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: #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: #616E88">// Reaproveita NotchBiquad e SyncAvg já definidos acima.</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">FS_HZ</span><span style="color: #D8DEE9FF">        4000</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</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">NOTCH_F0_HZ</span><span style="color: #D8DEE9FF">  60</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</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">NOTCH_Q</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>
<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">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">  </span><span style="color: #B48EAD">66</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// exemplo (depende do seu sincronismo real)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">avg_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</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: #D8DEE9">NotchBiquad</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">notch</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">notch_init</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">FS_HZ</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOTCH_F0_HZ</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOTCH_Q</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">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">syncavg_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">avg_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</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">// Exemplo: loop de aquisição (mock)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</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: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">20000</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Em firmware real: x_raw vem do ADC (DMA buffer), e zero-cross chama syncavg_period_reset(&amp;s)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x_raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</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: #88C0D0">sinf</span><span style="color: #D8DEE9FF">(2</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> 10</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FS_HZ</span><span style="color: #D8DEE9FF">)))</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// sinal útil 10 Hz</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">x_raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #B48EAD">300</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sinf</span><span style="color: #D8DEE9FF">(2</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> 60</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FS_HZ</span><span style="color: #D8DEE9FF">)))</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// hum 60 Hz</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Notch (float) -&gt; converte de volta para int32</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">y_notch</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">notch_process</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">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">x_raw</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">y_notch</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Evento externo de sincronismo: aqui é só demonstração (a cada N amostras)</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">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">%</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</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 style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">syncavg_period_reset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">s</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">// Média sincronizada</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">syncavg_push_sample</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</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">// Quando s.K aumenta, avg_buf contém a forma média por período</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">s</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">K</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: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">%</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">20</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 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">K=%lu, avg&#91;0&#93;=%ld, avg&#91;10&#93;=%ld</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                   (</span><span style="color: #D8DEE9">unsigned</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">long</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">K</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">long</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">avg_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">long</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">avg_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">&#93;)</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: #D8DEE9FF">    </span><span style="color: #81A1C1">return</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">Fechando a ideia: o notch discreto e a média sincronizada resolvem problemas parecidos (melhorar a qualidade do sinal), mas por “mecanismos” bem diferentes, e isso muda totalmente quando cada um é a melhor escolha. O notch é a ferramenta certa quando você conhece uma frequência indesejada bem definida e relativamente estável e quer arrancá-la do sinal com o mínimo de impacto no restante do espectro. Em firmware, isso costuma ser “hum” de 50/60 Hz, tons de chaveamento, ou uma ressonância estreita que aparece como pico bem localizado. O ponto crítico é que o notch é tão bom quanto a precisão do seu (f_0) e a escolha de (Q): se a interferência varia de frequência, um notch muito estreito deixa passar; se você alarga demais, começa a “machucar” conteúdo útil perto de (f_0). Além disso, como é um IIR, você precisa cuidar de estabilidade numérica e do formato de implementação (a forma direta II transposta tende a ser mais robusta em ponto flutuante e também costuma ser a melhor porta de entrada para depois migrar para ponto fixo).</p>



<p class="wp-block-paragraph">Já a média sincronizada não é “um filtro de frequência” no sentido clássico; ela é uma técnica de extração por coerência: tudo que está alinhado com o período de referência fica mais forte, e o que não está alinhado tende a desaparecer. Por isso ela é superior quando o sinal útil é repetitivo e você tem um marcador de fase confiável, como encoder em máquina rotativa, o próprio PWM em conversores/inversores, ou zero-cross da rede. O ganho prático é enorme porque ela aumenta SNR sem precisar “inventar” um modelo espectral do ruído, mas ela também tem uma fragilidade: se o sincronismo for ruim (jitter, período variável, marcador inconsistente) a média “borrará” a forma de onda e pode até criar artefatos que parecem sinal real. Em projetos de rede elétrica, por exemplo, se você fixa (N) como “amostras por ciclo” sem acompanhar a variação real da frequência, a média começa a perder fase ao longo dos ciclos; nesse caso, ou você mede o período e ajusta (N) dinamicamente, ou você reamostra o ciclo para um grid fixo antes de acumular.</p>



<p class="wp-block-paragraph">Na prática, em pipeline embarcado, uma combinação muito comum é usar notch primeiro para remover uma interferência tonal forte e depois usar média sincronizada para revelar a forma repetitiva de interesse com ruído bem mais baixo. Isso funciona especialmente bem quando a interferência não é coerente com o período que você está usando para sincronizar; se for coerente, a média pode reforçar a interferência, e aí o notch vira praticamente obrigatório antes. Se o seu sistema estiver no limite de CPU, o notch custa um número fixo e pequeno de multiplicações por amostra, enquanto a média sincronizada pode custar pouco por amostra mas “cobra” um custo por período quando você atualiza a forma média; dá para manter determinismo atualizando médias de forma incremental, ou reduzindo taxa, ou usando buffers e processamento em tarefa de menor prioridade.</p><p>The post <a href="https://mcu.tec.br/algoritimos/filstros/filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging/">Filtro notch discreto (notch IIR) e média sincronizada (sync averaging)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1356</post-id>	</item>
		<item>
		<title>Comparativo Técnico de Microcontroladores: ESP32, STM32, Arduino, RP2040 e nRF52</title>
		<link>https://mcu.tec.br/microcontroladores/comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 10:59:31 +0000</pubDate>
				<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[Arduino AVR]]></category>
		<category><![CDATA[baixo consumo]]></category>
		<category><![CDATA[bluetooth low energy]]></category>
		<category><![CDATA[controle industrial]]></category>
		<category><![CDATA[engenharia eletrônica]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[firmware embarcado]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[nRF52]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[wi-fi embarcado]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1291</guid>

					<description><![CDATA[<p>Este artigo apresenta uma análise comparativa e didática entre os principais microcontroladores do mercado — ESP32, STM32, Arduino (AVR), RP2040 e nRF52. O texto explora arquitetura, desempenho, consumo energético, conectividade e contexto de uso de cada família, ajudando engenheiros, estudantes e desenvolvedores a escolherem a plataforma mais adequada para projetos de IoT, sistemas industriais, dispositivos embarcados de baixo consumo e aplicações educacionais. O conteúdo é técnico, claro e orientado à tomada de decisão consciente em engenharia de sistemas embarcado</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52/">Comparativo Técnico de Microcontroladores: ESP32, STM32, Arduino, RP2040 e nRF52</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-poauy wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-poauy "><div class="eb-toc-container eb-toc-poauy  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;ESP32 \u2013 Conectividade Integrada e Foco em IoT&quot;,&quot;text&quot;:&quot;ESP32 \u2013 Conectividade Integrada e Foco em IoT&quot;,&quot;link&quot;:&quot;esp32-conectividade-integrada-e-foco-em-iot&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;STM32 \u2013 Desempenho, Escalabilidade e Foco Industrial&quot;,&quot;text&quot;:&quot;STM32 \u2013 Desempenho, Escalabilidade e Foco Industrial&quot;,&quot;link&quot;:&quot;stm32-desempenho-escalabilidade-e-foco-industrial&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Arduino (AVR) \u2013 Simplicidade, Acesso e Limita\u00e7\u00f5es Arquiteturais&quot;,&quot;text&quot;:&quot;Arduino (AVR) \u2013 Simplicidade, Acesso e Limita\u00e7\u00f5es Arquiteturais&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;RP2040 \u2013 Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo&quot;,&quot;text&quot;:&quot;RP2040 \u2013 Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo&quot;,&quot;link&quot;:&quot;rp2040-arquitetura-moderna-pio-e-flexibilidade-a-baixo-custo&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;nRF52 \u2013 Ultra Baixo Consumo e Comunica\u00e7\u00e3o Bluetooth Low Energy&quot;,&quot;text&quot;:&quot;nRF52 \u2013 Ultra Baixo Consumo e Comunica\u00e7\u00e3o Bluetooth Low Energy&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Tabela Comparativa T\u00e9cnica entre as Plataformas&quot;,&quot;text&quot;:&quot;Tabela Comparativa T\u00e9cnica entre as Plataformas&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Leitura cr\u00edtica da tabela&quot;,&quot;text&quot;:&quot;Leitura cr\u00edtica da tabela&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;ESP32 \u2013 Conectividade Integrada e Foco em IoT&quot;,&quot;value&quot;:&quot;esp32-conectividade-integrada-e-foco-em-iot&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;STM32 \u2013 Desempenho, Escalabilidade e Foco Industrial&quot;,&quot;value&quot;:&quot;stm32-desempenho-escalabilidade-e-foco-industrial&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Arduino (AVR) \u2013 Simplicidade, Acesso e Limita\u00e7\u00f5es Arquiteturais&quot;,&quot;value&quot;:&quot;arduino-avr-simplicidade-acesso-e-limita\u00e7\u00f5es-arquiteturais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;RP2040 \u2013 Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo&quot;,&quot;value&quot;:&quot;rp2040-arquitetura-moderna-pio-e-flexibilidade-a-baixo-custo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;nRF52 \u2013 Ultra Baixo Consumo e Comunica\u00e7\u00e3o Bluetooth Low Energy&quot;,&quot;value&quot;:&quot;nrf52-ultra-baixo-consumo-e-comunica\u00e7\u00e3o-bluetooth-low-energy&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Tabela Comparativa T\u00e9cnica entre as Plataformas&quot;,&quot;value&quot;:&quot;tabela-comparativa-t\u00e9cnica-entre-as-plataformas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Leitura cr\u00edtica da tabela&quot;,&quot;value&quot;:&quot;leitura-cr\u00edtica-da-tabela&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">Introdução</a><li><a href="#esp32-conectividade-integrada-e-foco-em-iot">ESP32 – Conectividade Integrada e Foco em IoT</a><li><a href="#stm32-desempenho-escalabilidade-e-foco-industrial">STM32 – Desempenho, Escalabilidade e Foco Industrial</a><li><a href="#eb-table-content-3">Arduino (AVR) – Simplicidade, Acesso e Limitações Arquiteturais</a><li><a href="#rp2040-arquitetura-moderna-pio-e-flexibilidade-a-baixo-custo">RP2040 – Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo</a><li><a href="#eb-table-content-5">nRF52 – Ultra Baixo Consumo e Comunicação Bluetooth Low Energy</a><li><a href="#eb-table-content-6">Tabela Comparativa Técnica entre as Plataformas</a><ul class="eb-toc__list"><li><a href="#eb-table-content-7">Leitura crítica da tabela</a></li></ul></ul></div></div></div></div></div>


<h2 class="wp-block-heading">Introdução</h2>



<p class="wp-block-paragraph">A escolha de um microcontrolador é uma das decisões mais críticas no desenvolvimento de sistemas embarcados, pois impacta diretamente o custo, o consumo de energia, a complexidade do firmware, a conectividade disponível e até mesmo a viabilidade do produto final. Nos últimos anos, o mercado passou a oferecer famílias extremamente distintas, que atendem desde projetos educacionais e protótipos rápidos até aplicações industriais, IoT em larga escala e dispositivos vestíveis de ultra-baixo consumo.</p>



<p class="wp-block-paragraph">Neste artigo comparativo, analisamos cinco plataformas amplamente utilizadas — <strong>ESP32</strong>, <strong>STM32</strong>, <strong>Arduino (AVR)</strong>, <strong>RP2040</strong> e <strong>nRF52</strong> — destacando suas arquiteturas, capacidades de processamento, conectividade, consumo energético e contextos de uso. O objetivo não é eleger um “melhor” microcontrolador, mas fornecer critérios técnicos claros para que o engenheiro ou desenvolvedor escolha a solução mais adequada ao seu projeto.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/microcontroladores/comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52/">Comparativo Técnico de Microcontroladores: ESP32, STM32, Arduino, RP2040 e nRF52</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1291</post-id>	</item>
		<item>
		<title>Os Melhores Sites sobre Microcontroladores, Sistemas Embarcados e IoT em 2026</title>
		<link>https://mcu.tec.br/geral/os-melhores-sites-sobre-microcontroladores-sistemas-embarcados-e-iot-em-2026/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=os-melhores-sites-sobre-microcontroladores-sistemas-embarcados-e-iot-em-2026</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Sun, 08 Feb 2026 00:07:52 +0000</pubDate>
				<category><![CDATA[geral]]></category>
		<category><![CDATA[ARM Cortex]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[datasheets]]></category>
		<category><![CDATA[desenvolvimento embarcado]]></category>
		<category><![CDATA[documentação técnica]]></category>
		<category><![CDATA[eletrônica embarcada]]></category>
		<category><![CDATA[engenharia eletrônica]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[firmware]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[kits de desenvolvimento]]></category>
		<category><![CDATA[MCU]]></category>
		<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[PIC]]></category>
		<category><![CDATA[portais de eletrônica]]></category>
		<category><![CDATA[RISC-V]]></category>
		<category><![CDATA[rtos]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1275</guid>

					<description><![CDATA[<p>Este artigo apresenta uma curadoria criteriosa e atualizada dos melhores sites sobre microcontroladores, sistemas embarcados e IoT, reunindo portais educacionais, fabricantes, distribuidores e plataformas técnicas amplamente reconhecidas no Brasil e no exterior. O conteúdo foi organizado para atender estudantes, makers, engenheiros de firmware e profissionais da indústria, oferecendo acesso direto a artigos técnicos, documentação oficial, cursos, kits de desenvolvimento e pesquisa de componentes. Entre os destaques estão portais especializados como Embarcados, MCU.TEC, Instituto Newton C. Braga, além de fabricantes como Microchip, STMicroelectronics, Renesas e Texas Instruments. O artigo também inclui lojas brasileiras de referência e plataformas globais como Octopart, Digi-Key e Mouser, facilitando desde o aprendizado até o desenvolvimento profissional e industrial de soluções embarcadas. Trata-se de um guia essencial para quem busca fontes confiáveis, técnicas e atualizadas no ecossistema de microcontroladores e eletrônica aplicada.</p>
<p>The post <a href="https://mcu.tec.br/geral/os-melhores-sites-sobre-microcontroladores-sistemas-embarcados-e-iot-em-2026/">Os Melhores Sites sobre Microcontroladores, Sistemas Embarcados e IoT em 2026</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4d8.png" alt="📘" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Conteúdo Educacional e Técnico (Portais e Comunidades)</h2>



<ul class="wp-block-list">
<li><strong>Embarcados</strong><br><a href="https://www.embarcados.com.br/">https://www.embarcados.com.br</a><br>Principal portal brasileiro sobre sistemas embarcados, microcontroladores, RTOS, Linux embarcado e indústria. Excelente equilíbrio entre teoria, prática e mercado.</li>



<li><strong>MCU.TEC</strong><br><a href="https://mcu.tec.br/">https://mcu.tec.br</a><br>Conteúdo técnico aprofundado sobre microcontroladores, FPGA, RTOS, protocolos, eletrônica aplicada e integração com IA. Forte foco em didática e engenharia real.</li>



<li><strong>Microgenios</strong><br><a href="https://www.microgenios.com.br/">https://www.microgenios.com.br</a><br>Cursos, treinamentos e artigos focados em PIC, Arduino, ESP32 e IoT, com abordagem prática para iniciantes e intermediários.</li>



<li><strong>Instituto Newton C. Braga</strong><br><a href="https://www.newtoncbraga.com.br/">https://www.newtoncbraga.com.br</a><br>Acervo clássico e extremamente vasto de eletrônica, incluindo microcontroladores, sensores, fontes e RF. Um verdadeiro repositório histórico-técnico.</li>



<li><strong>Vichinsky</strong><br><a href="https://www.vichinsky.com/">https://www.vichinsky.com</a><br>Conteúdo técnico voltado a PIC (especialmente PIC18F2550), 8051 e Arduino, com exemplos diretos e foco em firmware bare-metal.</li>



<li><strong>All About Circuits</strong><br><a href="https://www.allaboutcircuits.com/">https://www.allaboutcircuits.com</a><br>Um dos melhores sites internacionais para eletrônica e microcontroladores, com artigos técnicos, fóruns e análises profundas.</li>
</ul>



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



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3ed.png" alt="🏭" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fabricantes e Documentação Oficial</h2>



<ul class="wp-block-list">
<li><strong>Microchip Technology</strong><br><a href="https://www.microchip.com/">https://www.microchip.com</a><br>Documentação oficial de PIC, AVR (Atmel), SAM e ferramentas como MPLAB X. Fonte primária obrigatória para quem trabalha com PIC e AVR.</li>



<li><strong>STMicroelectronics</strong><br><a href="https://www.st.com/">https://www.st.com</a><br>Referência absoluta para STM32, HAL, LL, CubeMX e ecossistema ARM Cortex-M e Cortex-A.</li>



<li><strong>NXP Semiconductors</strong><br><a href="https://www.nxp.com/">https://www.nxp.com</a><br>Forte em microcontroladores industriais, automotivos, i.MX, LPC e segurança embarcada.</li>



<li><strong>Renesas Electronics</strong><br><a href="https://www.renesas.com/">https://www.renesas.com</a><br>Destaque para famílias RA, RX e RZ, muito usadas em aplicações industriais e IoT avançado.</li>



<li><strong>Texas Instruments</strong><br><a href="https://www.ti.com/">https://www.ti.com</a><br>MSP430, Sitara, documentação exemplar e application notes de alto nível.</li>
</ul>



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



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6d2.png" alt="🛒" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Lojas e Kits de Desenvolvimento (Brasil)</h2>



<ul class="wp-block-list">
<li><strong>AutoCore Robótica</strong><br><a href="https://www.autocorerobotica.com.br/">https://www.autocorerobotica.com.br</a><br>Venda de microcontroladores, módulos ESP, sensores e kits educacionais.</li>



<li><strong>Baú da Eletrônica</strong><br><a href="https://www.baudaeletronica.com.br/">https://www.baudaeletronica.com.br</a><br>Grande variedade de CIs, microcontroladores, ferramentas e componentes.</li>



<li><strong>ACEPIC Tecnologia</strong><br><a href="https://www.acepic.com.br/">https://www.acepic.com.br</a><br>Especializada em kits, treinamentos e soluções educacionais para PIC, ESP32 e sistemas embarcados.</li>
</ul>



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



<h2 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50d.png" alt="🔍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Plataformas de Pesquisa e Datasheets</h2>



<ul class="wp-block-list">
<li><strong>Octopart</strong><br><a href="https://octopart.com/">https://octopart.com</a><br>Essencial para pesquisa de microcontroladores, comparação de preços, estoque global e acesso rápido a datasheets oficiais.</li>



<li><strong>Digi-Key</strong><br><a href="https://www.digikey.com/">https://www.digikey.com</a><br>Além da loja, possui uma biblioteca técnica riquíssima (TechForum, artigos, vídeos).</li>



<li><strong>Mouser Electronics</strong><br><a href="https://www.mouser.com/">https://www.mouser.com</a><br>Excelente para lançamentos recentes, application notes e kits de desenvolvimento.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/geral/os-melhores-sites-sobre-microcontroladores-sistemas-embarcados-e-iot-em-2026/">Os Melhores Sites sobre Microcontroladores, Sistemas Embarcados e IoT em 2026</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1275</post-id>	</item>
		<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>Por que sensores industriais usam 0–10 V e 4–20 mA? Fundamentos, fórmulas e aplicações práticas</title>
		<link>https://mcu.tec.br/infraestrutura/por-que-sensores-industriais-usam-0-10-v-e-4-20-ma-fundamentos-formulas-e-aplicacoes-praticas/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=por-que-sensores-industriais-usam-0-10-v-e-4-20-ma-fundamentos-formulas-e-aplicacoes-praticas</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Sat, 13 Dec 2025 19:05:21 +0000</pubDate>
				<category><![CDATA[Infraestrutura]]></category>
		<category><![CDATA[0-10V]]></category>
		<category><![CDATA[4-20mA]]></category>
		<category><![CDATA[ADC]]></category>
		<category><![CDATA[automação industrial]]></category>
		<category><![CDATA[entrada analógica]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[instrumentação industrial]]></category>
		<category><![CDATA[loop de corrente]]></category>
		<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[ruído eletromagnético]]></category>
		<category><![CDATA[sensores industriais]]></category>
		<category><![CDATA[sinais analógicos]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[zero vivo]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1003</guid>

					<description><![CDATA[<p>Entenda por que sensores industriais utilizam os padrões 0–10 V e 4–20 mA. Este artigo explica os fundamentos elétricos, a matemática do escalonamento, imunidade a ruído, zero vivo, integração com microcontroladores e critérios técnicos de escolha. Um guia didático e minucioso para engenheiros, estudantes e profissionais de automação industrial que desejam projetar sistemas embarcados mais confiáveis e robustos.</p>
<p>The post <a href="https://mcu.tec.br/infraestrutura/por-que-sensores-industriais-usam-0-10-v-e-4-20-ma-fundamentos-formulas-e-aplicacoes-praticas/">Por que sensores industriais usam 0–10 V e 4–20 mA? Fundamentos, fórmulas e aplicações práticas</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Visão geral: por que a indústria padronizou 0–10 V e 4–20 mA</h2>



<p class="wp-block-paragraph">Em automação industrial, o “problema real” não é só medir uma grandeza (pressão, nível, vazão, temperatura), e sim <strong>transportar essa informação com confiabilidade</strong> por cabos longos, passando perto de motores, inversores de frequência, contatores e ambientes com aterramento imperfeito. Por isso, o setor convergiu para <strong>dois padrões analógicos</strong> simples, baratos e robustos: <strong>tensão (tipicamente 0–10 V)</strong> e <strong>corrente (tipicamente 4–20 mA)</strong>. Ambos representam a mesma ideia: um sensor transforma uma variável física em um sinal elétrico proporcional; a diferença está em <em>como</em> esse sinal “sobrevive” ao mundo industrial.</p>



<p class="wp-block-paragraph">O padrão <strong>0–10 V</strong> é muito comum quando as distâncias são moderadas, o cabeamento é bem controlado e o custo/complexidade precisa ser mínimo. Ele é intuitivo: a variável medida vira uma tensão proporcional na entrada analógica do CLP/DAQ. A relação básica de escalonamento (linear) é:</p>



<p class="wp-block-paragraph">\[<br>y = y_{\min} + \frac{(V &#8211; V_{\min})}{(V_{\max}-V_{\min})},(y_{\max}-y_{\min})<br>\]



<p class="wp-block-paragraph">Para 0–10 V, fica:</p>



<p class="wp-block-paragraph">\[<br>y = y_{\min} + \frac{V}{10},(y_{\max}-y_{\min})<br>\]



<p class="wp-block-paragraph">Já o padrão <strong>4–20 mA</strong> nasceu para vencer o que “mata” sinais de tensão no campo: <strong>queda de tensão no cabo, variações de resistência de contato, ruído acoplado e diferenças de referência de terra</strong>. Em um loop de corrente, o receptor não “confia” tanto em uma tensão absoluta; ele mede a corrente, e a corrente é <strong>a mesma ao longo de todo o circuito em série</strong> (pela própria natureza do loop), desde que o transmissor tenha tensão de alimentação suficiente para manter a conformidade. O escalonamento típico é:</p>



<p class="wp-block-paragraph">\[<br>y = y_{\min} + \frac{(I-4,\text{mA})}{16,\text{mA}},(y_{\max}-y_{\min})<br>\]



<p class="wp-block-paragraph">O “4 mA” (e não 0 mA) é intencional: é o chamado <strong>zero vivo</strong>. Assim, <strong>0 mA pode significar falha</strong> (fio rompido, transmissor sem alimentação), enquanto 4 mA significa “medindo zero da grandeza, mas o circuito está vivo”. Esse detalhe sozinho reduz diagnósticos ambíguos e melhora manutenção.</p>



<p class="wp-block-paragraph">Na prática, a escolha vira um trade-off objetivo:</p>



<ul class="wp-block-list">
<li><strong>0–10 V</strong> tende a ser simples, barato, fácil de interfacear, porém mais sensível a ruído e a problemas de referência/aterramento em longas distâncias.</li>



<li><strong>4–20 mA</strong> tende a ser mais robusto para cabos longos e ambientes agressivos, e ainda oferece diagnóstico de falha via “zero vivo”, ao custo de exigir loop, alimentação e resistor de carga (burden) adequados.</li>
</ul>



<p class="wp-block-paragraph">Observação importante (para conectar com arquitetura de sistemas reais): a indústria adota esses padrões porque eles reduzem risco sistêmico e tornam o comportamento mais previsível em campo — uma lógica muito alinhada à mentalidade de projeto de sistemas embarcados/tempo real, onde decisões de arquitetura existem para otimizar confiabilidade sob restrições práticas.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="474" height="237" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-31.png" alt="" class="wp-image-1006" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-31.png 474w, https://mcu.tec.br/wp-content/uploads/2025/12/image-31-300x150.png 300w" sizes="(max-width: 474px) 100vw, 474px" /></figure>



<h2 class="wp-block-heading">Padrão 0–10 V em detalhe técnico (vantagens, limites e matemática do erro)</h2>



<p class="wp-block-paragraph">O padrão <strong>0–10 V</strong> representa a variável medida como uma <strong>tensão proporcional</strong> aplicada à entrada analógica do sistema de aquisição (CLP, módulo de I/O, microcontrolador). Do ponto de vista elétrico, isso significa que o sensor funciona como uma <strong>fonte de tensão</strong> (idealmente) e o equipamento de leitura como uma <strong>carga de alta impedância</strong>. Quanto maior a impedância de entrada, menor a corrente drenada do sensor e menor o erro introduzido.</p>



<h3 class="wp-block-heading">Modelo elétrico simplificado</h3>



<p class="wp-block-paragraph">Na prática, o sensor não é uma fonte ideal: ele pode ser modelado como uma fonte de tensão \(V_s\) em série com uma resistência interna \(R_s\). O cabo adiciona uma resistência \(R_c\) e a entrada do conversor A/D (ADC) possui uma impedância \(R_{in}\).</p>



<p class="wp-block-paragraph">\[<br>V_{med} = V_s \cdot \frac{R_{in}}{R_s + R_c + R_{in}}<br>\]



<p class="wp-block-paragraph">Se \(R_{in} \gg (R_s + R_c)\), o termo tende a 1 e o erro é desprezível. Em ambientes industriais, módulos analógicos costumam ter <strong>impedâncias de entrada entre 100 kΩ e 1 MΩ</strong>, justamente para minimizar esse efeito. Já cabos longos, com seções pequenas, aumentam \(R_c\) e tornam o sistema mais sensível a erro.</p>



<h3 class="wp-block-heading">Influência do ruído eletromagnético</h3>



<p class="wp-block-paragraph">Outro ponto crítico do 0–10 V é o <strong>acoplamento de ruído</strong>. Um campo eletromagnético variável (por exemplo, próximo a motores ou inversores de frequência) pode induzir uma tensão espúria no cabo. Como o sinal é uma tensão absoluta, qualquer interferência somada ao sinal aparece diretamente na medição:</p>



<p class="wp-block-paragraph">\[<br>V_{ADC} = V_{sinal} + V_{ruído}<br>\]



<p class="wp-block-paragraph">Mesmo alguns poucos milivolts podem ser relevantes. Em um sensor escalado de 0–10 V para 0–100 bar, por exemplo, <strong>10 mV equivalem a 0,1 bar</strong>. Em aplicações de precisão, isso não é desprezível.</p>



<p class="wp-block-paragraph">Por isso, boas práticas são praticamente obrigatórias:</p>



<ul class="wp-block-list">
<li>uso de <strong>cabos blindados</strong>;</li>



<li>referência de <strong>terra bem definida</strong> (sensor e receptor compartilham o mesmo GND);</li>



<li>filtragem analógica simples, como um <strong>filtro RC passa-baixa</strong> antes do ADC.</li>
</ul>



<p class="wp-block-paragraph">O corte de um filtro RC típico é dado por:</p>



<p class="wp-block-paragraph">\[<br>f_c = \frac{1}{2\pi RC}<br>\]



<p class="wp-block-paragraph">Esse filtro reduz ruído de alta frequência, mas introduz atraso de fase, algo que precisa ser considerado em sistemas de controle em malha fechada.</p>



<h3 class="wp-block-heading">Resolução e relação com o ADC</h3>



<p class="wp-block-paragraph">Quando o sinal 0–10 V entra em um ADC de \(N\) bits, a menor variação detectável (LSB – <em>Least Significant Bit</em>) é:</p>



<p class="wp-block-paragraph">\[<br>\Delta V = \frac{10\ \text{V}}{2^N}<br>\]



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



<ul class="wp-block-list">
<li>ADC de 10 bits: \(\Delta V \approx 9{,}77\ \text{mV}\)</li>



<li>ADC de 12 bits: \(\Delta V \approx 2{,}44\ \text{mV}\)</li>
</ul>



<p class="wp-block-paragraph">Esse valor define o limite teórico de resolução do sistema. Na prática, ruído, offset e erro de ganho costumam dominar antes mesmo do limite do ADC.</p>



<h3 class="wp-block-heading">Quando 0–10 V faz sentido</h3>



<p class="wp-block-paragraph">O padrão 0–10 V é muito usado quando:</p>



<ul class="wp-block-list">
<li>as <strong>distâncias são curtas</strong> (painel ou máquina compacta);</li>



<li>o ambiente eletromagnético é relativamente controlado;</li>



<li>há necessidade de <strong>baixo custo</strong> e simplicidade;</li>



<li>o sistema já possui entradas analógicas de alta impedância e boa referência de terra.</li>
</ul>



<p class="wp-block-paragraph">É exatamente nesses limites — ruído, referência de terra e distância — que o padrão 0–10 V começa a perder espaço para o <strong>4–20 mA</strong>, que trata esses problemas de forma estrutural, e não apenas mitigativa.</p>



<h2 class="wp-block-heading">Padrão 4–20 mA: robustez elétrica, “zero vivo” e imunidade a ruído</h2>



<p class="wp-block-paragraph">O padrão <strong>4–20 mA</strong> foi adotado em larga escala porque resolve, de forma estrutural, problemas que no 0–10 V exigem cuidados adicionais. Aqui, a variável física não é representada por uma tensão absoluta, mas por uma <strong>corrente proporcional</strong>, que circula em um <strong>loop em série</strong> envolvendo transmissor, cabo, carga (burden) e fonte de alimentação. A grande vantagem é simples e poderosa: <strong>a corrente é a mesma em todos os pontos do loop</strong>, independentemente da resistência do cabo, desde que o transmissor tenha tensão suficiente para manter o regime.</p>



<h3 class="wp-block-heading">Modelo elétrico do loop de corrente</h3>



<p class="wp-block-paragraph">Um loop típico pode ser modelado como:</p>



<ul class="wp-block-list">
<li>fonte de alimentação \(V_{loop}\),</li>



<li>transmissor de corrente (sensor),</li>



<li>resistência do cabo \(R_c\),</li>



<li>resistência de carga \(R_b\) (burden resistor, onde a corrente é convertida em tensão),</li>



<li>eventualmente dispositivos intermediários (isoladores, barreiras).</li>
</ul>



<p class="wp-block-paragraph">A tensão total necessária para o loop funcionar corretamente é:</p>



<p class="wp-block-paragraph">\[<br>V_{loop} \ge V_{tx} + I \cdot (R_c + R_b)<br>\]



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



<ul class="wp-block-list">
<li>\(V_{tx}\) é a tensão mínima de conformidade do transmissor,</li>



<li>\(I\) é a corrente do loop (entre 4 e 20 mA).</li>
</ul>



<p class="wp-block-paragraph">Se essa condição for satisfeita, <strong>a corrente permanece correta</strong>, mesmo com variações de resistência do cabo, oxidação de contatos ou distâncias longas.</p>



<h3 class="wp-block-heading">O conceito de “zero vivo” (4 mA)</h3>



<p class="wp-block-paragraph">Diferentemente de um sistema 0–20 mA, o uso de <strong>4 mA como zero</strong> não é arbitrário. Ele resolve dois problemas fundamentais:</p>



<ol class="wp-block-list">
<li><strong>Detecção de falhas</strong>
<ul class="wp-block-list">
<li>0 mA → fio rompido, transmissor sem alimentação ou falha grave.</li>



<li>4 mA → zero físico medido, sistema operando normalmente.</li>
</ul>
</li>



<li><strong>Alimentação do próprio sensor</strong><br>Em muitos casos, o transmissor é <strong>alimentado pelo próprio loop</strong> (<em>loop-powered</em>). Os 4 mA mínimos garantem energia suficiente para a eletrônica interna.</li>
</ol>



<p class="wp-block-paragraph">O escalonamento linear clássico é:</p>



<p class="wp-block-paragraph">\[<br>y = y_{\min} + \frac{(I &#8211; 4,\text{mA})}{16,\text{mA}} \cdot (y_{\max} &#8211; y_{\min})<br>\]



<p class="wp-block-paragraph">Por exemplo, em um sensor de pressão de 0–100 bar:</p>



<ul class="wp-block-list">
<li>4 mA → 0 bar</li>



<li>12 mA → 50 bar</li>



<li>20 mA → 100 bar</li>
</ul>



<h3 class="wp-block-heading">Conversão corrente → tensão (burden resistor)</h3>



<p class="wp-block-paragraph">Na maioria dos sistemas embarcados e CLPs, o ADC mede <strong>tensão</strong>, não corrente. Por isso, usa-se um resistor de carga \(R_b\) para converter corrente em tensão:</p>



<p class="wp-block-paragraph">\[<br>V = I \cdot R_b<br>\]



<p class="wp-block-paragraph">Valores típicos:</p>



<ul class="wp-block-list">
<li>\(R_b = 250,\Omega\) → 4–20 mA vira <strong>1–5 V</strong></li>



<li>\(R_b = 100,\Omega\) → 0,4–2 V</li>
</ul>



<p class="wp-block-paragraph">A escolha de \(R_b\) é crítica:</p>



<ul class="wp-block-list">
<li>valores altos aumentam a tensão disponível para o ADC,</li>



<li>valores altos também aumentam a tensão exigida do loop (impactando a conformidade).</li>
</ul>



<h3 class="wp-block-heading">Imunidade a ruído: por que funciona melhor</h3>



<p class="wp-block-paragraph">Ruídos eletromagnéticos tendem a se manifestar como <strong>tensões induzidas</strong> no cabo. Em um sistema de corrente:</p>



<ul class="wp-block-list">
<li>pequenas tensões parasitas <strong>não alteram significativamente a corrente</strong> do loop;</li>



<li>o transmissor “força” a corrente correta dentro de sua faixa de conformidade.</li>
</ul>



<p class="wp-block-paragraph">Matematicamente, um ruído de tensão \(V_n\) somado ao loop gera uma variação de corrente:</p>



<p class="wp-block-paragraph">\[<br>\Delta I = \frac{V_n}{R_{total}}<br>\]



<p class="wp-block-paragraph">Como \(R_{total}\) costuma ser relativamente alto (centenas de ohms), \(\Delta I\) é pequeno, tornando o sistema naturalmente mais imune.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="520" height="346" src="https://mcu.tec.br/wp-content/uploads/2025/12/image-30.png" alt="" class="wp-image-1004" srcset="https://mcu.tec.br/wp-content/uploads/2025/12/image-30.png 520w, https://mcu.tec.br/wp-content/uploads/2025/12/image-30-300x200.png 300w" sizes="(max-width: 520px) 100vw, 520px" /><figcaption class="wp-element-caption">Obtido em: https://www.newtoncbraga.com.br/projetos/7578-conversor-4-20-ma-para-0-5-v-art1082.html</figcaption></figure>
</div>


<h3 class="wp-block-heading">Quando 4–20 mA é a melhor escolha</h3>



<p class="wp-block-paragraph">O padrão 4–20 mA é preferido quando:</p>



<ul class="wp-block-list">
<li>há <strong>longas distâncias</strong> (dezenas ou centenas de metros);</li>



<li>o ambiente é <strong>eletricamente agressivo</strong>;</li>



<li>é necessário <strong>diagnóstico simples de falhas</strong>;</li>



<li>sensores precisam ser alimentados pelo próprio sinal;</li>



<li>confiabilidade é mais importante que simplicidade.</li>
</ul>



<p class="wp-block-paragraph">Essa robustez explica por que, mesmo com fieldbuses modernos e Ethernet industrial, <strong>4–20 mA continua extremamente atual</strong>.</p>



<h2 class="wp-block-heading">Comparação direta: 0–10 V vs 4–20 mA e impactos no projeto de hardware e firmware</h2>



<p class="wp-block-paragraph">Depois de entender cada padrão isoladamente, a decisão de engenharia passa a ser <strong>comparativa e contextual</strong>. Não existe “melhor padrão absoluto”; existe o <strong>mais adequado ao cenário físico, elétrico e ao nível de confiabilidade exigido</strong>. Aqui vale olhar não só o sensor, mas o <em>sistema completo</em>: cabeamento, entradas analógicas, ADC, referência, firmware e manutenção.</p>



<h3 class="wp-block-heading">Comparação elétrica fundamental</h3>



<p class="wp-block-paragraph">No <strong>0–10 V</strong>, o sistema depende fortemente de uma <strong>referência comum de terra</strong> entre sensor e receptor. Qualquer diferença de potencial entre GNDs aparece diretamente como erro de medição. Em ambientes industriais, isso é frequente devido a:</p>



<ul class="wp-block-list">
<li>correntes de retorno pelo terra,</li>



<li>malhas de aterramento,</li>



<li>equipamentos de potência próximos.</li>
</ul>



<p class="wp-block-paragraph">Já no <strong>4–20 mA</strong>, o loop é essencialmente <strong>diferencial em corrente</strong>. A referência de terra perde importância relativa, porque a variável medida é a corrente no circuito em série. Isso reduz drasticamente problemas de <em>ground loop</em>.</p>



<h3 class="wp-block-heading">Comparação matemática do erro</h3>



<p class="wp-block-paragraph"><strong>Erro por resistência de cabo</strong></p>



<ul class="wp-block-list">
<li>0–10 V:<br>\[<br>\varepsilon_V \approx I_{in} \cdot R_c<br>\]<br>Onde \(I_{in}\) é a corrente drenada pela entrada. Se a impedância de entrada não for suficientemente alta, o erro cresce com o comprimento do cabo.</li>



<li>4–20 mA:<br>\[<br>\varepsilon_I \approx 0 \quad (\text{desde que haja conformidade})<br>\]<br>A resistência do cabo só “consome” tensão, não altera a corrente medida.</li>
</ul>



<p class="wp-block-paragraph"><strong>Erro por ruído</strong></p>



<ul class="wp-block-list">
<li>0–10 V:<br>\[<br>V_{med} = V_{sinal} + V_{ruído}<br>\]</li>



<li>4–20 mA:<br>\[<br>\Delta I = \frac{V_{ruído}}{R_{loop}}<br>\]<br>Com \(R_{loop}\) elevado, a variação de corrente é pequena.</li>
</ul>



<h3 class="wp-block-heading">Impacto no projeto de hardware embarcado</h3>



<p class="wp-block-paragraph"><strong>Entradas analógicas (ADC)</strong></p>



<ul class="wp-block-list">
<li>0–10 V: geralmente exige <strong>divisor resistivo</strong> ou amplificador para adaptar ao range típico do ADC (0–3,3 V ou 0–5 V). Isso adiciona erro de ganho e offset.</li>



<li>4–20 mA: basta um <strong>resistor de precisão</strong> (ex.: 250 Ω, 0,1%) e, opcionalmente, um filtro RC simples. A conversão corrente→tensão é extremamente previsível.</li>
</ul>



<p class="wp-block-paragraph"><strong>Proteção elétrica</strong></p>



<ul class="wp-block-list">
<li>0–10 V: mais sensível a surtos e ESD, pois a entrada “vê” diretamente a tensão do campo.</li>



<li>4–20 mA: o loop naturalmente limita corrente; ainda assim, proteção contra sobretensão é aplicada, mas o sistema tende a ser mais tolerante.</li>
</ul>



<h3 class="wp-block-heading">Impacto no firmware</h3>



<p class="wp-block-paragraph">No firmware, ambos acabam convergindo para a mesma lógica: <strong>ler um ADC e aplicar um escalonamento linear</strong>. A diferença está na confiabilidade do dado bruto.</p>



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



<p class="wp-block-paragraph">\[<br>y = y_{\min} + \frac{(x &#8211; x_{\min})}{(x_{\max} &#8211; x_{\min})}(y_{\max} &#8211; y_{\min})<br>\]



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



<ul class="wp-block-list">
<li>em 0–10 V, (x) é a tensão medida,</li>



<li>em 4–20 mA, (x) é a corrente (ou a tensão no burden resistor).</li>
</ul>



<p class="wp-block-paragraph">No entanto, no <strong>4–20 mA</strong>, o firmware ganha uma vantagem adicional:</p>



<ul class="wp-block-list">
<li>leituras <strong>abaixo de 3,8 mA</strong> podem ser tratadas como <strong>falha de campo</strong>, e não apenas “valor baixo”.<br>Isso simplifica diagnóstico, alarmes e estratégias de <em>fail-safe</em>.</li>
</ul>



<h3 class="wp-block-heading">Critérios práticos de escolha</h3>



<p class="wp-block-paragraph"><strong>Escolha 0–10 V quando:</strong></p>



<ul class="wp-block-list">
<li>o sensor está próximo ao controlador;</li>



<li>o ambiente é pouco ruidoso;</li>



<li>custo e simplicidade são prioritários;</li>



<li>o sistema é mais “máquina local” do que “planta industrial”.</li>
</ul>



<p class="wp-block-paragraph"><strong>Escolha 4–20 mA quando:</strong></p>



<ul class="wp-block-list">
<li>há longas distâncias de cabo;</li>



<li>existe forte interferência eletromagnética;</li>



<li>confiabilidade e diagnóstico são críticos;</li>



<li>sensores precisam ser alimentados pelo próprio sinal;</li>



<li>o sistema faz parte de uma planta industrial maior.</li>
</ul>



<p class="wp-block-paragraph">Essa análise explica por que, mesmo em projetos modernos com microcontroladores avançados e Ethernet industrial, <strong>o front-end analógico 4–20 mA continua sendo padrão de ouro</strong> no chão de fábrica.</p>



<h2 class="wp-block-heading">Integração prática com microcontroladores (STM32, ESP32): cálculo, front-end analógico e firmware</h2>



<p class="wp-block-paragraph">Ao integrar sensores <strong>0–10 V</strong> ou <strong>4–20 mA</strong> a microcontroladores, o desafio deixa de ser conceitual e passa a ser <strong>engenharia de interface</strong>: adaptar níveis elétricos ao ADC, preservar precisão, filtrar ruído e transformar a leitura bruta em uma variável física confiável no firmware.</p>



<h3 class="wp-block-heading">Integração de sensores 0–10 V</h3>



<p class="wp-block-paragraph">A maioria dos microcontroladores (STM32, ESP32, RP2040) possui ADCs com faixa máxima de <strong>3,3 V</strong> (alguns STM32 permitem 5 V externamente, mas o ADC interno continua limitado). Portanto, é necessário <strong>rebaixar a tensão</strong>.</p>



<p class="wp-block-paragraph"><strong>Divisor resistivo</strong><br>A solução mais simples é um divisor:</p>



<p class="wp-block-paragraph">\[<br>V_{ADC} = V_{in} \cdot \frac{R_2}{R_1 + R_2}<br>\]



<p class="wp-block-paragraph">Para mapear 0–10 V em 0–3,3 V:</p>



<p class="wp-block-paragraph">\[<br>\frac{R_2}{R_1 + R_2} = 0{,}33<br>\]



<p class="wp-block-paragraph">Um exemplo prático:</p>



<ul class="wp-block-list">
<li>\(R_1 = 20,k\Omega\)</li>



<li>\(R_2 = 10,k\Omega\)</li>
</ul>



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



<ul class="wp-block-list">
<li>resistores de <strong>1% ou melhor</strong> (idealmente 0,1%);</li>



<li>impedância equivalente não muito alta, para não prejudicar o <em>sample-and-hold</em> do ADC;</li>



<li>uso de <strong>buffer com amplificador operacional</strong> se o cabo for longo ou a fonte tiver alta impedância.</li>
</ul>



<p class="wp-block-paragraph"><strong>Filtragem</strong><br>Um filtro RC simples antes do ADC ajuda muito:</p>



<p class="wp-block-paragraph">\[<br>f_c = \frac{1}{2\pi RC}<br>\]



<p class="wp-block-paragraph">Para sinais lentos (temperatura, nível), cortes entre <strong>5 Hz e 20 Hz</strong> são comuns.</p>



<h3 class="wp-block-heading">Integração de sensores 4–20 mA</h3>



<p class="wp-block-paragraph">Aqui o caminho é mais elegante e previsível.</p>



<p class="wp-block-paragraph"><strong>Resistor de carga (burden)</strong><br>Escolhendo \(R_b = 250,\Omega\):</p>



<p class="wp-block-paragraph">\[<br>V = I \cdot R_b<br>\]



<ul class="wp-block-list">
<li>4 mA → 1,0 V</li>



<li>20 mA → 5,0 V</li>
</ul>



<p class="wp-block-paragraph">Se o ADC for de 3,3 V, duas opções surgem:</p>



<ol class="wp-block-list">
<li>usar \(R_b = 165,\Omega\) → 0,66–3,3 V</li>



<li>manter 250 Ω e usar divisor/buffer.</li>
</ol>



<p class="wp-block-paragraph">A primeira opção costuma ser preferida pela simplicidade.</p>



<p class="wp-block-paragraph"><strong>Potência do resistor</strong><br>A potência dissipada é:</p>



<p class="wp-block-paragraph">\[<br>P = I^2 \cdot R<br>\]



<p class="wp-block-paragraph">No pior caso (20 mA, 250 Ω):</p>



<p class="wp-block-paragraph">\[<br>P = (0{,}02)^2 \cdot 250 = 0{,}1,W<br>\]



<p class="wp-block-paragraph">Logo, usa-se resistor de <strong>0,25 W ou maior</strong>, com baixa deriva térmica.</p>



<h3 class="wp-block-heading">Conversão no firmware</h3>



<p class="wp-block-paragraph">No firmware, a leitura do ADC ((N) bits) gera um valor digital (D):</p>



<p class="wp-block-paragraph">\[<br>V_{ADC} = \frac{D}{2^N &#8211; 1} \cdot V_{ref}<br>\]



<p class="wp-block-paragraph">Para 4–20 mA:</p>



<p class="wp-block-paragraph">\[<br>I = \frac{V_{ADC}}{R_b}<br>\]



<p class="wp-block-paragraph">E o escalonamento final:</p>



<p class="wp-block-paragraph">\[<br>y = y_{\min} + \frac{(I &#8211; 4,\text{mA})}{16,\text{mA}}(y_{\max} &#8211; y_{\min})<br>\]



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



<ul class="wp-block-list">
<li>rejeitar leituras abaixo de <strong>3,8 mA</strong> (falha);</li>



<li>filtrar por média móvel ou filtro IIR simples;</li>



<li>separar claramente <strong>aquisição</strong>, <strong>conversão</strong> e <strong>lógica de controle</strong>.</li>
</ul>



<h3 class="wp-block-heading">Layout e EMC</h3>



<p class="wp-block-paragraph">Independentemente do padrão:</p>



<ul class="wp-block-list">
<li>mantenha trilhas analógicas longe de PWM, clocks e barramentos rápidos;</li>



<li>use <strong>plano de terra contínuo</strong>;</li>



<li>aterramento da blindagem do cabo em <strong>um único ponto</strong>;</li>



<li>considere isolamento galvânico em ambientes severos.</li>
</ul>



<p class="wp-block-paragraph">Esses cuidados fazem mais diferença do que aumentar bits de ADC.</p>



<h2 class="wp-block-heading">Seção 6 — Conclusão técnica: por que 0–10 V e 4–20 mA continuam dominantes na indústria</h2>



<p class="wp-block-paragraph">Mesmo com a evolução de barramentos digitais industriais, Ethernet determinística e sensores inteligentes, os padrões <strong>0–10 V</strong> e <strong>4–20 mA</strong> permanecem amplamente utilizados porque resolvem, de forma simples e comprovada, um problema central da automação: <strong>transportar informação analógica com previsibilidade em ambientes hostis</strong>. Eles não dependem de pilhas de protocolo, não exigem sincronismo complexo e falham de maneira compreensível para técnicos e engenheiros de campo.</p>



<p class="wp-block-paragraph">O <strong>0–10 V</strong> sobrevive pela simplicidade. Ele é direto, fácil de depurar com um multímetro comum e suficiente para aplicações locais, máquinas compactas e painéis onde o controle de aterramento e ruído é viável. Em termos de engenharia, é um padrão que funciona bem quando o sistema é tratado como um todo — sensor, cabo, referência e ADC — e quando as limitações são conscientemente aceitas.</p>



<p class="wp-block-paragraph">Já o <strong>4–20 mA</strong> permanece como referência em confiabilidade porque sua robustez é estrutural, não circunstancial. A imunidade a ruído, a tolerância a longas distâncias, a independência de referência de terra e o conceito de <strong>zero vivo</strong> fazem dele um padrão naturalmente alinhado com requisitos de segurança, manutenção e diagnóstico. Em projetos industriais reais, isso se traduz em menos paradas, menos ambiguidades e decisões mais claras no firmware e na operação.</p>



<p class="wp-block-paragraph">Do ponto de vista de sistemas embarcados, esses padrões também ensinam uma lição importante: <strong>engenharia de sinal vem antes de sofisticação de processamento</strong>. Um ADC de alta resolução ou um algoritmo avançado não compensam um front-end mal escolhido. É por isso que, mesmo em arquiteturas modernas com STM32, ESP32 ou SoCs industriais, o caminho analógico clássico continua sendo a fundação.</p>



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



<ul class="wp-block-list">
<li>0–10 V é uma solução eficiente quando simplicidade e proximidade física são garantidas.</li>



<li>4–20 mA é a escolha natural quando confiabilidade, diagnóstico e ambiente industrial severo entram em jogo.</li>



<li>a escolha correta reduz complexidade no hardware, no firmware e na manutenção ao longo de toda a vida útil do sistema.</li>
</ul>



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



<h2 class="wp-block-heading">Materiais para SEO</h2>



<h3 class="wp-block-heading">Título do artigo</h3>



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



<h3 class="wp-block-heading">Frase chave foco</h3>



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



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/infraestrutura/por-que-sensores-industriais-usam-0-10-v-e-4-20-ma-fundamentos-formulas-e-aplicacoes-praticas/">Por que sensores industriais usam 0–10 V e 4–20 mA? Fundamentos, fórmulas e aplicações práticas</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1003</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 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 loading="lazy" 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>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>
		<item>
		<title>Aritmética de Ponteiros</title>
		<link>https://mcu.tec.br/geral/aritmetica-de-ponteiros/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=aritmetica-de-ponteiros</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Sat, 10 May 2025 13:53:45 +0000</pubDate>
				<category><![CDATA[geral]]></category>
		<category><![CDATA[aritmética de ponteiros]]></category>
		<category><![CDATA[endereçamento de memória]]></category>
		<category><![CDATA[macros dinâmicas]]></category>
		<category><![CDATA[mapear periféricos]]></category>
		<category><![CDATA[memoria de 32 bits.]]></category>
		<category><![CDATA[offsets]]></category>
		<category><![CDATA[ponteiros em C]]></category>
		<category><![CDATA[registradores STM32]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[uint32_t]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=494</guid>

					<description><![CDATA[<p>Entenda de forma didática o endereçamento de memória em STM32: aritmética de ponteiros, mapeamento de registradores de 32 bits e boas práticas com macros dinâmicas.</p>
<p>The post <a href="https://mcu.tec.br/geral/aritmetica-de-ponteiros/">Aritmética de Ponteiros</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Neste artigo, apresentaremos de forma didática como funciona o endereçamento de memória em microcontroladores STM32 que utilizam endereçamento de 4 em 4 bytes (32 bits). Iremos explorar o <strong>mapa de memória</strong>, mostrar como definimos ponteiros para acessar posições de periféricos e memória interna, e detalhar a <strong>aritmética de ponteiros</strong> que permite calcular endereços de registradores de forma clara e sistemática. Ao longo do texto, usaremos símbolos gregos nomeados para representar conceitos-chave, como α\alphaα para o endereço-base, β\betaβ para deslocamentos e γ\gammaγ para o endereço resultante.</p>



<p class="wp-block-paragraph">Em seguida, demonstraremos exemplos práticos de declaração de ponteiros em C para acessar registradores de GPIO, UART e outros dispositivos, explicando como cada offset é obtido a partir do endereço-base do bloco de periféricos. Apresentaremos as <strong>fórmulas fundamentais</strong> que auxiliam na compreensão do cálculo de endereços: \[\gamma = \alpha + N \times \beta\]



<p class="wp-block-paragraph">onde N é o índice do registrador e β=4\beta=4β=4 bytes. Também detalharemos como a aritmética de ponteiros em C já incorpora esse fator de 4, de modo que, ao incrementar um ponteiro de tipo <code>uint32_t*</code>, ele avança exatamente 4 bytes na memória.</p>



<p class="wp-block-paragraph">Por fim, abordaremos boas práticas de definição de ponteiros simbólicos, com uso de macros e <code>typedef</code>, para tornar o código mais legível e livre de “números mágicos”. Será uma visão completa, desde o fundamento teórico até exemplos práticos que você poderá copiar direto para seus projetos em STM32.</p>



<p class="wp-block-paragraph"><strong>Mapa de Memória do STM32</strong></p>



<p class="wp-block-paragraph">No universo STM32, todo o espaço de endereçamento de 32 bits é dividido em grandes “zonas” fixas, cada uma com um endereço-base definido em hexadecimal. Chamemos cada endereço-base de α\alphaα, β, δ etc., conforme o bloco:</p>



<ol class="wp-block-list">
<li><strong>Memória Flash</strong>
<ul class="wp-block-list">
<li>Endereço-base (α): <code>0x0800 0000</code></li>



<li>Tamanho típico: até alguns megabytes (dependendo da família)</li>



<li>Usada para armazenar o firmware.</li>
</ul>
</li>



<li><strong>SRAM</strong>
<ul class="wp-block-list">
<li>Endereço-base (β): <code>0x2000 0000</code></li>



<li>Geralmente entre 64 KB e 512 KB em STM32 modernos.</li>
</ul>
</li>



<li><strong>Periféricos (APB e AHB)</strong>
<ul class="wp-block-list">
<li>Endereço-base principal (γ): <code>0x4000 0000</code></li>



<li>Dentro desse bloco, há subdivisões para barramentos AHB1, AHB2, APB1, APB2, cada uma com seu próprio base offset. Por exemplo:
<ul class="wp-block-list">
<li>AHB1: <code>\(\gamma + 0x0002 0000 = 0x4002 0000</code>\)</li>



<li>APB2: \(<code>\gamma + 0x0001 0000 = 0x4001 0000</code>\)</li>
</ul>
</li>
</ul>
</li>



<li><strong>Memória de Depuração e Reservada</strong>
<ul class="wp-block-list">
<li>ST-LINK e ETM: <code>0xE004 2000</code> em diante</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">Cada bloco α,β,γ é apenas o ponto de partida. Para acessar um registrador N-ésimo dentro do bloco de periféricos, usamos a fórmula \[\delta = \gamma + N \times \beta_{\text{offset}}\]



<p class="wp-block-paragraph">onde βoffset=4\beta_{\text{offset}} = 4βoffset​=4 bytes (tamanho de um registrador de 32 bits).</p>



<p class="wp-block-paragraph">Por exemplo, para o registrador <strong>GPIOA_MODER</strong> (modo de pinos de GPIOA), cujo offset oficial é <code>0x00</code> a partir de <code>GPIOA_BASE = 0x4002 0000</code>: \[ \text{GPIOA\_MODER} = \gamma + 0x0002\,0000 + (0 \times 4) = 0x4002\,0000.\]



<p class="wp-block-paragraph">Já o registrador <strong>GPIOA_ODR</strong> (data output register), offset <code>0x14</code>, fica em \[\text{GPIOA\_ODR} = 0x4002\,0000 + (0x14) = 0x4002\,0014\].</p>



<p class="wp-block-paragraph">Em resumo, o mapa de memória STM32 é uma sequência de blocos alinhados em fronteiras de 1 MB ou mais, cada um com um endereço-base α,β,γ. Nos próximos exemplos práticos veremos como declarar ponteiros em C usando essas constantes e como a <strong>aritmética de ponteiros</strong> já “sabe” que cada incremento de <code>uint32_t*</code> pula 4 bytes automaticamente.</p>



<p class="wp-block-paragraph"><strong>Declaração de Ponteiros e Boas Práticas</strong></p>



<p class="wp-block-paragraph">No código C para STM32, cada bloco de registradores tem um <strong>endereço-base</strong> que chamaremos de α\alphaα. Para tornar tudo mais legível e evitar “números mágicos”, recomendamos definir macros e <code>typedef</code> que explicitem a intenção:</p>



<pre class="wp-block-preformatted"><code>// 1) Definição de tipos e macros úteis<br>typedef volatile uint32_t vuint32_t;          // acesso a registradores de 32 bits<br>#define GPIOA_BASE   ((uintptr_t)0x40020000)  // α = endereço-base do bloco GPIOA<br>#define GPIOA_MODER_OFFSET  (0x00u)           // β₁ = offset do registrador MODER<br>#define GPIOA_ODR_OFFSET    (0x14u)           // β₂ = offset do registrador ODR<br></code></pre>



<p class="wp-block-paragraph">A partir daí, para criar um ponteiro para cada registrador, usamos a <strong>conversão de ponteiro</strong> em C, que chamaremos de γ\gammaγ. Por exemplo:</p>



<pre class="wp-block-preformatted">/<code>/ 2) Declaração de ponteiros simbólicos<br>#define GPIOA_MODER  ((vuint32_t*)(GPIOA_BASE + GPIOA_MODER_OFFSET))  // γ₁<br>#define GPIOA_ODR    ((vuint32_t*)(GPIOA_BASE + GPIOA_ODR_OFFSET))    // γ₂<br></code></pre>



<ul class="wp-block-list">
<li>Ao escrever <code>GPIOA_MODER</code>, você tem já um ponteiro para o registrador de modo de pino.</li>



<li>A aritmética de ponteiros em C incorpora automaticamente o fator “4 bytes”: incrementar <code>GPIOA_MODER</code> em 1 avança exatamente 4 bytes na memória.</li>
</ul>



<p class="wp-block-paragraph">Esse padrão — usar um <code>typedef</code> para o tipo de registrador e macros para base (α) e offset (β) — é a forma mais clara de identificar cada endereço de dispositivo. Nos próximos exemplos, veremos como usar a <strong>aritmética de ponteiros</strong> para iterar sobre grupos de registradores semelhantes sem recalcular manualmente cada deslocamento.</p>



<p class="wp-block-paragraph"><strong>Aritmética de Ponteiros</strong></p>



<p class="wp-block-paragraph">Na aritmética de ponteiros em C, o incremento de um ponteiro já considera o tamanho do tipo apontado. No nosso caso, como usamos <code>vuint32_t*</code> (ponteiro para <code>uint32_t</code>), cada incremento avança <strong>4 bytes</strong>. Vamos nomear:</p>



<ul class="wp-block-list">
<li>Endereço-base do ponteiro: γ</li>



<li>Passo do incremento: \(\rho = sizeof(uint32\_t) = 4\)</li>



<li>Índice de deslocamento: N</li>
</ul>



<p class="wp-block-paragraph">Então, para obter o NNN-ésimo registrador a partir de γ, usamos a fórmula: \(\gamma_{(N)} \;=\; \gamma + N \times \rho\)</p>



<p class="wp-block-paragraph">Em código C, ao fazer:</p>



<pre class="wp-block-preformatted"><code>vuint32_t *p = GPIOA_MODER;  // p aponta para γ (GPIOA_MODER)<br></code></pre>



<ul class="wp-block-list">
<li><code>p + 0</code> → \(\gamma_{(0)} = \gammaγ\) → primeiro registrador (<code>MODER</code>)</li>



<li><code>p + 1</code> → \(\gamma_{(1)} = \gamma + 1\times4\) → segundo registrador (offset +0x04)</li>



<li>…</li>



<li><code>p + N</code> → \(\gamma_{(N)}\)​ → registrador em <code>GPIOA_BASE + (MODER_OFFSET + N*4)</code></li>
</ul>



<p class="wp-block-paragraph"><strong>Exemplo prático</strong><br>Suponha que dentro de cada porta GPIO existam 8 registradores consecutivos a partir de <code>GPIOA_MODER</code>:</p>



<pre class="wp-block-preformatted"><code>for (uint32_t i = 0; i &lt; 8; i++) {<br>    vuint32_t *reg = GPIOA_MODER + i;<br>    // Isso acessa: GPIOA_BASE + (GPIOA_MODER_OFFSET + i*4)<br>    uint32_t valor = *reg;      // lê o valor do registrador i<br>    *reg = valor | 0x01;        // só um exemplo de operação bit a bit<br>}<br></code></pre>



<p class="wp-block-paragraph">Aqui, cada iteração leva <code>reg</code> a um novo endereço: \[\gamma_{(i)} = \underbrace{GPIOA\_BASE + GPIOA\_MODER\_OFFSET}_{\gamma} + i \times \rho\]



<p class="wp-block-paragraph">e ρ já é 4 bytes, portanto não precisamos fazer multiplicação manual de <code>4*i</code> no cálculo de ponteiro — o compilador cuida disso.</p>



<p class="wp-block-paragraph"><strong>Fórmulas Fundamentais de Endereçamento</strong></p>



<p class="wp-block-paragraph">Nesta seção reunimos as expressões matemáticas essenciais para calcular e entender como obter qualquer endereço de registrador em um STM32 que endereça de 4 em 4 bytes (32 bits). Vamos nomear:</p>



<ul class="wp-block-list">
<li>α = endereço-base do bloco de periféricos (por exemplo, <code>GPIOA_BASE</code> = <code>0x40020000</code>)</li>



<li>β = tamanho de cada registrador em bytes = 4</li>



<li>N = índice (inteiro) do registrador desejado dentro do bloco</li>



<li>γ = endereço resultante do registrador</li>
</ul>



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



<ol class="wp-block-list">
<li><strong>Cálculo direto de offset</strong> \(\gamma \;=\; \alpha \;+\; \text{Offset}_{\text{Registro}\)​ Em que \(\text{Offset}_{\text{Registro}} \;=\; N \;\times\;\beta\) Logo, juntando: \( \gamma = \alpha + N\,\beta\).</li>



<li><strong>Forma geral em notação de ponteiro</strong><br>Se definirmos um ponteiro simbólico p=(vuint32_t∗) α p = (\mathtt{vuint32\_t}^*)\,\alphap=(vuint32_t∗)α então o N-ésimo registrador é simplesmente \(\quad\Longrightarrow\quad \gamma = \alpha + N \times \beta\), pois o compilador faz \((p+N)\times4\) bytes automaticamente.</li>



<li><strong>Cálculo reverso (índice a partir de um endereço)</strong><br>Às vezes precisamos descobrir N dado um endereço γ. Basta inverter: \(N \;=\; \frac{\gamma &#8211; \alpha}{\beta}\)​. Como γ e α são múltiplos de 4, N será inteiro.</li>



<li><strong>Exemplo completo</strong>
<ul class="wp-block-list">
<li>Suponha \(\alpha = 0x4002\,0000\) (GPIOA_BASE)</li>



<li>Queremos o registrador cujo offset oficial é <code>0x14</code> → \(N = 0x14/4 = 5\)</li>



<li>Aplicando a fórmula: \(\gamma = 0x4002\,0000 + 5\times4 = 0x4002\,0014\)</li>



<li>Para descobrir N se só tivermos \(\gamma = 0x4002\,0014\): \( N = \tfrac{0x4002\,0014 &#8211; 0x4002\,0000}{4} = \tfrac{0x14}{4} = 5.\)</li>
</ul>
</li>



<li><strong>Resumo das expressões</strong> \[\boxed{ \begin{aligned} \gamma &amp;= \alpha + N\,\beta,\\ N &amp;= \dfrac{\gamma &#8211; \alpha}{\beta},\\ \beta &amp;= \text{sizeof(uint32\_t)} = 4\;\text{bytes}. \end{aligned} }\]</li>
</ol>



<p class="wp-block-paragraph">Com essas fórmulas em mãos, você pode derivar qualquer endereço de registrador, definir ponteiros de forma simbólica e até calcular índices de forma reversa quando precisar depurar ou validar offsets.</p>



<p class="wp-block-paragraph"><strong>Exemplos Avançados de Aritmética de Ponteiros e Uso em Periféricos</strong></p>



<p class="wp-block-paragraph">Nesta seção, vamos ver cenários práticos em que a aritmética de ponteiros facilita o acesso a blocos sequenciais de registradores, como temporizadores (TIM), controladores DMA e unidades UART. Manteremos a notação grega para clareza:</p>



<ul class="wp-block-list">
<li>α: endereço-base do bloco de periféricos (por exemplo, <code>TIM2_BASE</code>)</li>



<li>β=4: tamanho de cada registrador em bytes</li>



<li>N: índice do registrador desejado</li>



<li>γ: endereço resultante</li>
</ul>



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



<ol class="wp-block-list">
<li><strong>Iteração sobre registradores de um temporizador (TIM2)</strong><br>A família STM32 define o bloco TIM2 em \(\alpha_{\text{TIM2}} = 0x4000\,0000 + 0x0000\,0000 = 0x4000\,0000\). Os registradores estão dispostos em sequência de 4 em 4 bytes, começando em <code>TIM2_CR1</code> (offset <code>0x00</code>), <code>TIM2_CR2</code> (<code>0x04</code>), <code>TIM2_SMCR</code> (<code>0x08</code>) etc. Supondo que haja 10 registradores consecutivos, podemos fazer: </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" data-code="#define TIM2_BASE ((uintptr_t)0x40000000) // α₁
vuint32_t *pTIM2 = (vuint32_t*)TIM2_BASE; // ponteiro para α₁ 
for (uint32_t i = 0; i &lt; 10; i++) { 
// γ = α₁ + i*β 
    vuint32_t *reg = pTIM2 + i; 
    uint32_t val = *reg; // lê registrador i 
    *reg = val &amp; 0xFFFF; // exemplo de operação 
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">#define TIM2_BASE ((uintptr_t)0x40000000) // α₁</span></span>
<span class="line"><span style="color: #88C0D0">vuint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">pTIM2</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> (vuint32_t*)TIM2_BASE</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ponteiro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">α₁</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</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: #88C0D0">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">i++</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">γ</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">α₁</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">i</span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">β</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">vuint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">reg</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pTIM2</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">i</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">val</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">reg</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">lê</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">registrador</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">i</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">*reg</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">val</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">0xFFFF</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exemplo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">operação</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Aqui, cada <code>pTIM2 + i</code> gera o endereço \[\gamma_i = \alpha_{\text{TIM2}} + i \times \beta\].</p>



<ol class="wp-block-list">
<li><strong>Acesso a canais DMA com stride (passo) múltiplo</strong><br>Em muitos microcontroladores STM32, os canais DMA possuem blocos de registradores com “stride” maior que 4 bytes (por exemplo, 0x14 bytes entre as estruturas de cada canal). Se quisermos acessar o canal kkk do DMA1, definimos:<ul><li class="">\(\alpha_{\text{DMA1}} = 0x4002\,6000\)\(\beta_{\text{canal}} = 0x14\) bytesN=k</li></ul>A fórmula geral vira \(\gamma = \alpha_{\text{DMA1}} + N \times \beta_{\text{canal}}\). Em C: </li>
</ol>



<p class="wp-block-paragraph"></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" data-code="#define DMA1_BASE ((uintptr_t)0x40026000) // α₂ 
#define DMA1_CH_OFFSET (0x14u) // β₂ = 20 bytes 
// ponteiro genérico ao canal k 
static inline vuint32_t* DMA1_Channel(uint32_t k) { 
  return (vuint32_t*)(DMA1_BASE + k * DMA1_CH_OFFSET); 
} 
// Exemplo: configurar o registrador CCR do canal 3 
vuint32_t *pCCR3 = DMA1_Channel(3) + (0x08u/4); 
// offset 0x08 dentro do bloco do canal (CCR), dividido por β=4 
*pCCR3 |= (1 &lt;&lt; 0); // habilita o canal" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">#define DMA1_BASE ((uintptr_t)0x40026000) // α₂ </span></span>
<span class="line"><span style="color: #616E88">#define DMA1_CH_OFFSET (0x14u) // β₂ = 20 bytes </span></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ponteiro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">genérico</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ao</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">canal</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">k</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #88C0D0">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">vuint32_t</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">DMA1_Channel</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">k</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</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"> (vuint32_t*)</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">DMA1_BASE</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">k</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">DMA1_CH_OFFSET</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>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Exemplo:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">configurar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">registrador</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">CCR</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">canal</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #88C0D0">vuint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">pCCR3</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">DMA1_Channel</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">3</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> (0x08u/4)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">offset</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x08</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dentro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bloco</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">canal</span><span style="color: #D8DEE9FF"> (CCR), dividido por β=4 </span></span>
<span class="line"><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">pCCR3 </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF">= (1 &lt;&lt; </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">habilita</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">canal</span></span></code></pre></div>



<ol class="wp-block-list">
<li><strong>Blocos de registradores em interfaces UART</strong><br>Em UARTs, o bloco UART1 (<code>\(\alpha_{\text{UART1}} = 0x4001\,1000</code>\)) é composto por registradores de status, data e controle. Suponha que queremos varrer o registrador de dados (offset <code>0x24</code>) e o de status (offset <code>0x1C</code>) de forma programática: </li>
</ol>



<p class="wp-block-paragraph"></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" data-code="#define UART1_BASE ((uintptr_t)0x40011000) // α₃ 
#define UART_SR_OFFSET (0x1Cu) // β₃₁ 
#define UART_DR_OFFSET (0x24u) // β₃₂ 
vuint32_t *pUART_SR = (vuint32_t*)(UART1_BASE + UART_SR_OFFSET); 
vuint32_t *pUART_DR = (vuint32_t*)(UART1_BASE + UART_DR_OFFSET); 
// Exemplo: ler e reescrever o dado se o status indicar transmissor pronto 
if ((*pUART_SR &amp; (1 &lt;&lt; 7)) != 0) { 
  uint32_t dado = *pUART_DR; 
  *pUART_DR = dado; // ecoa o dado 
}" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">#define UART1_BASE ((uintptr_t)0x40011000) // α₃ </span></span>
<span class="line"><span style="color: #616E88">#define UART_SR_OFFSET (0x1Cu) // β₃₁ </span></span>
<span class="line"><span style="color: #616E88">#define UART_DR_OFFSET (0x24u) // β₃₂ </span></span>
<span class="line"><span style="color: #88C0D0">vuint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">pUART_SR</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> (vuint32_t*)</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">UART1_BASE</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">UART_SR_OFFSET</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #88C0D0">vuint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">pUART_DR</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> (vuint32_t*)</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">UART1_BASE</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">UART_DR_OFFSET</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Exemplo:</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ler</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">reescrever</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">se</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">status</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">indicar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">transmissor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pronto</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">((</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">pUART_SR </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> (</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">7</span><span style="color: #ECEFF4">))</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 style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">pUART_DR</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">*pUART_DR</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dado</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ecoa</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dado</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span></code></pre></div>



<ol class="wp-block-list">
<li><strong>Cálculo reverso de índice para depuração</strong><br>Se você souber apenas o endereço γ e quiser descobrir N, aplique: \( N = \frac{\gamma &#8211; \alpha}{\beta}\). Por exemplo, se você encontra em log o endereço <code>0x40011024</code>, então \(N = \frac{0x40011024 &#8211; 0x40011000}{4} = \frac{0x24}{4} = 9.\). Assim, você sabe que esse é o <strong>9º</strong> registrador a partir de <code>UART1_BASE</code>.</li>
</ol>



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



<p class="wp-block-paragraph">Esses exemplos mostram a flexibilidade da aritmética de ponteiros no acesso a qualquer bloco de registradores, seja ele linear (stride = 4 bytes) ou composto (stride > 4 bytes). Com as fórmulas \(\gamma = \alpha + N\,\beta \quad\text{e}\quad N = \frac{\gamma &#8211; \alpha}{\beta}\),</p>



<p class="wp-block-paragraph">você consegue tanto gerar ponteiros de forma simbólica quanto inferir índices para validação e depuração de maneira sistemática.</p>



<p class="wp-block-paragraph"><strong>Boas Práticas de Organização de Código e Macros Dinâmicas</strong></p>



<p class="wp-block-paragraph">Para manter o código enxuto e evitar dispersão de “números mágicos”, adote sempre uma camada de abstração sobre os endereços-base e offsets. Use <code>typedef</code> e macros parametrizadas para criar <strong>macros dinâmicas</strong> que recebam como argumento o índice NNN ou o nome do periférico. Por exemplo, em vez de ter dezenas de definições fixas, poderíamos criar:</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" data-code="// Macro genérica para obter ponteiro a registrador
#define REG32(BASE, OFFSET)  ((vuint32_t*)((uintptr_t)(BASE) + (uintptr_t)(OFFSET)))
// Macro dinâmica para blocos com stride maior
#define REG32_STRIDE(BASE, STRIDE, IDX, SUBOFFSET) \
    ((vuint32_t*)((uintptr_t)(BASE) + ((uintptr_t)(STRIDE) * (IDX)) + (uintptr_t)(SUBOFFSET)))
    " style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Macro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">genérica</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">obter</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ponteiro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">registrador</span></span>
<span class="line"><span style="color: #616E88">#define REG32(BASE, OFFSET)  ((vuint32_t*)((uintptr_t)(BASE) + (uintptr_t)(OFFSET)))</span></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Macro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dinâmica</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">blocos</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">stride</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">maior</span></span>
<span class="line"><span style="color: #616E88">#define REG32_STRIDE(BASE, STRIDE, IDX, SUBOFFSET) \</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">((</span><span style="color: #D8DEE9FF">vuint</span><span style="color: #B48EAD">32</span><span style="color: #D8DEE9FF">_t</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF">)((uintptr_t)(BASE) </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> ((uintptr_t)(STRIDE) </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (IDX</span><span style="color: #ECEFF4">))</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">+</span><span style="color: #D8DEE9FF"> (uintptr_t)</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">SUBOFFSET</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF">))</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span></span></code></pre></div>



<p class="wp-block-paragraph">Aqui, λ\lambdaλ (lambda) poderia simbolizar a <strong>função de mapeamento</strong> que, dado um bloco e um índice, retorna o endereço correto. Em C, essa “função” é a macro <code>REG32_STRIDE</code>, que une o endereço-base α\alphaα, o stride σ\sigmaσ (que pode ser 4 ou outro valor), o índice NNN e um suboffset adicional. Isso reduz drasticamente a repetição de código e facilita futuras manutenções: se o stride ou a organização de blocos mudar, basta ajustar a macro, e todo o projeto se adapta automaticamente.</p>



<p class="wp-block-paragraph">Além disso, organize as macros e <code>typedef</code> em um único arquivo de cabeçalho, como <code>stm32_memmap.h</code>. Dentro dele, defina seções claras para cada tipo de periférico (Φ para GPIO, Ψ para TIM, Ω para UART, etc.), de modo que o programador simplesmente inclua o cabeçalho certo e tenha acesso a todas as definições necessárias, sem precisar decorar endereços. Essa convenção modulariza o projeto e deixa explícita a responsabilidade de cada bloco.</p>



<p class="wp-block-paragraph">Por fim, crie <strong>checks de compilação</strong> usando <code>static_assert</code> (C11) ou <code>#if</code>/<code>#error</code> para garantir que offsets e strides sejam múltiplos de 4 bytes. Dessa forma, caso alguém tente definir um offset incorreto, o compilador já gera um erro antes mesmo de subir o firmware. Isso dá robustez ao seu sistema embarcado e evita bugs sutis de alinhamento de memória.</p>



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



<p class="wp-block-paragraph"><strong>Conclusão</strong></p>



<p class="wp-block-paragraph">Neste artigo vimos como o endereçamento de memória em STM32 se baseia em blocos de 32 bits que avançam de 4 em 4 bytes. Aprendemos a usar as letras gregas α\alphaα, β\betaβ e γ para representar, respectivamente, o endereço-base, o tamanho do passo (stride) e o endereço calculado. Exploramos a <strong>aritmética de ponteiros</strong>, que já incorpora o fator de 4 bytes, e conferimos fórmulas diretas e inversas para gerar e interpretar endereços de registradores. Por fim, discutimos boas práticas de organização de código, com macros dinâmicas e validações em tempo de compilação, garantindo clareza e segurança nos acessos a periféricos.</p>



<p class="wp-block-paragraph">Com esse conjunto de conceitos e ferramentas — que vão de λ como função de mapeamento até verificações de alinhamento — você está apto a desenvolver drivers e módulos para STM32 com confiança, legibilidade e sem “números mágicos”. Agora é só aplicar esses padrões nos seus projetos e aproveitar a simplicidade e potência oferecidas pela aritmética de ponteiros em C.</p><p>The post <a href="https://mcu.tec.br/geral/aritmetica-de-ponteiros/">Aritmética de Ponteiros</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">494</post-id>	</item>
		<item>
		<title>Detecção de Humanos e Obstáculos com HMMD: Comparando Tecnologias FMCW e LiDAR</title>
		<link>https://mcu.tec.br/geral/deteccao-de-humanos-e-obstaculos-com-hmmd-comparando-tecnologias-fmcw-e-lidar/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=deteccao-de-humanos-e-obstaculos-com-hmmd-comparando-tecnologias-fmcw-e-lidar</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 11 Apr 2025 15:29:01 +0000</pubDate>
				<category><![CDATA[geral]]></category>
		<category><![CDATA[Sensores]]></category>
		<category><![CDATA[detecção de humanos com HMMD]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[inteligência embarcada]]></category>
		<category><![CDATA[LiDAR]]></category>
		<category><![CDATA[micro movimentação]]></category>
		<category><![CDATA[obstáculos estáticos]]></category>
		<category><![CDATA[ondas contínuas]]></category>
		<category><![CDATA[presença humana]]></category>
		<category><![CDATA[radar fmcw]]></category>
		<category><![CDATA[radar para IoT]]></category>
		<category><![CDATA[radar vs lidar]]></category>
		<category><![CDATA[respiração]]></category>
		<category><![CDATA[sensores 24GHz]]></category>
		<category><![CDATA[sistema embarcado]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[transformada de fourier]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=350</guid>

					<description><![CDATA[<div class="members-access-error">Faça o login e <strong>solicite acesso</strong> ao artigo conforme os grupos privados que faz parte.</div>
<p>The post <a href="https://mcu.tec.br/geral/deteccao-de-humanos-e-obstaculos-com-hmmd-comparando-tecnologias-fmcw-e-lidar/">Detecção de Humanos e Obstáculos com HMMD: Comparando Tecnologias FMCW e LiDAR</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="members-access-error">Faça o login e <strong>solicite acesso</strong> ao artigo conforme os grupos privados que faz parte.</div>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">350</post-id>	</item>
	</channel>
</rss>
