☰
STM32F103开发板入门指南:从环境搭建到第一个程序
2026/9/29 2:43:12 网站建设 项目流程

STM32F103的开发板到手了,接下来该干什么

板子刚拆封那会儿,我盯着那块蓝色PCB看了半天——STM32F103C8T6,72MHz主频,64KB Flash,20KB SRAM,板载了ST-Link和USB接口,还引出了所有GPIO。说实话,这玩意儿比当年我用的51单片机强太多了,但随之而来的问题是:从哪儿下手?网上教程铺天盖地,有讲寄存器的,有讲标准库的,有讲HAL的,还有直接上RTOS的,看多了反而不知道该听谁的。这篇文章就是写给刚拿到STM32F103开发板、想系统入门但不想被各种教程绕晕的人。我会从板子到手后的第一件事开始,把环境搭建、工程创建、第一个程序烧录、常见问题排查这条完整链路讲清楚,中间穿插我自己踩过的坑和总结出来的经验。不管你是电子专业的学生,还是转行做嵌入式的开发者,跟着这条路径走,至少能少走两三个月的弯路。

1. 拿到板子先别急着写代码,这几件事决定了后面顺不顺

1.1 确认板子型号和核心芯片的具体参数

STM32F103这个系列下面有非常多型号,C8T6、RCT6、ZET6、VET6等等,封装不同、引脚数不同、Flash和RAM大小也不同。我手里这块是C8T6,LQFP48封装,64KB Flash、20KB SRAM,属于入门级里最经典的配置。为什么要先确认这个?因为后面你选芯片包、配工程、写链接脚本的时候,都要跟具体型号对应。比如你拿的是RCT6(256KB Flash、48KB SRAM),却按C8T6的配置去建工程,编译可能没问题,但烧录后跑起来会出各种莫名其妙的问题。

板子上一般会印型号,如果没有,看主控芯片表面的丝印。另外注意板子的晶振频率——大部分F103板子用的是8MHz外部晶振,经过PLL倍频到72MHz作为系统时钟。也有少数板子用12MHz晶振,这个在配置时钟树的时候要特别留意,配错了串口波特率会全乱。

1.2 检查板载的调试器和供电方式

现在市面上很多F103开发板都板载了ST-Link或者DAP-Link调试器,直接用一根USB线就能完成供电、下载、调试三件事。但有些便宜的板子只留了SWD排针,需要你外接调试器。拿到板子后先确认这一点,因为它决定了你后面用什么方式烧录程序。

如果板载了调试器,插上USB后设备管理器里应该能看到对应的调试器设备。如果没看到,可能需要装驱动。ST-Link的驱动在ST官网可以下载,DAP-Link的话Win10以上一般免驱。这里有个细节:有些板子的USB接口只负责供电,调试接口是另外一个Type-C或者Micro-USB口,别插错了。

注意:插上USB后如果板子上的电源灯不亮,先换一根USB线试试。很多便宜的USB线只有充电功能,没有数据线芯,这个坑我见过太多次了。

1.3 准备好必要的软件工具链

STM32开发常用的IDE有Keil MDK、IAR EWARM、STM32CubeIDE这几种。Keil在国内用得最多,资料也最全,但需要单独安装芯片包(Pack)。STM32CubeIDE是ST官方推出的免费IDE,基于Eclipse,集成了CubeMX配置工具,适合不想折腾License的开发者。VS Code加PlatformIO或者EIDE插件也是一条路,适合习惯轻量级编辑器的朋友。

我的建议是:入门阶段用Keil MDK或者STM32CubeIDE,先把流程跑通,别一上来就折腾VS Code的各种插件配置。等你对编译、链接、烧录这些环节有了直观感受之后,再换工具也不迟。芯片包的安装后面会详细讲,这里先有个概念就行。

2. 开发环境搭建:从零到编译通过的完整路径

2.1 Keil MDK的安装与芯片包配置

Keil MDK的安装本身没什么难度,一路Next就行。关键是装完之后要安装STM32F1系列的Device Family Pack。这个包不在Keil安装包里,需要单独下载。打开Keil后点击Pack Installer图标,在左侧找到STMicroelectronics,展开后找到STM32F1 Series,点击对应的Pack进行安装。

如果网络环境不好导致在线安装失败,也可以去Keil官网手动下载Pack文件,然后双击安装。Pack文件的后缀是.pack,安装路径一般会自动识别Keil的安装目录。装完之后新建工程时才能在芯片列表里找到STM32F103C8这类型号。

