尧图精选

STM32F103开发板学习路线:从环境搭建到实战避坑

🕒 发布时间:2026/10/2 0:27:05 📁 来源:尧图网络
STM32F103开发板到手先把这条学习路线理顺板子刚拿到手别急着插线、别急着点灯先把思路理顺。STM32F103这款芯片在嵌入式圈子里几乎是“入门标配”不是因为它的性能有多爆炸而是因为它太典型了——Cortex-M3内核、丰富的外设、海量的教程、便宜的板子几乎你能搜到的所有嵌入式问题最后都会落到这颗芯片上。这篇文章就围绕STM32F103开发板从环境搭建、工程创建、核心外设到实战项目再到调试点位把新手最常踩的坑和最值得花时间的地方一次性说清楚。内容比较多适合刚把板子买回来、还没有明确学习计划的朋友也适合已经点过灯、但是对定时器、串口、CAN这些外设还停留在“能跑就行”的开发者。哪怕是纯粹做毕业设计这套流程也一样用得上。1. 为什么F103开发板是入门的“标准答案”1.1 一颗芯片撑起整个MCU学习路径STM32F103C8T6这颗芯片几十块钱就能买到板子更是几十块到几百块不等。它内部有什么72MHz主频、20KB RAM、64KB Flash这个配置放在今天不算高但学习完全够用——GPIO、定时器、USART、I2C、SPI、ADC、DAC、CAN、USB几乎所有MCU该有的外设它都有。也就是说你在这块板子上学会的东西换到F4、H7、甚至国产GD32、AT32上都是同样的思路。我经常跟新手说一句话玩STM32不是在学某一种芯片而是在学一类芯片。你把F103的寄存器手册看懂了换任何一款Cortex-M3/M4的芯片翻手册的路径都是通的。F103的资源少反而逼迫你去做底层机制的理解比如时钟树是怎么走的、外设总线是怎么分的、中断优先级是怎么嵌套的。这些东西在高端芯片上反而容易被封装隐藏掉。1.2 Cortex-M3与标准外设库的历史地位F103用的是ARM Cortex-M3内核虽然已经推出了十几年但它的中断系统、存储映射、指令集依然是嵌入式开发的“通用语言”。很多国产芯片像GD32、APT32在设计上兼容STM32F103你在这块板上写的代码改改引脚定义就能跑到国产芯片上这在工程上是巨大的便利。学习F103还有一条隐性红利资料密度。市面上关于F103的教程、源码、答疑加起来可以用“海量”形容。无论你是想看寄存器版的硬核讲解还是标准库版的手把手教学或者HAL库的图形化配置都能找到对应材料。所以第一步选型F103就是“标准答案”。2. 从零搭建开发环境Keil5、芯片包与调试器2.1 Keil5兼容C51和STM32的安装方式很多人在Keil5上栽过跟头装完发现建不了STM32工程一查才知道芯片包没装。Keil5和旧版Keil4不一样它把设备支持包Device Family Pack拆出去了。默认安装的MDK只带ARM编译器不带具体芯片的库文件包你需要先到Keil官网下载STM32F1系列的DFP双击安装到Keil的安装目录下。Keil5另一个常见的坑是C51和MDK共存。如果你同时用51单片机和STM32建议把C51和MDK装在同一个Keil安装目录下这样你打开一次Keil就能自由切换。装的时候顺序其实无所谓只要路径一致最后生成的UV4.exe会被共用的C51和ARM编译器识别。如果装成了两个独立目录会出现“打开一个另一个就没了”的错觉其实是两个进程共用了一个IDE工程属性里的编译器选项不同导致的。2.2 STM32芯片包离线安装没有网络的应急方案芯片包安装不上最常见的原因就是服务器连接慢或者公司网络限制。解决方法是下载离线包。到Keil官网的DFP页面找到STM32F1系列的pack文件通常是Keil.STM32F1xx_DFP.x.x.x.pack下载完后直接双击Keil会自动识别为插件包并完成安装。还有一个细节如果双击pack没有反应试着用管理员身份运行Keil再把pack文件放到一个纯英文路径的目录里避免中文目录导致的解压失败。安装成功后你在新建工程时就能看到STMicroelectronics目录下出现了STM32F103C8、F103ZET等具体型号这时才算环境就绪。2.3 下载调试器的选型ST-Link、J-Link、DAP买开发板时商家通常有两种方案板载ST-Link/V2或者外接DAP下载器。我自己建议新手选择板载ST-Link版本因为它不需要额外接线一根USB线就既供电又下载和调试。如果你用的是不带板载调试器的板子就需要一个外接调试器推荐DAP-Link或ST-Link V2。J-Link虽然强但盗版克隆版本在学习场景下性价比有限而且newer版本的MDK会检测固件出现“The connected J-Link is defective”的提示不如直接用ST-Link生态。选调试器的时候注意区分SWD和JTAG模式STM32默认支持这两种下载方式但SWD只用两根线SWDIO和SWCLK特别适合板子空间有限、引脚紧张的初学者。3. 新建第一个工程标准库还是HAL库3.1 标准库新建工程的完整解剖很多菜鸟跟着教程建工程总是少文件编译报错一堆。标准库新建工程时最怕的是库文件、头文件路径、宏定义三者对不上。以标准外设库V3.5为例一个最简工程需要这几个部分启动文件startup_stm32f10x_hd.s或md.s记得区分芯片型号密度内核相关文件core_cm3.c/h这些是CMSIS核心RCC系统初始化相关代码尤其在用外部晶振时要配置PLL倍频标准库的src目录下你用到哪些外设就把对应的.c文件加进来不要全加宏定义STM32F10X_HD、USE_STDPERIPH_DRIVER这两个必须写对。头文件路径也别漏了包括Libraries下的CMSIS文件夹和FWlib的inc文件夹。我见过很多新手在路径设置里把include路径填成了lib文件夹的上级目录编译就会爆出一堆“stm32f10x.h: No such file or directory”。3.2 点亮第一颗LEDGPIO的完整配置流程点亮LED是嵌入式界的“Hello World”但这一步背后的机制值得吃透。GPIO有输入输出、复用、模拟四种模式F103的每个端口都挂在APB2总线上所以用GPIO前必须先开时钟。下面是标准库版本的一个完整示例#include stm32f10x.h void Delay(void) { for (uint32_t i 0; i 1000000; i); } int main(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOC, GPIO_InitStructure); while (1) { GPIO_SetBits(GPIOC, GPIO_Pin_13); Delay(); GPIO_ResetBits(GPIOC, GPIO_Pin_13); Delay(); } }这里有个新玩家常见的疑问为什么点灯之前要开时钟因为STM32为了低功耗外设时钟默认是全部关闭的你如果不使能GPIOC的时钟寄存器写的值根本无效灯就永远不亮。这个“先开时钟再操作外设”的思路贯穿整个F103学习生涯。3.3 寄存器、标准库、HAL库三套方案的取舍学习F103会遇到一个问题我应该学库还是学寄存器我的答案很直接如果你目标是搞懂原理、做底层驱动寄存器版是最透彻的路径你要自己去写RCC寄存器自己去查GPIO配置位如果你目标是快速上手、做项目、毕业设计标准库版是平衡点它把寄存器操作封装成函数但不隐藏关键流程如果你目标是走ST生态、用CubeMX快速生成多平台代码HAL库是趋势但它的层级厚出错后排查难度更高。就F103而言标准库材料最丰富且代码量适中我推荐新手先用标准库入门把GPIO、定时器、串口调通再逐步迁移到HAL。很多人一上来就学HAL结果连RCC时钟树在哪配置都不清楚遇到问题完全无处下手。4. 吃透定时器时序控制与波形生成的核心武器4.1 定时器工作的本质预分频、计数、重载STM32F103内部的定时器资源很丰富有基本定时器TIM6/TIM7、通用定时器TIM2/TIM3/TIM4/TIM5还有高级定时器TIM1/TIM8。学习定时器时永远要抓住三个数预分频系数PSC、计数周期ARR、时钟源频率。PSC和ARR的关系可以用生活中的例子来类比“预分频”就像把钟摆的摆动次数先除以N再把每次摆动计数到上限后重新归零。换算公式很简单定时器时钟 输入时钟 / (PSC1)溢出时间 (ARR1) / 定时器时钟。比如72MHz输入PSC71那么定时器时钟就是1MHz也就是1微秒计一次ARR999就是1毫秒产生一次更新事件也就是1kHz的中断频率。4.2 三种核心模式配置定时中断、PWM输出、输入捕获定时器中断是最基础用法我建议新手把“1毫秒进一次中断”调通用全局变量做计时基准。这一套搞懂你后面的超声波测距、按键消抖、OLED刷新帧率管理全都用得上。PWM输出则是电机控制、舵机驱动、调光灯的底子。配置上需要把GPIO复用为定时器通道对应的引脚再配置TIM_CounterMode、TIM_Pulse和ARR。PWM的占空比 比较值 / ARR。以舵机控制为例20ms周期0.5ms到2.5ms范围内的高电平对应舵机角度很多人直接把PSC和ARR填错导致输出频率不对舵机乱抖一查周期根本不是20ms。输入捕获模式是测频率和脉宽的利器常用于超声波测距回波时间测量、红外遥控解码等场景。思路是把定时器的某个通道配置为捕获模式当引脚检测到上升沿时记录CNT值下一次上升沿再记录两次的差值乘以定时器时钟周期就得到信号周期。5. 串口通信调试交互和数据上云的基础5.1 USART初始化必须注意的时钟和引脚映射F103的USART1挂载在APB2总线USART2/3挂在APB1总线这两条总线的时钟频率不同APB1默认36MHzAPB2默认72MHz波特率配置时的计算基准也不同。新手最容易在这上面翻车USART1在72MHz下算波特率正常同样的代码切到USART2波特率就乱了。另一个大坑是引脚复用。STM32的USART引脚不是随便选的USART1固定是PA9(TX)、PA10(RX)USART2是PA2、PA3等而且这些引脚默认可能是JTAG/SWD复用引脚使用前要配置GPIO模式为AF_PP复用推挽或AF_OD复用开漏。很多新手把PA9配成普通推挽输出串口发不出数据就是这个原因。5.2 串口对接ESP8266与“巴法云”物联网买板子后很多人第一个“物联网”项目就是把数据送到云平台。ESP8266模块通过串口和STM32通信协议是你自己定的——通常是用一个帧头加数据长度加校验位的格式。用串口中断接收不定长数据时一个经典方案是每收一个字节进中断存入环形缓冲区主循环解析缓冲区内的数据帧。巴法云这种物联网平台本质上提供了一个MQTT服务器你把ESP8266接入网络后让ESP8266和服务器保持连接STM32只需要通过串口把数据发给ESP8266ESP8266内部固件会自动向MQTT主题发布消息。我当时做这个项目时最大的体会是分帧解析的重要性——ESP8266返回的字符串里常夹杂着“OK”“busy”之类的响应如果没做好状态机解析会很头疼。6. 横纵扩展从热搜词看常用实战方向6.1 超声波测距核心是时间差不是“量距离”HC-SR04超声波模块触发方式是给Trig引脚一个10us以上的高电平模块自动发射声波并输出Echo引脚高电平高电平持续时间就是声音往返的总时间。距离厘米 Echo高电平时间(us) / 58空气声速约340m/s往返距离自然要除以2。实现过程中最简单的测高电平时间方式是“轮询等待Echo引脚变高再延时等待变低用定时器计时”。这样会阻塞主循环但如果应用不太复杂也够用。更好的方式是输入捕获配置好定时器的输入捕获通道捕获上升沿和下降沿用两次捕获的CNT差值。新手直接拿轮询方式做也行但要清楚这个方案会有几十微秒到上百微秒的误差。6.2 ILI9341屏幕读ID返回0xA1A1的异常排查ILI9341是常见TFT LCD驱动芯片读ID本应是0x9341但很多新手会读出0xA1A1。这个问题的根源通常是SPI时序中“D/CX位”没处理好。ILI9341的命令和数据操作由DC引脚决定如果你读ID的指令发送时DC电平在前导字节和后续字节之间切换错误控制器收到的不是完整命令序列就会返回错误ID或0xA1A1。0xA1A1这个特定值一般是因为液晶控制器在未正确初始化的状态下数据线默认电平恰好组合成0xA1或者SPI模式下读寄存器前没切换为读状态。排查时先确认初始化序列里“Sleep Out”“Display Off”这些命令是否按厂家手册一字不差地执行再去检查SPI模式是不是模式0空闲低电平上升沿采样ILI9341对SPI模式比较挑剔。6.3 DS1302时钟模块和数码管显示驱动思路迁移DS1302是常用的实时时钟芯片用三线接口SCLK、I/O、CE/CET通信。搜到的热词里的“普中A2开发板DS1302数码管时钟”项目本质上就是一个时钟芯片驱动和一个显示驱动的组合工程。这里要提醒新手的是DS1302对时序的时序要求很严格读取数据时在SCLK下降沿之后I/O线上才能有效很多人的数据读到都是0xFF就是信号建立时间不够。数码管本身是低成本显示方案动态扫描时必须注意刷新率一般在1kHz以上才不会闪烁。用定时器中断做扫描同时完成时分秒的更新这类小项目是最合适的综合练习。6.4 CAN通信为什么突然连不上F103自带CAN控制器在工业控制和车身电子中广泛使用。热词里提到“CAN通信突然连不上”这几乎是每位工程师都经历过的噩梦。根因通常有四类波特率配置不一致。CAN有两个时钟段同步段、相位段1、相位段2必须保证网络中所有节点的位时序参数一致终端电阻缺失。CAN总线两端只要各接一个120欧电阻这是基本要求少了一端电阻信号反射会导致总线错误高字节序/位序错配。CAN标准帧ID和数据字节序在不同厂商协议中定义不同总线关闭Bus Off。某个节点发送错误过多控制器自动从正常状态切换到离线状态需要重新初始化才能恢复。排查用CAN分析仪最省事看不到波形时先用回环模式测试本机收发。如果硬件上没有CAN收发器一般开发板都集成TJA1050或者MCP2551但如果你是自己做的板子先查VCC和GND是不是接反了。7. 新手最容易踩的坑故障排查速查表与避坑心得7.1 下载烧录失败的“三大元凶”“VS Code里编译成功却怎么也烧录不进开发板”是很多人在从Keil切到VSCode后遇到的情况。其实问题不在编译而在烧录配置。VSCode的Embedded IDE插件或者PlatformIO需要在配置文件里指定烧录工具、接口类型、芯片型号。烧录失败原因通常有三个连接类型下载器型号配置错了比如代码选“ST-Link”实际插的是DAP接线松了SWDIO和SWCLK两根线接触不良会随机失败芯片读保护开启。如果你之前烧过加密程序或者误操作设置了RDP调试器无法连接需要先用“under reset”模式或ST-Link Utility去解除保护。7.2delay函数卡死别急着改代码先查时钟热词“stm32延时函数delay卡死”是非常典型的入门问题。ESDelay、标准库自带的SysTick延时函数、或者自己写的循环延时卡死的现象背后往往只有一个核心原因SysTick定时器的时钟源和预期不符或者中断优先级冲突。F103的SysTick默认使用HCLK/8作为时钟源而很多人配置外部晶振后忘了调整SystemInit里的时钟分频参数导致延时时间比预期长几十倍看起来就像死循环卡住。还有一种情况是SysTick的中断优先级和别的中断一样高中断互相抢占把SysTick的计时线程卡死了。解决办法很土但有效先把SysTick的优先级设为最低再看延时的实际时间用示波器或者逻辑分析仪测一下某个GPIO翻转周期。7.3 STM32芯片第一脚怎么确认这个问题看似基础却难倒过不少焊板子的人。贴片封装的STM32第一脚通常用三种方式标记芯片一角上的小圆点、正面斜切角周边长方形色块、封装丝印上的“白点”。注意STM32F103的圆形凹点在丝印上有时出现在2脚附近不要想当然把“圆点”当第1脚一定要以官方数据手册的Bottom View透视图为准。7.4 STM32禁用JTAG哪些引脚不能随意复用F103有几组默认引脚兼容JTAG仿真器PA13SWDIO、PA14SWCLK、PA15JTDI、PB3JTDO、PB4JTRST。如果你在代码里把PA15或PB3当普通GPIO使用会发现它们怎么都输不出电平——因为这些引脚上电后默认作为JTAG复用功能。解决办法是在代码里先调用GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE)禁用JTAG功能但这样会同时关掉SWD调试接口。如果还用SWD调试就用GPIO_Remap_SWJ_JTAGDisable只关JTAG保留SWD。这就是为什么很多人一禁用JTAG后下载器就连接不上了的来源。结语几个实操项目建议STM32F103开发板买回来只是学习链条的第一步。我建议按下面这个顺序做一遍能让你对F103的理解上一个台阶先做“LED呼吸灯”用PWM调光同时测一下PWM的频率和占空比第二步做“串口收发命令控制LED”把串口中断、状态机、帧校验都过一遍第三步做一个传感器项目比如超声波测距或者DHT11温湿度把ADC或者定时器输入捕获用上第四步再做一个小屏项目用ILI9341或者OLED显示数据把SPI/I2C联合起来用。在踩过一轮坑之后你再去翻标准库源码会有完全不同的收获。嵌入式学习从来不是看书看会的你就拿一块板子、一根USB线、一个示例工程慢慢折腾。折腾通了这板子的价值就回本了。如果后面想深入研究USB设备、RTOS、甚至Linux驱动的部分F103也提供了足够的基础。有点可惜了没能早些告诉大家这块板子买到手你花时间最大的从来不是看视频而是静下心把时序图和参考手册对着读把一个外设调通。这一点越早体会到学得越快。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →