第二章 开发环境搭建:交叉编译工具链安装、调试器配置、串口终端工具使用
说实话,很多初学者一上来就急着写代码,结果卡在环境搭建上三天三夜。我当年也干过这种蠢事——工具链没配好就编译,报错信息看得一头雾水。后来学乖了:先把环境收拾利索,后面才能跑得顺畅。
这一章,咱们就把开发环境彻底搞定。包括三样东西:交叉编译工具链、调试器(JTAG/SWD)、串口终端。这三板斧拿下了,你就能在PC上编译出能在ARM芯片上跑的程序,还能烧进去、调起来、看输出。
核心思路: 你的PC是x86架构,目标板是ARM架构。PC上编译的程序不能在ARM上直接跑,必须用交叉编译工具链。调试器负责把程序烧进去并控制执行,串口则让你看到板子“说了什么”。
2.1 交叉编译工具链安装
什么叫交叉编译?说白了,就是在你的电脑上编译出能在另一个CPU架构上运行的程序。比如你在x86的笔记本上编译ARM的可执行文件。
我个人习惯用 gcc-arm-none-eabi 这套工具链。它是开源的,专门针对ARM Cortex-M系列芯片。安装方式很简单,我直接说最常用的两种。
2.1.1 在Ubuntu上安装
sudo apt update
sudo apt install gcc-arm-none-eabi
装完以后,验证一下:
arm-none-eabi-gcc --version
如果看到版本号,说明装好了。嗯,这里要注意:有些老版本的Ubuntu源里工具链版本太旧,我建议去ARM官网下载最新版。
2.1.2 在Windows上安装
Windows下我推荐用 GNU Arm Embedded Toolchain 的Windows安装包。去ARM官网下载,一路Next就行。装完后记得把bin目录加到系统PATH里。
小技巧: 我个人习惯在用户目录下建一个 ~/tools/ 文件夹,把所有工具链都放里面。这样换电脑时直接拷贝这个文件夹,省得重新配。
2.1.3 验证工具链是否可用
写个最简单的程序试试:
// test.c
int main(void) {
return 0;
}
编译:
arm-none-eabi-gcc -c test.c -o test.o
arm-none-eabi-objdump -d test.o
如果能看到ARM汇编指令,说明工具链工作正常。
我曾经踩过的坑: 有一次我装完工具链,编译时总报“找不到头文件”。查了半天,发现是环境变量没配好。记住:工具链的bin目录必须加到PATH里,否则系统找不到可执行文件。
2.2 调试器配置(JTAG/SWD)
调试器是嵌入式开发的“眼睛”。没有它,你只能靠猜。JTAG和SWD是两种常见的调试接口。JTAG需要4-5根线,SWD只需要2根(SWDIO和SWCLK)。现在大多数Cortex-M芯片都支持SWD,我个人也更喜欢用SWD,因为省引脚。
2.2.1 常用调试器硬件
| 调试器型号 | 接口类型 | 特点 |
|---|---|---|
| J-Link | JTAG/SWD | 速度快,稳定,价格稍贵 |
| ST-Link | SWD | STM32板载调试器,性价比高 |
| DAP-Link | SWD | 开源,支持CMSIS-DAP协议 |
| OpenOCD + FT2232 | JTAG/SWD | 灵活,但配置稍复杂 |
我在项目中用得最多的是J-Link。虽然贵了点,但稳定性和速度确实好。有一次调试一个USB协议栈,用ST-Link死活连不上,换J-Link一次成功。从那以后,我手边常备一个J-Link。
2.2.2 安装调试器驱动
以J-Link为例:
- 去SEGGER官网下载J-Link软件包
- 安装后,驱动会自动装好
- 用USB线连接调试器和电脑
- 打开设备管理器,确认能看到J-Link设备
小技巧: 如果你用的是Linux,可能需要给J-Link添加udev规则。否则普通用户权限下无法访问USB设备。规则文件一般在安装包里就有,拷贝到 /etc/udev/rules.d/ 目录下就行。
2.2.3 连接调试器到目标板
SWD接口只需要4根线:
- SWDIO:数据线
- SWCLK:时钟线
- GND:地线
- VCC:参考电压(可选,有些调试器需要)
连接时注意:SWDIO和SWCLK上最好加10kΩ上拉电阻到VCC。我曾经因为没加上拉电阻,导致调试器偶尔连不上,排查了整整一天。
2.2.4 验证调试器连接
用J-Link自带的命令行工具测试:
JLinkExe
device STM32F103C8
connect
如果能看到芯片ID,说明连接成功。如果报错,先检查接线,再检查驱动。
注意: 调试器连接时,目标板必须上电。有些调试器可以从USB取电给目标板,但电流有限。如果你的板子功耗大,建议单独供电。
2.3 串口终端工具使用
串口是嵌入式开发中最常用的调试手段。printf打印、日志输出、交互命令,全靠它。你想想看,没有串口,你怎么知道程序跑到哪一步了?
2.3.1 常用串口终端工具
| 工具名称 | 平台 | 特点 |
|---|---|---|
| PuTTY | Windows | 轻量,支持SSH和串口 |
| MobaXterm | Windows | 功能丰富,支持多标签 |
| screen | Linux | 命令行工具,轻量 |
| minicom | Linux | 经典串口工具,配置稍复杂 |
| Serial Monitor (VS Code插件) | 跨平台 | 集成在IDE中,方便 |
我个人在Windows下用MobaXterm,在Linux下用screen。MobaXterm的会话管理功能很强大,可以保存多个串口配置。screen则胜在轻量,一条命令就能用。
2.3.2 串口参数设置
串口通信需要双方约定好参数。常见的设置是:
- 波特率:115200(最常用)
- 数据位:8
- 停止位:1
- 校验位:无
- 流控制:无
为什么是115200?因为它是标准波特率中比较快的一个,而且大多数芯片的UART都能稳定支持。我见过有人用921600,结果线稍微长一点就丢数据。
2.3.3 在Linux下使用screen
# 查看串口设备
ls /dev/ttyUSB*
# 连接串口,波特率115200
screen /dev/ttyUSB0 115200
# 退出screen:Ctrl+A,然后按K
如果提示权限不足,把用户加到dialout组:
sudo usermod -a -G dialout $USER
然后注销重新登录。
2.3.4 在Windows下使用MobaXterm
- 打开MobaXterm,点击“Session”
- 选择“Serial”
- 选择串口号(在设备管理器中查看)
- 设置波特率115200,数据位8,停止位1,校验位无
- 点击“OK”
连接成功后,如果目标板有打印输出,你就能在终端里看到了。
小技巧: 我习惯在串口终端里开启“本地回显”。这样你输入的命令也能显示出来,方便调试交互式程序。MobaXterm里在“Terminal settings”中勾选“Local echo”就行。
2.3.5 验证串口通信
写一个简单的程序,让板子每隔1秒打印一次“Hello World”:
#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
int main(void) {
HAL_Init();
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置串口引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置串口
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&huart1);
char msg[] = "Hello World!\r\n";
while (1) {
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
HAL_Delay(1000);
}
}
编译烧录后,打开串口终端,你应该能看到每隔1秒打印一次“Hello World”。
我曾经踩过的坑: 有一次我串口终端什么也收不到,检查了接线、波特率、程序,都没问题。最后发现是USB转串口模块的TX和RX接反了。记住:TX接RX,RX接TX,交叉连接!
2.4 本章知识体系
为了让你更直观地理解这三样工具的关系,我画了一张图:
这张图展示了PC和目标板之间的数据流。你在PC上写代码,用交叉编译工具链编译成ARM可执行文件,通过调试器烧录到芯片里,然后用串口终端看输出。这三样工具缺一不可。
2.5 常见问题与避坑指南
- 工具链装好了但编译报错:检查环境变量,确认arm-none-eabi-gcc在PATH里。我曾经因为装了多个版本的Python,导致PATH混乱,工具链找不到。
- 调试器连不上芯片:先检查接线,再检查芯片供电。有些芯片需要先复位才能连接。我遇到过芯片被锁死的情况,需要用调试器的“unlock”功能。
- 串口收不到数据:检查TX/RX是否接反,波特率是否匹配。还有一个常见问题:串口工具的流控制(RTS/CTS)没关,导致数据发不出去。
- 串口收到乱码:波特率不匹配,或者芯片的时钟配置不对。我遇到过芯片内部时钟不准,导致实际波特率偏离设定值的情况。
总结一下: 开发环境搭建是嵌入式开发的第一步,也是最容易出问题的一步。工具链、调试器、串口终端,这三样东西配好了,后面的开发就会顺畅很多。别急着写代码,先把环境搞利索。
嗯,这一章的内容就到这里。环境搭好了,下一章咱们就可以开始写真正的板级代码了。