news 2026/4/16 2:21:35

Keil串口通信调试:新手必备的实战入门篇

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Keil串口通信调试:新手必备的实战入门篇

Keil串口调试实战:从零点亮“开发者之眼”

你有没有过这样的经历?代码烧进STM32,板子上电,LED不闪、屏幕无显,程序像掉进了黑洞——完全不知道它跑到了哪里。这时候,最朴素也最有效的救星是什么?串口打印一行Hello, World!

在嵌入式开发中,没有比串口更忠实的“眼睛”了。而对国内大多数初学者来说,Keil MDK就是他们第一次点亮这双眼睛的工具箱。本文不讲空泛理论,也不堆砌术语,而是带你一步步亲手实现一个能在PC上看到输出的完整串口调试系统——用Keil + STM32 + 串口助手,从工程创建到printf打印,全程实操,拒绝“已解决”。


为什么是串口?因为它够“笨”,但也够可靠

别看现在I2C、SPI、USB、以太网五花八门,但调试阶段,工程师第一反应永远是:“先打个串口看看。”

UART之所以成为调试标配,就因为它简单到极致

  • 只要两根线:TX(发)、RX(收);
  • 不需要共同时钟,靠双方约定好波特率就能通信;
  • 协议清晰:起始位 → 数据位 → 停止位,一帧数据清清楚楚;
  • 几乎所有MCU都自带至少一个UART外设;
  • PC端通过一块几块钱的USB转TTL模块(如CH340、CP2102)就能接入。

更重要的是,你可以用它输出任何你想知道的信息:变量值、函数进入标志、状态机跳转……它是你和单片机之间的“摩斯电码”。

🔧 典型应用场景:
- 系统启动自检信息输出
- 传感器原始数据实时回传
- 故障日志记录与分析
- 按键/中断触发事件追踪


Keil不是万能的,但它足够“接地气”

说到ARM开发,IAR、GCC、VS Code都各有拥趸,但在中国高校实验室和中小企业里,Keil依然是那个绕不开的名字

原因很简单:
- 安装简单,界面直观,适合新手快速上手;
- 中文资料铺天盖地,百度一搜就有答案;
- 和ST官方库(如STM32F1标准外设库)配合默契;
- 支持J-Link、ST-Link等主流下载器,调试体验流畅。

当然,它也有短板——免费版限制32KB代码大小,商业授权价格偏高。但对于学习阶段而言,这个“门槛低+生态熟”的组合,依然是绝佳起点。

而且,Keil有个隐藏神技叫semihosting,允许你在不用串口的情况下,直接把printf输出显示在IDE控制台。不过今天我们不玩虚的,我们要走硬核路线:让数据真正通过TX引脚发出去,经USB模块传到电脑屏幕


动手前准备:硬件与软件清单

别急着敲代码,先把环境搭起来:

✅ 硬件部分

名称示例型号备注
开发板STM32F103C8T6(蓝丸)最常见入门板
下载器ST-Link V2或使用板载DAP
USB-TTL模块CH340G / CP2102用于串口通信
杜邦线若干——连接PA2(TX) → RXD

📌 接线重点:
- MCU的TX 引脚接 USB模块的 RXD(发送对接接收)
- 不需要接RTS/CTS流控线(默认关闭)
- GND必须共地!

✅ 软件部分

工具版本建议
Keil MDK5.37及以上
STM32F1xx标准外设库V3.5.0
串口助手XCOM、SSCOM、PuTTY任选

第一步:建工程,别再复制别人的模板

很多人学嵌入式第一步就是找“例程压缩包”,解压→打开.uvprojx→改几行代码→下载。结果一旦换个芯片就不会了。

我们要做的,是从头新建一个工程。

1. 启动 μVision,新建 Project

  • File → New uVision Project
  • 选择目标芯片:STM32F103C8
  • Keil会自动加载对应的启动文件(startup_stm32f10x_md.s)

2. 添加必要的源文件

右键“Source Group 1” → Add Existing Files:
-system_stm32f10x.c—— 系统时钟初始化
-stm32f10x_usart.c,stm32f10x_gpio.c,stm32f10x_rcc.c—— 外设驱动
- 自己写的main.c

💡 提示:这些.c文件来自标准外设库的Libraries/STM32F10x_StdPeriph_Driver/src/目录。

3. 包含头文件路径

Project → Options → C/C++ → Include Paths:

