1. 拿到板子先别急着点灯STM32F103开发板入门全景拆解STM32F103这块板子大概是无数嵌入式人入坑的第一块开发板。我身边做硬件、做固件、做物联网的朋友聊起入门经历十有八九都是从一块F103最小系统板或者整板开始的。这次把板子买回来说明你已经迈出了最关键的一步——硬件到手了剩下的就是怎么把它“盘活”。但我要先泼一盆冷水很多人拿到板子第一件事就是插上USB打开Keil找个点灯例程烧进去灯亮了就觉得自己会了然后过两天就吃灰了。问题出在哪出在跳过了“理解这块板子到底有什么、为什么这么设计”的阶段。STM32F103是意法半导体基于ARM Cortex-M3内核的32位微控制器主频常见72MHz片上Flash从16KB到1MB不等SRAM从6KB到96KB封装从LQFP48到LQFP144都有。市面上常见的“STM32F103开发板”通常指F103C8T6最小系统板蓝色药丸那种或者F103ZET6/F103VET6这类大板。C8T6便宜、小巧适合入门和做小项目ZET6资源多、外设全适合跑复杂一点的工程。你买的是哪种直接决定了后面能玩到什么程度。这篇文章适合谁看如果你是刚拿到板子、装好了Keil但不知道下一步干什么的新手或者你之前玩过51单片机、想转到STM32但被各种库和配置搞晕的人再或者你手头有块板子但一直没找到系统学习路径那这篇内容就是给你写的。我会从板子到手后的第一件事开始一路讲到工程模板搭建、外设调试、常见坑排查把F103开发板入门的完整链路拆开揉碎讲清楚。2. 板子到手后的第一轮检查与工具链准备2.1 开箱后必须确认的硬件细节板子拿到手先别通电。我见过太多人直接插USB结果板子上的电源指示灯不亮或者一插上电脑就提示“USB设备无法识别”折腾半天发现是跳线帽没插或者供电选择不对。所以第一步是肉眼检查。先看供电部分。大多数F103开发板支持三种供电方式USB供电、DC电源座供电、以及通过排针从外部引入3.3V或5V。板子上通常有跳线帽或者拨码开关来选择供电来源。你要确认的是如果打算用USB供电跳线帽是否短接了USB的5V到板载稳压芯片的输入端。很多板子的USB口只负责数据通信不负责供电或者需要短接某个跳线才能供电。这个细节在板子的原理图里一定有标注找不到原理图就去卖家页面翻或者直接问客服要。然后确认BOOT引脚的状态。STM32F103有两个BOOT引脚BOOT0和BOOT1。BOOT0决定启动模式BOOT1配合BOOT0选择具体从哪启动。正常从Flash启动时BOOT0接低电平GNDBOOT1任意。如果你要串口下载程序需要把BOOT0接高电平3.3VBOOT1接低电平复位后进入系统存储器启动模式。很多板子用跳线帽或者拨码开关来设置这两个引脚拿到板子先确认它们的状态不然你烧录的时候会发现“怎么都烧不进去”。再看晶振。F103板子上一般有两个晶振一个8MHz的高速晶振HSE给系统提供主时钟一个32.768kHz的低速晶振LSE给RTC用。有些廉价板子为了省成本LSE晶振不焊这会影响RTC功能但不影响基本运行。你拿到板子后如果发现RTC走时不准或者根本不动先检查LSE晶振是否焊接了。最后看调试接口。F103支持SWD和JTAG两种调试方式。SWD只需要两根线SWCLK和SWDIO加上GND和3.3V一共四根线就能下载和调试。JTAG需要更多引脚但功能更全。现在主流都是用SWD因为引脚少、接线简单。板子上通常会引出一个标准的20针JTAG座或者4针的SWD排针。你要确认的是板子上是否有这个接口以及接口的引脚顺序。不同厂家的板子SWD排针的顺序可能不一样接错线会烧调试器或者芯片。注意在通电之前务必用万用表蜂鸣档测一下板子上3.3V和GND之间是否短路。有些板子出厂时可能有焊接不良或者锡渣残留直接通电会烧稳压芯片。这个检查花不了两分钟但能避免不必要的损失。2.2 调试器选型ST-Link、J-Link还是DAP-Link调试器是你和芯片之间的桥梁选对了后面一路顺畅选错了天天折腾。市面上常见的调试器有ST-Link、J-Link、DAP-Link三种各自有适用场景。ST-Link是意法半导体官方的调试器兼容性最好配合STM32CubeProgrammer或者Keil MDK使用都很稳。价格从十几块的克隆版到几百块的原版都有。克隆版ST-Link在大多数场景下够用但固件升级可能会遇到问题。如果你只是学F103买个克隆版ST-Link完全够用注意买带SWD接口的版本通常是四针或者五针。J-Link是SEGGER的调试器功能强大支持芯片型号多调试速度快。但正版J-Link价格不菲克隆版J-Link在F103上也能用但固件容易被锁而且某些克隆版对Keil版本有要求。如果你后续要玩更高级的芯片或者需要更快的下载速度J-Link值得考虑。但纯入门F103J-Link有点杀鸡用牛刀。DAP-Link是开源的调试器方案基于CMSIS-DAP协议价格便宜通常二三十块就能买到。它支持SWD和JTAG配合Keil、IAR、VS Code都能用。DAP-Link的优点是开源、便宜、兼容性好缺点是某些克隆版的稳定性不如ST-Link。如果你预算有限DAP-Link是不错的选择。我的建议是入门F103先买一个克隆版ST-Link十几块钱配合Keil MDK使用遇到问题的概率最低。等你玩到需要更高级调试功能的时候再考虑J-Link。2.3 软件工具链的安装与配置软件方面你需要至少装三个东西Keil MDK或者STM32CubeIDE、STM32CubeMX、以及对应的芯片包。Keil MDK是经典的STM32开发环境国内资料最多遇到问题最容易搜到答案。安装Keil MDK之后还需要安装STM32F1系列的Device Family PackDFP也就是芯片包。芯片包不装Keil里找不到F103的型号新建工程时选不了芯片。芯片包可以从Keil官网下载也可以从意法半导体官网下载。安装方法很简单双击.pack文件Keil会自动识别并安装。STM32CubeMX是意法半导体的图形化配置工具用来生成初始化代码。你可以用它配置时钟树、外设引脚、中断优先级等然后生成Keil或者STM32CubeIDE的工程。对于新手来说CubeMX能大幅降低初始化代码的编写难度但我不建议完全依赖它。原因后面会讲。STM32CubeIDE是意法半导体推出的免费IDE基于Eclipse集成了CubeMX和编译调试功能。如果你不想用KeilCubeIDE是不错的替代方案。但CubeIDE的代码编辑体验不如Keil和VS Code编译速度也偏慢。还有一个组合是VS Code Keil Assistant插件 ARM GCC工具链。这个组合的编辑体验最好但配置起来稍微麻烦一点。如果你已经熟悉VS Code可以尝试这个方案。但纯新手我建议先用Keil MDK把流程跑通再考虑换编辑器。提示安装Keil MDK和芯片包时路径不要有中文和空格否则可能出现各种奇怪的编译错误。这个坑我踩过不止一次重装系统才解决。3. 从零搭建一个可复用的STM32工程模板3.1 为什么需要一个自己的工程模板很多人学STM32的方式是打开例程编译下载看现象然后换下一个例程。这种方式能让你快速看到效果但一旦要自己写代码就不知道从哪开始了。因为你没有自己的工程模板每次新建工程都要重新配置一堆东西效率极低。一个可复用的工程模板应该包含启动文件、系统初始化文件、外设驱动文件、以及合理的目录结构。启动文件是芯片上电后执行的第一段代码负责初始化堆栈、设置中断向量表、调用SystemInit函数、最后跳转到main函数。F103的启动文件有多个版本对应不同容量的芯片startup_stm32f103xb.s对应中容量64KB或128KB Flashstartup_stm32f103xe.s对应大容量256KB到512KB Flash。选错了启动文件编译能过但运行会出问题。系统初始化文件主要是system_stm32f103.c里面定义了SystemInit函数负责配置时钟。但CubeMX生成的代码会把时钟配置放在main函数里SystemInit只做最基础的设置。这两种方式都可以但你要清楚代码到底在干什么。3.2 手动搭建工程模板的完整步骤我以Keil MDK为例讲一下手动搭建工程模板的流程。这个流程你走一遍后面再建工程就是几分钟的事。第一步新建工程目录。我习惯的目录结构是这样的根目录下建四个文件夹——CMSIS、Library、User、Output。CMSIS放内核相关的文件Library放标准外设库文件User放自己的代码Output放编译输出文件。这种结构清晰后面换芯片或者加外设都方便。第二步复制必要的文件。从ST官方标准外设库或者CubeMX生成的代码里把以下文件复制到对应目录CMSIS目录下放core_cm3.h、core_cm3.c、stm32f10x.h、system_stm32f10x.c、system_stm32f10x.h以及启动文件startup_stm32f10x_hd.s根据你的芯片容量选。Library目录下放stm32f10x_gpio.c、stm32f10x_rcc.c、stm32f10x_usart.c等你需要的外设驱动文件以及对应的头文件。User目录下放main.c、stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h。第三步在Keil里新建工程选择芯片型号。注意如果你用的是F103C8T6选STM32F103C8如果是F103ZET6选STM32F103ZE。选完芯片后Keil会问你是否复制启动文件选“否”因为我们已经手动复制了。第四步添加文件分组。在Keil的Project窗口里右键Target选择Manage Components然后新建几个GroupCMSIS、Library、User。把对应的.c文件添加到各个Group里。注意启动文件也要添加到CMSIS组里虽然它是汇编文件但Keil能识别。第五步配置头文件路径。在Options for Target里选择C/C选项卡在Include Paths里添加CMSIS、Library、User三个目录的路径。不添加头文件路径编译时会提示找不到头文件。第六步添加全局宏定义。在C/C选项卡的Define里添加USE_STDPERIPH_DRIVER和STM32F10X_HD根据芯片容量选中容量是STM32F10X_MD大容量是STM32F10X_HD。USE_STDPERIPH_DRIVER告诉编译器使用标准外设库STM32F10X_HD告诉编译器芯片的容量类型这两个宏定义不写编译会报错。第七步配置调试器。在Options for Target的Debug选项卡里选择你用的调试器ST-Link Debugger或者J-Link/J-Trace Cortex然后点击Settings确认能识别到芯片。在Flash Download选项卡里勾选Reset and Run这样下载完程序后芯片会自动复位运行。第八步编译。如果一切配置正确编译应该零错误零警告。如果有错误大概率是文件路径不对、宏定义没写、或者启动文件选错了。注意标准外设库和HAL库是两套不同的库不能混用。标准外设库是早期的库代码直接操作寄存器效率高但可移植性差。HAL库是后来的库抽象层次更高可移植性好但效率略低。F103用标准外设库的教程最多但HAL库是趋势。建议先学标准外设库理解底层再转HAL库。3.3 用CubeMX生成工程模板的利弊分析CubeMX生成工程模板的好处是快。你只需要在图形界面上点几下配置好时钟和外设点击生成代码一个完整的工程就出来了。时钟树配置尤其方便输入晶振频率和目标主频CubeMX会自动计算分频和倍频系数避免手动计算出错。但CubeMX生成的代码有几个问题。第一代码冗余。CubeMX会生成大量初始化代码即使你只用到一个GPIO它也会把整个HAL库的初始化都生成出来导致编译出来的固件体积偏大。第二抽象层次太高。HAL库把寄存器操作封装成了函数调用你调一个HAL_GPIO_WritePin背后可能执行了几十行代码。对于F103这种资源有限的芯片有时候直接操作寄存器更高效。第三出了问题不好排查。HAL库的代码层层封装一旦某个外设不工作你要一层层往下查不如直接看寄存器直观。我的建议是用CubeMX生成时钟配置和引脚配置但外设驱动部分自己写。这样既省去了配置时钟的麻烦又能保持代码的精简和可控。4. 第一个程序从点灯到串口通信的实操记录4.1 GPIO点灯看似简单但暗藏玄机点灯是嵌入式的Hello World但F103的点灯和51单片机不太一样。51单片机直接给端口写0或1就行F103需要先使能GPIO时钟再配置引脚模式最后才能写数据。使能GPIO时钟是第一步。F103的每个外设都有独立的时钟开关不使能时钟外设不工作。GPIOA到GPIOE的时钟在RCC_APB2ENR寄存器里控制。用标准外设库的话调用RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)就行。配置引脚模式是第二步。F103的GPIO有八种模式输入浮空、输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、开漏复用、推挽复用。点灯用推挽输出就行。推挽输出的驱动能力强能直接驱动LED。开漏输出需要外部上拉电阻驱动能力弱一般用于I2C等需要线与的总线。配置引脚速度是第三步。F103的GPIO输出速度可以选2MHz、10MHz、50MHz。速度越高功耗越大EMI也越大。点灯用2MHz就够了没必要选50MHz。但如果你要输出PWM或者驱动高速信号就要选更高的速度。写数据是最后一步。用GPIO_SetBits(GPIOA, GPIO_Pin_5)把引脚拉高用GPIO_ResetBits(GPIOA, GPIO_Pin_5)把引脚拉低。注意F103的LED通常是一端接3.3V另一端接GPIO所以GPIO输出低电平时LED亮输出高电平时LED灭。这个逻辑和51单片机相反别搞混了。提示如果你点灯不亮先检查LED的极性。用万用表测一下LED两端电压如果GPIO输出低电平时LED两端有1.8V到2.2V的压降说明LED在亮只是亮度不够。如果压降为0说明GPIO没输出低电平检查时钟和模式配置。4.2 串口通信调试信息输出的命脉串口是嵌入式开发中最重要的调试手段。没有串口你只能靠点灯来判断程序运行状态效率极低。F103通常有3个USART和2个UARTUSART支持同步和异步通信UART只支持异步。一般用USART1因为它挂在APB2总线上时钟频率高波特率精度好。配置串口的步骤使能USART1和GPIOA的时钟配置PA9为复用推挽输出TXPA10为浮空输入或上拉输入RX配置USART1的波特率、数据位、停止位、校验位使能USART1最后使能接收中断如果需要接收数据。波特率计算是个容易出错的地方。F103的USART波特率计算公式是波特率 fCK / (16 * USARTDIV)其中fCK是USART的时钟频率USARTDIV是一个浮点数整数部分写在USART_BRR寄存器的高12位小数部分写在低4位。比如fCK是72MHz目标波特率是115200那么USARTDIV 72000000 / (16 * 115200) 39.0625。整数部分是39小数部分是0.06250.0625 * 16 1所以BRR寄存器的值应该是39 4 | 1 0x271。用标准外设库的话直接调用USART_Init函数传入波特率库函数会自动计算BRR的值。发送数据用USART_SendData函数发送前要等待TXE标志位置位发送完要等待TC标志位置位。接收数据用USART_ReceiveData函数接收前要等待RXNE标志位置位。如果开了接收中断在中断服务函数里读数据并清除标志位。注意串口通信的GND一定要共地。我见过有人只接了TX和RX没接GND结果收到的全是乱码。因为电平参考点不一致逻辑电平判断错误。共地是串口通信的基本要求别偷懒。4.3 定时器从延时到PWM的进阶F103的定时器资源很丰富有高级定时器TIM1和TIM8通用定时器TIM2到TIM5基本定时器TIM6和TIM7。高级定时器支持互补输出和死区控制适合驱动电机。通用定时器支持输入捕获、输出比较、PWM输出适合测频率、测占空比、调光调速。基本定时器只能定时适合做系统时基。定时器的配置步骤使能定时器时钟配置定时器预分频系数和自动重装载值配置计数模式使能定时器。预分频系数决定计数频率自动重装载值决定计数周期。比如72MHz的时钟预分频系数设为71计数频率就是72MHz / (71 1) 1MHz自动重装载值设为999计数周期就是1000个计数也就是1ms。所以定时器溢出频率是1kHz中断周期是1ms。PWM输出的配置稍微复杂一点。除了定时器的基本配置还要配置输出比较通道的模式为PWM模式设置比较值决定占空比使能输出比较通道最后使能定时器。占空比 比较值 / (自动重装载值 1)。比如自动重装载值是999比较值是300占空比就是30%。提示F103的定时器时钟不是固定的72MHz。APB1总线的定时器TIM2到TIM7时钟是APB1时钟的两倍APB2总线的定时器TIM1、TIM8时钟是APB2时钟。如果系统时钟是72MHzAPB1分频系数是2那么APB1时钟是36MHz但TIM2到TIM7的时钟是72MHz。这个细节在配置定时器时要注意不然算出来的定时周期会差一倍。5. 新手最容易踩的坑与排查思路5.1 烧录失败从“找不到芯片”到“Flash下载失败”烧录失败是新手遇到最多的问题。症状有很多种Keil提示“No Cortex-M Device found”或者“Flash Download failed”或者“Cannot access target”。原因也很多我按概率从高到低排一下。第一调试器接线错误。SWD需要接SWCLK、SWDIO、GND、3.3V四根线。SWCLK和SWDIO不能接反接反了找不到芯片。GND必须接不接GND信号没有参考点。3.3V可以不接调试器通常能从目标板取电但如果目标板功耗大最好接上。第二BOOT引脚状态不对。如果BOOT0接高电平芯片从系统存储器启动不运行Flash里的程序调试器可能找不到芯片。把BOOT0接低电平复位后再试。第三芯片被读保护了。如果之前烧过程序并且设置了读保护调试器无法访问Flash。需要用STM32CubeProgrammer或者ST-Link Utility解除读保护。解除读保护会擦除整个Flash所以之前程序会丢失。第四调试器固件版本太旧。克隆版ST-Link的固件版本可能和Keil版本不兼容导致找不到芯片。用ST-Link Utility升级调试器固件试试。第五芯片供电不足。如果目标板只靠调试器供电而调试器的3.3V输出电流有限通常只有100mA到200mA带不动板子上的外设芯片可能无法正常工作。给目标板单独供电再试。5.2 程序跑不起来从“卡在启动文件”到“HardFault”程序编译通过、烧录成功但跑起来没反应或者跑一会儿就死机。这种问题比烧录失败更难排查因为你看不到任何错误信息。如果程序卡在启动文件里通常是堆栈大小不够。启动文件里定义了Stack_Size和Heap_Size默认值可能偏小。如果你的程序用了比较大的局部数组或者递归调用堆栈会溢出导致HardFault。把Stack_Size改大一点比如从0x400改成0x800。如果程序跑一会儿就HardFault通常是数组越界、空指针访问、或者中断优先级配置错误。HardFault的排查方法在HardFault_Handler里加一个死循环然后连上调试器看程序停在哪个函数。或者用Keil的Event Recorder功能记录程序运行轨迹。如果程序完全不跑检查时钟配置。F103上电后默认使用内部8MHz RC振荡器如果程序里配置了外部晶振但晶振没起振系统时钟会切换失败程序可能跑飞。用示波器测一下晶振引脚看有没有波形。没有波形的话检查晶振焊接和负载电容。提示F103的晶振负载电容通常是20pF到30pF。如果电容选大了晶振起振慢或者不起振选小了频率偏差大。一般用22pF比较稳妥。如果晶振不起振可以先降低驱动电流或者换一个晶振试试。5.3 外设不工作从“时钟没使能”到“引脚复用冲突”外设不工作是另一个高频问题。症状是配置了外设但读不到数据或者输出不对。最常见的原因是时钟没使能。F103的每个外设都有独立的时钟开关不使能时钟外设的寄存器写不进去。比如你用GPIOA但忘了使能GPIOA的时钟那么GPIOA的配置寄存器全是默认值引脚不会按你的配置工作。第二个原因是引脚复用冲突。F103的引脚功能是复用的一个引脚可能同时是GPIO、USART、SPI、I2C的功能。如果你把PA9配置成了GPIO输出又想用它做USART1的TX那肯定不行。配置外设之前先查数据手册的引脚定义表确认引脚的功能和你的配置一致。第三个原因是中断优先级配置错误。F103的中断优先级分为抢占优先级和响应优先级数值越小优先级越高。如果两个中断的抢占优先级相同响应优先级不同高响应优先级的中断不能打断低响应优先级的中断。如果配置错了中断可能不触发或者触发顺序不对。第四个原因是外设的使能顺序不对。有些外设需要先配置再使能有些需要先使能再配置。比如USART要先配置好波特率、数据位、停止位再使能USART。如果先使能再配置配置可能不生效。5.4 常见问题速查表问题现象可能原因排查方法解决方法调试器找不到芯片接线错误、BOOT引脚状态不对、芯片读保护检查SWD接线、测BOOT0电平、用CubeProgrammer连接重新接线、BOOT0接低、解除读保护烧录成功但程序不跑时钟配置错误、堆栈溢出、启动文件选错测晶振波形、加大堆栈、检查启动文件换晶振、改Stack_Size、换对应容量的启动文件串口输出乱码波特率不对、GND没共地、时钟频率不对示波器测TX波形、检查GND、确认系统时钟改波特率、接GND、重新配置时钟GPIO输出不对时钟没使能、模式配置错误、引脚复用冲突读GPIO寄存器、查引脚定义表使能时钟、改模式、换引脚定时器不中断时钟没使能、NVIC没配置、中断标志没清除读定时器寄存器、检查NVIC配置使能时钟、配置NVIC、清除中断标志PWM无输出输出通道没使能、比较值不对、引脚复用没配置测引脚波形、读比较寄存器使能输出通道、改比较值、配置复用功能6. 从入门到进阶F103还能玩什么6.1 基于F103的实用小项目推荐点灯和串口只是开始F103能做的事情远不止这些。我推荐几个适合练手的小项目每个项目都能让你学到新的外设和编程技巧。第一个是超声波测距。用HC-SR04超声波模块配合定时器的输入捕获功能测量回波脉冲的宽度换算成距离。这个项目能让你学会定时器输入捕获、外部中断、以及简单的滤波算法。HC-SR04的Trig引脚接GPIO输出Echo引脚接定时器输入捕获通道。触发信号是10微秒的高电平然后Echo引脚会输出一个高电平脉冲脉冲宽度和距离成正比。距离 脉冲宽度 * 340 / 2 / 10000单位是厘米。第二个是DS3231高精度时钟。DS3231是I2C接口的实时时钟芯片精度比F103内部的RTC高得多。用I2C接口读取DS3231的时间寄存器显示在OLED屏幕上。这个项目能让你学会I2C通信、OLED显示、以及时间格式转换。DS3231的I2C地址是0x68时间寄存器从0x00开始依次是秒、分、时、星期、日、月、年都是BCD码格式。第三个是PWM调光台灯。用F103的定时器输出PWM驱动LED灯珠通过按键或者串口命令调节占空比实现调光。这个项目能让你学会PWM输出、按键消抖、以及简单的状态机编程。PWM频率建议在1kHz以上避免人眼看到闪烁。占空比从0%到100%分10档或者100档调节。第四个是Modbus RTU从站。用F103的USART配合RS485收发器实现Modbus RTU从站协议。这个项目能让你学会串口通信、RS485方向控制、以及协议解析。Modbus RTU的帧格式是地址 功能码 数据 CRC校验。从站收到帧后判断地址是否匹配然后执行对应功能码的操作最后返回响应帧。6.2 代码组织与工程管理经验写代码容易管代码难。我见过很多人的F103工程所有代码都堆在main.c里几千行改一个功能要翻半天。这种代码组织方式在项目小的时候没问题但项目一大就失控了。我的建议是按功能模块划分文件。比如LED相关的代码放在led.c和led.h里按键相关的放在key.c和key.h里串口相关的放在uart.c和uart.h里。每个模块对外提供几个接口函数内部实现细节不暴露。这样改一个模块不影响其他模块也方便代码复用。头文件里用条件编译防止重复包含。每个头文件开头写#ifndef __XXX_H然后#define __XXX_H结尾写#endif。这是C语言的标准做法不写的话头文件被多次包含会导致重复定义错误。全局变量尽量少用。全局变量多了代码的可读性和可维护性都会下降。如果确实需要全局变量用static修饰限制作用域在当前文件内。跨文件共享的变量通过函数接口访问不要直接extern。提示Keil MDK支持代码折叠和函数跳转善用这些功能能提高编码效率。在View菜单里打开Outline窗口可以看到当前文件的所有函数和变量点击就能跳转。在Edit菜单里打开Configuration勾选Show Line Numbers和Show Bookmarks方便定位代码。6.3 后续学习路径建议F103学会之后下一步可以往几个方向发展。如果你对物联网感兴趣可以学ESP32或者ESP8266这些芯片自带WiFi功能能做智能家居、远程监控之类的项目。F103可以作为传感器节点通过串口或者SPI和ESP32通信ESP32负责联网和云端通信。如果你对电机控制感兴趣可以学F103的高级定时器做BLDC或者PMSM的驱动。高级定时器支持互补输出和死区控制能直接驱动三相逆变桥。配合霍尔传感器或者编码器可以实现闭环调速。如果你对实时操作系统感兴趣可以在F103上跑FreeRTOS或者RT-Thread。F103的RAM虽然不大但跑一个精简的RTOS还是够的。RTOS能让你学会任务调度、信号量、消息队列等概念为后续做复杂项目打基础。如果你对FPGA感兴趣可以学Zynq或者K210这些芯片结合了ARM核和FPGA或者AI加速器能做图像处理、神经网络推理之类的应用。F103可以作为协处理器负责实时性要求高的控制任务。不管往哪个方向发展F103打下的基础都是通用的。GPIO、中断、定时器、串口、I2C、SPI这些外设的操作逻辑在别的芯片上也是类似的。把F103玩透了换别的芯片就是查手册、改配置的事。我个人在实际操作中的体会是学STM32最有效的方式是“做项目驱动学习”。不要按部就班地看教程、背寄存器而是定一个具体的目标比如做一个温湿度记录仪、一个蓝牙小车、一个红外遥控解码器然后围绕这个目标去查资料、写代码、调试。遇到问题解决问题学到的知识最扎实。板子买回来了就赶紧动手吧别让它吃灰。