这里有个常见问题:有些人装完Pack后新建工程还是找不到芯片,原因通常是Pack版本和Keil版本不匹配。比如Keil MDK 5.36配STM32F1的Pack 2.3.0一般没问题,但如果Keil版本太老(比如5.14),可能需要用旧版的Pack。遇到这种情况,要么升级Keil,要么降级Pack,没有别的办法。

2.2 使用STM32CubeMX生成初始化代码

STM32CubeMX是ST官方出的图形化配置工具,可以帮你生成引脚配置、时钟树、外设初始化的代码。对于新手来说,它能大幅降低入门门槛,因为你不需要一上来就对着参考手册写寄存器。

具体流程是这样的:新建工程,选择芯片型号STM32F103C8Tx,然后配置时钟源。在RCC里把HSE设为Crystal/Ceramic Resonator,然后在Clock Configuration里把HCLK拉到72MHz。接着配置调试接口,在SYS里把Debug设为Serial Wire,这样SWD接口才能正常工作。最后配置你要用的外设,比如GPIO、USART、TIM等。

生成代码的时候注意选对工具链。如果你用Keil,就选MDK-ARM;如果用STM32CubeIDE,就选STM32CubeIDE。生成的代码会包含main.c、stm32f1xx_hal_msp.c、stm32f1xx_it.c等文件,以及HAL库的驱动文件。

提示:CubeMX生成的代码里,用户代码要写在/* USER CODE BEGIN/和/USER CODE END */之间,否则下次重新生成代码时会被覆盖掉。这个规则一定要记住,我见过太多人因为把代码写错位置,重新生成后全部丢失的。

2.3 标准库工程模板的手动搭建

虽然HAL库现在是主流,但很多老教程和项目还在用标准库(Standard Peripheral Library)。标准库的好处是代码量小、执行效率高、贴近寄存器操作,适合想深入理解底层的人。但ST已经不再维护标准库了,新建工程需要手动拷贝库文件。

手动搭建标准库工程的步骤大致是:新建工程目录,在里面创建Startup、Library、User、Output等文件夹。把启动文件(startup_stm32f10x_md.s)、系统文件(system_stm32f10x.c)、内核文件(core_cm3.c/h)以及STM32F10x_StdPeriph_Driver里的外设驱动文件拷贝到对应目录。然后在Keil里新建工程,添加这些文件,配置头文件包含路径,最后在Options for Target里设置好Output和Listing路径。

这个过程比较繁琐,但做一遍之后你对STM32工程的组成结构会有非常清晰的认识。网上有很多现成的标准库工程模板可以下载,但建议至少自己手动搭一次,知道每个文件是干什么用的。

3. 第一个程序:从点亮LED到串口输出

3.1 GPIO输出实验:点亮板载LED

点亮LED是嵌入式开发的Hello World。F103的GPIO配置流程是:使能GPIO时钟、配置GPIO模式、设置输出电平。用HAL库的话,代码大概长这样:

// 使能GPIOC时钟 __HAL_RCC_GPIOC_CLK_ENABLE(); // 配置PC13为推挽输出 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // 在主循环里翻转电平 while (1) { HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); HAL_Delay(500); }

这里有个细节:很多F103最小系统板的板载LED接在PC13上,而且是低电平点亮。也就是说,你写HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET)的时候LED是亮的,写SET的时候是灭的。这个跟硬件电路有关,拿到板子后最好用万用表测一下LED的正负极方向,或者直接看原理图。

3.2 串口通信实验:printf重定向

串口是调试过程中最重要的工具之一。F103一般用USART1,引脚是PA9(TX)和PA10(RX)。配置好波特率(常用115200)、数据位、停止位、校验位之后,就可以收发数据了。

为了能用printf输出调试信息,需要重定向fputc函数:

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

然后在Keil的Options for Target里勾选Use MicroLIB,否则printf可能无法正常工作。这个坑非常经典,很多人写了重定向代码但串口没输出,就是因为没勾MicroLIB。

串口调试助手可以用SSCOM、XCOM或者PuTTY。注意波特率、数据位、停止位、校验位要和代码里配置的一致,否则收到的全是乱码。

3.3 定时器实验:精准延时与PWM输出

HAL_Delay()函数用的是SysTick定时器,精度一般,而且在中断里调用会有问题。如果需要更精准的延时或者PWM输出,就要用通用定时器(TIM2~TIM5)。

配置定时器的时候要算好预分频系数(PSC)和自动重装载值(ARR)。比如系统时钟72MHz,想要1ms的定时周期,可以设PSC=71,ARR=999,这样定时器时钟就是72MHz/(71+1)=1MHz,计数1000次就是1ms。

