<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[STM32 UART 串口通信:printf 重定向与中断接收(示例帖)]]></title><description><![CDATA[<p dir="auto">串口是 STM32 调试的生命线:打印日志、看传感器数据、跟上位机联调都靠它。这篇把最常用的两招讲透:printf 重定向输出,中断方式接收。</p>
<h2>1. CubeMX 配置要点</h2>
<ul>
<li>Connectivity → USART1,Mode 选 Asynchronous</li>
<li>波特率 115200,8 数据位、无校验、1 停止位(8N1)</li>
<li>NVIC Settings 里勾选 USART1 global interrupt(中断接收才需要)</li>
<li>PA9(TX)、PA10(RX)接到 USB 转串口模块,注意 <strong>TX 接 RX、RX 接 TX,交叉接</strong></li>
</ul>
<h2>2. printf 重定向</h2>
<p dir="auto">C 库的 printf 最终调 fputc,重写它把字符送进串口:</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int fputc(int ch, FILE *f) {
    HAL_UART_Transmit(&amp;huart1, (uint8_t *)&amp;ch, 1, HAL_MAX_DELAY);
    return ch;
}

// main 里直接用
printf("system clock: %lu Hz\r\n", HAL_RCC_GetSysClockFreq());
</code></pre>
<p dir="auto">注意两点:</p>
<ul>
<li>printf 发 \n 不会自动回车,串口助手里看到满屏阶梯状就改成 \r\n</li>
<li>HAL_MAX_DELAY 是阻塞等待,放在中断里调 printf 会卡死,中断里只做标记</li>
</ul>
<h2>3. 中断接收(推荐做法)</h2>
<p dir="auto">轮询接收会堵住主循环,用中断 + 一字节缓冲:</p>
<pre><code class="language-c">uint8_t rx_byte;
uint8_t rx_buf[128];
uint8_t rx_len = 0;

void start_uart_rx(void) {
    HAL_UART_Receive_IT(&amp;huart1, &amp;rx_byte, 1); // 启动一次
}

// 每收到 1 字节进一次回调,记得重新挂起下一次接收
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart-&gt;Instance == USART1) {
        if (rx_byte == '\n' || rx_len &gt;= sizeof(rx_buf) - 1) {
            rx_buf[rx_len] = '\0';
            // 在这里处理一行命令,不要做耗时操作
            rx_len = 0;
        } else if (rx_byte != '\r') {
            rx_buf[rx_len++] = rx_byte;
        }
        HAL_UART_Receive_IT(&amp;huart1, &amp;rx_byte, 1); // 关键:重新挂起
    }
}
</code></pre>
<h2>4. 排障清单</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>现象</th>
<th>先查</th>
</tr>
</thead>
<tbody>
<tr>
<td>串口无输出</td>
<td>波特率两边是否一致;TX/RX 是否交叉接;GND 有没有共地</td>
</tr>
<tr>
<td>输出乱码</td>
<td>波特率/时钟配置,检查 HSE 是否起振</td>
</tr>
<tr>
<td>只能收一次</td>
<td>回调里有没有重新调 HAL_UART_Receive_IT</td>
</tr>
<tr>
<td>printf 卡死</td>
<td>是否在中断上下文里调用;串口外设时钟开了没</td>
</tr>
</tbody>
</table>
<p dir="auto">下一篇计划写定时器 PWM 驱动舵机/电机,连载目录见 /series。</p>
]]></description><link>https://www.potatochip.dev/topic/18/stm32-uart-串口通信-printf-重定向与中断接收-示例帖</link><generator>RSS for Node</generator><lastBuildDate>Fri, 09 Oct 2026 19:22:30 GMT</lastBuildDate><atom:link href="https://www.potatochip.dev/topic/18.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 01 Oct 2026 15:15:43 GMT</pubDate><ttl>60</ttl></channel></rss>