.\Inc .\Libraries\CMSIS\CM3\CoreSupport .\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x .\Libraries\STM32F10x_StdPeriph_Driver\inc

这样编译器才能找到#include "stm32f10x.h"


第二步:写代码,让USART2真正工作起来

我们选择USART2,因为它使用的引脚 PA2(TX) 和 PA3(RX) 在蓝丸板上更容易引出(不像USART1可能占用SWD调试口)。

初始化代码详解(基于标准库)

#include "stm32f10x.h" void USART2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; // Step 1: 使能时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); // USART2在APB1总线 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // GPIOA也在APB2 // Step 2: 配置PA2为复用推挽输出(TX) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用功能,推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Step 3: 配置PA3为浮空输入(RX) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // UART接收脚通常设为浮空 GPIO_Init(GPIOA, &GPIO_InitStructure); // Step 4: 配置USART2参数 USART_InitStructure.USART_BaudRate = 115200; // 波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位 USART_InitStructure.USART_Parity = USART_Parity_No; // 无校验 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 收发模式 USART_Init(USART2, &USART_InitStructure); // Step 5: 启动USART2 USART_Cmd(USART2, ENABLE); }

📌 关键点说明:

  • 时钟必须先开:否则后续配置无效;
  • TX引脚必须设为AF_PP:这样才能由USART硬件控制输出电平;
  • RX引脚设为IN_FLOATING即可,内部已有上拉/下拉可根据需要调整;
  • 波特率设为115200是目前调试最常用的高速率,响应快且兼容性好。

第三步:重定向printf,让调试变得优雅

你知道吗?每次你写下printf("i=%d\n", i);,底层其实是在调用一个叫fputc()的函数来逐个发送字符。

我们可以“劫持”这个过程,让它把每个字符送到串口而不是电脑控制台。

实现fputc重定向

#include <stdio.h> // 重定义fputc,将printf输出导向USART2 int fputc(int ch, FILE *f) { // 等待发送缓冲区为空 while (!USART_GetFlagStatus(USART2, USART_FLAG_TXE)); // 发送一个字节 USART_SendData(USART2, (uint8_t)ch); return ch; // 返回已发送字符 }

⚠️ 注意事项:
- 必须包含<stdio.h>
- 必须在 Keil 工程中启用MicroLIB
- 设置路径:Project → Options → Target → ✔ Use MicroLIB

MicroLIB 是一个轻量级C库,专为嵌入式设计,支持printf重定向。如果不勾选,printf可能链接失败或占用过多内存。


第四步:主函数验证,跑通第一个“Hello”

int main(void) { SystemInit(); // 初始化系统时钟(72MHz) USART2_Init(); // 初始化串口 printf("🎉 Keil串口调试成功!\r\n"); printf("系统时钟频率:%d Hz\r\n", SystemCoreClock); int counter = 0; while (1) { printf("计数器:%d\r\n", counter++); for (volatile int i = 0; i < 1000000; i++); // 延时约1秒 } }

编译 → 下载 → 上电!

然后打开你的串口助手(比如XCOM),设置:
- 串口号:根据设备管理器识别(如 COM5)
- 波特率:115200
- 数据位:8
- 停止位:1
- 校验位:None

点击“打开串口”,如果一切顺利,你会看到屏幕上不断刷出:

🎉 Keil串口调试成功! 系统时钟频率:72000000 Hz 计数器:0 计数器:1 ...

恭喜你,你已经拥有了自己的“开发者之眼”


常见坑点与避坑指南

别高兴太早,下面这些问题90%的人都踩过:

现象原因解法
完全没输出① TX/RXD接反
② 没开MicroLIB
③ 时钟未初始化
查线序、检查选项、确认SystemInit()
输出乱码波特率不匹配或主频不准PC和MCU同设115200;确保SystemCoreClock正确
打印一次后卡死未等待TXE标志检查是否加了while循环检测TXE
printf不编译未包含 或未用MicroLIB补头文件,勾选Use MicroLIB
接收不到数据RX脚模式错误或外部干扰设为浮空输入,加滤波电容

💡 经验分享:
如果你发现波特率总是偏差大,可能是晶振频率不对。STM32内部RC振荡器精度较差,建议后期使用外部8MHz晶振并正确配置PLL倍频至72MHz。


进阶思路:不只是“打印”,还能做什么?

当你熟练掌握基础串口调试后,可以尝试以下扩展:

1. 接收命令,实现交互式调试

if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE)) { uint8_t ch = USART_ReceiveData(USART2); if (ch == 'r') { printf("收到重启指令!\r\n"); NVIC_SystemReset(); } }