PWM输出的配置稍微复杂一点,需要设置PWM模式、占空比、极性等。用CubeMX配置的话,选好定时器和通道,设置好PSC和ARR,然后在代码里用__HAL_TIM_SET_COMPARE()宏来动态调整占空比。

4. 烧录与调试:程序怎么进到芯片里

4.1 ST-Link烧录的接线与配置

SWD接口需要四根线:VCC、GND、SWDIO、SWCLK。有些板子还引出了SWO和NRST,但最基本的四根线就能完成烧录和调试。接线的时候注意VCC的电压,F103是3.3V供电,别接5V。

在Keil里配置ST-Link调试器:Options for Target -> Debug -> 选择ST-Link Debugger -> Settings -> 确认Port是SW,能识别到芯片ID。然后在Flash Download选项卡里确认编程算法是STM32F10x Medium-density Flash(对应64KB/128KB的型号)。

如果识别不到芯片,先检查接线,再检查板子是否上电,最后检查SWD引脚是否被程序禁用了。有些程序会把SWD引脚配置成普通GPIO,导致下次无法烧录。遇到这种情况,需要把BOOT0拉高,让芯片从系统存储器启动,然后重新烧录。

4.2 常见烧录失败原因排查

烧录失败是新手最常遇到的问题,原因五花八门。我整理了一个排查表:

现象可能原因解决办法
找不到芯片接线错误或板子没供电检查SWD四根线,确认电源灯亮
找不到芯片SWD引脚被禁用BOOT0拉高,重新上电后再烧录
烧录报错Flash Download failed编程算法选错确认芯片型号对应的Flash算法
烧录成功但不运行复位电路问题检查NRST引脚,尝试手动复位
烧录成功但不运行时钟配置错误检查HSE晶振是否起振

还有一个经典问题:VS Code里编译成功,但怎么也烧录不进开发板。这种情况通常是烧录工具配置不对,或者OpenOCD的配置文件跟芯片不匹配。建议先用Keil或者STM32CubeProgrammer确认能正常烧录,再回头调VS Code的配置。

4.3 使用STM32CubeProgrammer进行独立烧录

STM32CubeProgrammer是ST官方的烧录工具,支持ST-Link、UART、USB、OTA等多种方式。它的好处是不依赖IDE,可以单独用来烧录hex或者bin文件。批量生产的时候特别有用。

用ST-Link连接后,选择对应的端口,加载hex文件,点击Download就行。如果要烧录bin文件,需要手动指定起始地址(一般是0x08000000)。烧录完成后可以点击Verify校验,确保数据写入正确。

5. 入门之后往哪走:几个值得深入的方向

5.1 中断系统与NVIC配置

STM32的中断系统比51复杂得多,有优先级分组、抢占优先级、响应优先级等概念。F103的NVIC支持16个优先级,通过NVIC_PriorityGroupConfig()来设置分组。分组决定了抢占优先级和响应优先级各占几位。

举个例子:如果你设置分组为NVIC_PriorityGroup_2,那么抢占优先级和响应优先级各占2位,取值范围都是0~3。抢占优先级高的可以打断抢占优先级低的中断,相同抢占优先级下响应优先级高的先执行,但不能打断。

外部中断(EXTI)的配置流程是:使能GPIO和AFIO时钟、配置GPIO为输入模式、配置EXTI触发方式、配置NVIC、编写中断服务函数。按键中断是最典型的应用场景。

5.2 定时器输入捕获与超声波测距

超声波测距模块(HC-SR04)是很多STM32项目的标配。原理很简单:Trig引脚发一个10us的高电平脉冲,模块发出超声波,Echo引脚变高,收到回波后变低。Echo高电平的持续时间就是超声波往返的时间,除以2再乘以声速就是距离。

用定时器的输入捕获功能可以精准测量Echo引脚的高电平时间。配置TIM的某个通道为输入捕获模式,上升沿触发,在中断里记录CNT值,然后切换为下降沿触发,再次记录CNT值,两次之差就是高电平时间。

这里有个经验:超声波测距的精度受温度影响比较大,声速在0度时是331m/s,每升高1度增加0.6m/s。如果要做高精度测量,需要加温度补偿。另外测量周期不要太短,HC-SR04建议至少60ms一次,否则会有回波干扰。

5.3 USB虚拟串口与设备开发