2. 使用中断方式收发

避免轮询占用CPU,提升效率:

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); NVIC_EnableIRQ(USART2_IRQn);

3. 结合FreeRTOS做日志分级

#define DEBUG(fmt, ...) do{ printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__); }while(0) #define INFO(fmt, ...) do{ printf("[INFO ] " fmt "\r\n", ##__VA_ARGS__); }while(0)

4. 构建简易AT指令集

用于控制Wi-Fi、蓝牙模块,甚至自己实现远程升级(ISP)。


写在最后:调试能力,才是工程师的核心竞争力

很多人觉得“会写算法”、“懂RTOS”才高级,但我想说:能把最基础的串口调试跑通的人,才是真正踏实的工程师

因为调试不是一项功能,而是一种思维方式——
你得学会提出假设、验证现象、定位问题、迭代修正。这个过程比写出完美代码更重要。

Keil只是一个工具,串口只是一条通道,但它们共同教会我们的,是如何与沉默的硬件对话。

所以,下次当你面对一片漆黑的终端时,别慌。
插上线,打开串口助手,写一句printf("Start...\n");
哪怕只看到一个字符,也是通往真相的第一步。

👉 如果你在实践中遇到了其他问题,欢迎在评论区留言交流。我们一起把这条路走得更稳、更远。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 15:06:27

ComfyUI-Manager终极优化指南:让低配设备也能流畅运行AI创作

ComfyUI-Manager终极优化指南&#xff1a;让低配设备也能流畅运行AI创作 【免费下载链接】ComfyUI-Manager 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Manager 还在为老旧电脑运行ComfyUI时的卡顿、崩溃而烦恼吗&#xff1f;本文将从实战角度出发&#xff…

作者头像 李华
网站建设 2026/4/15 14:38:04

近视率持续攀升:儿童近视防控,家长不可忽视的必修课

近年来&#xff0c;我国儿童青少年近视率呈逐年上升趋势&#xff0c;低龄化、重度化特征愈发明显——教育部发布的监测数据显示&#xff0c;部分地区小学生近视率已突破40%&#xff0c;初中生超70%&#xff0c;近视问题正以惊人的速度侵蚀着下一代的视觉健康。儿童近视绝非简单…

作者头像 李华
网站建设 2026/4/15 15:06:00

核心要点:proteus仿真时钟源配置方法

一文搞懂Proteus仿真中的时钟配置&#xff1a;从晶振到代码的完整闭环你有没有遇到过这种情况&#xff1f;在Proteus里画好了电路、写好了程序&#xff0c;点击仿真却“纹丝不动”——LED不闪、串口没输出、调试器卡在启动文件。翻来覆去检查代码逻辑&#xff0c;结果问题根本不…

作者头像 李华
网站建设 2026/4/14 21:22:05

初学者必看的Multisim下载与配置手把手教程

从零开始&#xff1a;手把手教你搞定 Multisim 安装与配置&#xff0c;轻松开启电路仿真之旅 你是不是也曾在搜索引擎里反复输入“ multisim下载 ”&#xff0c;却在一堆广告、破解包和英文官网之间迷失方向&#xff1f; 刚入门电子设计的你&#xff0c;是否被老师一句“用…

作者头像 李华
网站建设 2026/4/15 15:06:22

LVGL抗锯齿文本渲染技术:通俗解释其工作原理

让文字“丝滑”起来&#xff1a;LVGL抗锯齿渲染的底层真相 你有没有遇到过这种情况&#xff1f;在一块小小的OLED屏上显示中文时&#xff0c;字边缘像被锯子啃过一样——明明是圆润的“口”字&#xff0c;却变成了阶梯状的“囗”&#xff0c;尤其是斜笔画和小字号&#xff0c;…

作者头像 李华
网站建设 2026/4/9 20:31:33

Defender Control:3步搞定Windows安全防护个性化设置

Defender Control&#xff1a;3步搞定Windows安全防护个性化设置 【免费下载链接】defender-control An open-source windows defender manager. Now you can disable windows defender permanently. 项目地址: https://gitcode.com/gh_mirrors/de/defender-control 还…

作者头像 李华