F103的USB外设是Full Speed的,可以做成虚拟串口(CDC)、HID设备、大容量存储等。用CubeMX配置USB Device的时候,选择Communication Device Class,生成代码后安装ST的VCP驱动,电脑上就会多出一个串口。

USB虚拟串口的好处是不需要额外的USB转串口芯片,一根线就能搞定通信。但要注意,F103的USB和CAN共用引脚,不能同时使用。另外USB的时钟必须精确配置为48MHz,否则枚举会失败。

5.4 基于标准库和HAL库的取舍

标准库和HAL库各有优劣。标准库代码精简、执行效率高、寄存器操作直观,适合资源紧张或者需要精细控制的场景。HAL库抽象程度高、跨系列移植方便、配合CubeMX开发效率高,但代码体积大、执行效率相对低。

我的建议是:入门阶段用HAL库+CubeMX,快速建立信心和整体认知。等你有了一定基础,再回头研究标准库或者直接操作寄存器,理解底层原理。实际项目中,两者可以混用,比如用CubeMX生成初始化代码,然后关键部分用寄存器操作优化性能。

6. 那些教程不会告诉你的实操经验

6.1 关于延时函数卡死的问题

HAL_Delay()卡死是新手经常遇到的现象。原因通常是SysTick中断优先级配置不当,或者在中断服务函数里调用了HAL_Delay()。SysTick的中断优先级默认是最低的,如果某个高优先级中断一直在执行,SysTick中断就无法触发,HAL_Delay()就会一直等待。

解决办法是:不要在中断里调用HAL_Delay(),如果确实需要延时,用简单的循环延时或者硬件定时器。另外检查一下NVIC的优先级分组,确保SysTick的优先级没有被意外设得太低。

6.2 关于JTAG和SWD引脚复用

F103的PA13、PA14、PA15、PB3、PB4这几个引脚默认是JTAG功能。如果你想把它们当普通GPIO用,需要禁用JTAG,只保留SWD。用标准库的话,调用GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE)就行。用HAL库的话,在CubeMX的SYS配置里把Debug设为Serial Wire,生成的代码会自动处理。

这个坑很隐蔽,因为引脚看起来能用,但输出电平不对。我当初调一个SPI屏幕,PB3和PB4死活不出信号,查了半天才发现是JTAG没禁用。

6.3 关于电源和复位电路的细节

有些便宜的F103板子为了省成本,复位电路只放了一个电容,没有上拉电阻。这种板子上电后可能不复位,或者复位不可靠。表现就是程序有时候跑有时候不跑,或者烧录后要手动按复位键才运行。

如果遇到这种情况,可以在NRST引脚和VCC之间加一个10K的上拉电阻,再并一个100nF的电容到地。这是ST官方推荐的标准复位电路。另外BOOT0引脚最好也加一个10K下拉电阻,避免悬空导致启动模式不确定。

6.4 关于芯片包安装失败的替代方案

Keil的Pack Installer有时候会因为网络问题下载失败。除了手动下载Pack文件之外,还有一个办法是用离线Pack。在Keil的Pack Installer里选择File -> Import,然后选择下载好的.pack文件。如果连官网都打不开,可以去一些国内的电子论坛找网友分享的Pack文件,注意核对版本号和文件完整性。

STM32CubeIDE的话,芯片包是集成在安装包里的,一般不需要单独安装。但如果你需要更新到最新版的HAL库,可以在Help -> Manage Embedded Software Packages里在线更新。

6.5 关于开发板挂载Ubuntu后的权限问题

有些朋友喜欢在Ubuntu下用OpenOCD或者STM32CubeProgrammer烧录。插上ST-Link后可能会提示权限不足,这是因为普通用户没有USB设备的访问权限。解决办法是添加udev规则:

sudo nano /etc/udev/rules.d/99-stlink.rules

在里面写入:

SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="3748", MODE="0666"

然后重新加载udev规则:

sudo udevadm control --reload-rules sudo udevadm trigger

不同版本的ST-Link的idProduct可能不同,可以用lsusb命令查看。这个配置做一次就行,以后插上就能直接用。

板子到手只是开始,真正有意思的是后面把一个个外设调通、把一个个项目做出来的过程。F103虽然老,但资料全、生态好、价格便宜,作为入门第一块STM32开发板再合适不过。我到现在还会用F103做一些小项目,它的性能和资源对于大多数控制类应用来说完全够用。先把GPIO、串口、定时器、中断这几个基础外设玩熟,后面学RTOS、文件系统、网络协议栈都会顺很多。遇到问题别慌,先查手册、再查论坛、最后动手验证,嵌入式开发就是这样一步步积累起来的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询