ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32F103开发板上手实战:从开箱到外设避坑指南

STM32F103开发板上手实战:从开箱到外设避坑指南 1. 拿到板子先别急着点灯搞懂F103的脾气再说STM32F103这块板子在嵌入式圈子里基本就是“新手村第一只怪”。便宜、资料多、坑也经典几乎每个搞单片机的人都从它手里过过一遍。你手里这块开发板大概率是F103C8T6最小系统板或者ZET6那种大板子不管哪种核心都是ARM Cortex-M3内核72MHz主频64KB到512KB的Flash20KB的SRAM。这个配置放在今天看确实寒酸但用来学外设、跑裸机、理解中断和时钟树绰绰有余。我见过太多人板子买回来Keil装完新建工程编译通过然后卡在“烧录不进去”这一步。VS Code里编译成功却烧录失败这个热搜词不是白来的。问题往往不在代码而在调试器配置、启动模式跳线、或者芯片被读保护了。所以这篇东西不跟你扯虚的从开箱到跑通第一个工程再到几个典型外设的实操把F103开发板上手会遇到的坑一个个填平。适合谁看刚买板子的大学生、转行嵌入式的软件工程师、带毕设的倒霉蛋以及想从51过渡到32位机的老玩家。你不需要有STM32基础但至少得知道C语言指针和结构体是啥不然看寄存器操作会有点懵。2. 开发板到手后的第一轮硬件检查与工具链搭建2.1 板子上的跳线帽和供电先确认这三处拿到板子先别插USB。翻到背面或者侧面找三个东西BOOT0和BOOT1跳线、电源指示灯、调试器接口。BOOT0决定芯片从哪启动接GND是主Flash启动接VCC是系统存储器启动用于串口下载。正常跑程序BOOT0必须接地BOOT1随便。很多板子出厂跳线帽是悬空的你直接上电芯片找不到启动地址表现就是“程序烧进去了但不跑”。供电方面F103开发板一般有两种取电方式USB口直接供5V板载LDO转3.3V或者外部DC座供7-12V。如果你用ST-Link调试器供电注意调试器的3.3V输出电流有限带不动板载外设多的情况。我实测过某款C8T6最小板插上OLED和超声波模块后ST-Link供电直接掉到2.9V芯片反复复位。所以调试器只接SWDIO、SWCLK、GND三根线供电单独走USB这是最稳的接法。调试接口认准SWD模式四根线3.3V、GND、SWDIO、SWCLK。JTAG虽然也能用但占用引脚多F103上SWD和JTAG复用你如果开了JTAGPB3、PB4、PA15就不能当普通IO用。热搜里“stm32禁用jtag”就是这个原因。在代码里加这两句RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);这样JTAG关了SWD还能用PB3、PB4、PA15释放出来做普通GPIO。2.2 Keil、CubeMX、VS Code怎么选别纠结工具链这块新手最容易陷入“哪个IDE最好”的争论。我的建议很直接前期用Keil MDK 标准库或HAL库中期转VS Code PlatformIO或CubeCLT后期看项目需求。Keil的好处是资料多随便搜个“STM32F103 LED闪烁”出来的代码99%是Keil工程。安装Keil5之后必须装STM32F1xx_DFP芯片包不然新建工程找不到器件。热搜里“stm32芯片包安装”就是这一步。芯片包去Keil官网下或者用Pack Installer在线装注意版本别太新F1系列用2.3.0左右的包最稳。CubeMX用来生成初始化代码省得你手算时钟树。F103的时钟树不算复杂但新手容易把APB1和APB2的分频搞混。APB2最高72MHzAPB1最高36MHz定时器时钟要看APB预分频系数如果APB预分频是1定时器时钟等于APB时钟否则定时器时钟是APB时钟的2倍。这个规则在CubeMX里会自动算好但你得知道它为什么这么算。VS Code方案适合已经熟悉命令行的老手。装Cortex-Debug插件配OpenOCD或ST-Link GDB Server编译用Makefile或CMake。热搜里“stm32 vscode配置”和“vs code里编译成功却怎么也烧录不进开发板”往往是OpenOCD的配置文件选错了。F103用interface/stlink-v2.cfg和target/stm32f1x.cfg如果你用的是ST-Link V3接口文件要换成stlink-dap.cfg。烧录失败先看OpenOCD的输出它会告诉你到底是连不上芯片还是Flash锁了。2.3 新建工程的两种路子标准库和HAL库标准库新建工程的步骤建文件夹、拷库文件、加头文件路径、写main.c、配时钟、配GPIO。这套流程在CSDN上能搜到无数遍但坑在于库文件的版本。F103的标准库最后版本是V3.5.0网上有些工程用的是V3.0.0两者在stm32f10x.h里的宏定义不一样。你如果混用编译报错能报一屏。HAL库用CubeMX生成好处是跨系列移植方便坏处是代码臃肿一个GPIO初始化能给你生成几十行。但新手用HAL库不容易卡在时钟配置上因为CubeMX的图形界面把时钟树画出来了你点几下鼠标就能看到每个总线的频率。我个人的做法学习阶段用标准库因为寄存器操作更直观你能看到GPIO_SetBits(GPIOA, GPIO_Pin_5)背后到底写了哪些寄存器。做项目赶时间用HAL库CubeMX生成完直接写业务逻辑。3. 第一个工程从点亮LED到串口打印的完整实操3.1 LED闪烁背后的时钟和GPIO配置点亮LED是嵌入式界的“Hello World”但这里面藏着F103的时钟使能逻辑。F103的GPIO挂在APB2总线上用之前必须先开时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);然后配置GPIO模式。LED接在PA5上通常是推挽输出、50MHz速度GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure);推挽输出和开漏输出的区别推挽能输出高低电平驱动能力强开漏只能输出低电平高电平靠外部上拉。LED一般用推挽I2C总线用开漏。延时函数别用delay_ms那种循环空跑F103的SysTick定时器可以配成1ms中断在中断里递减计数。热搜里“stm32延时函数delay卡死”通常是因为中断优先级配置不对SysTick中断被其他高优先级中断阻塞了。检查NVIC_PriorityGroupConfig的设置确保SysTick的抢占优先级足够高。3.2 串口配置与printf重定向串口是调试利器。F103的USART1挂在APB2USART2/3挂在APB1。配置步骤开时钟、配GPIOTX推挽复用、RX浮空输入、配USART参数波特率、数据位、停止位、校验位、使能USART。RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); USART_Cmd(USART1, ENABLE);printf重定向要重写fputc函数int fputc(int ch, FILE *f) { while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET); USART_SendData(USART1, (uint8_t)ch); return ch; }注意Keil里要勾选“Use MicroLIB”否则printf会卡在半主机模式。VS Code里用newlib的话重定向函数名是_write。3.3 烧录失败的五个常见原因和排查顺序热搜里“vs code里编译成功却怎么也烧录不进开发板”和“load error: flash”这两个问题我按排查顺序列一下现象可能原因排查方法连不上芯片SWD线接反或接触不良万用表测SWDIO对地电阻正常几百欧能连上但烧录报错Flash被读保护ST-Link Utility里解除读保护烧录成功但不运行BOOT0跳线不对确认BOOT0接地烧录到一半失败调试器供电不足板子单独供电提示Flash算法错误Keil工程器件选错确认选的是STM32F103C8/ZET6ST-Link Utility是个好工具能直接看芯片的Flash内容、选项字节、读保护状态。如果芯片被锁了用ST-Link Utility的“Target - Option Bytes”把Read Out Protection改成Disabled然后全片擦除。4. 进阶外设实操定时器、超声波和USB虚拟串口4.1 定时器模式PWM输出和输入捕获测频率F103有4个通用定时器TIM2-TIM5和2个高级定时器TIM1、TIM8。通用定时器做PWM输出配置步骤开时钟、配GPIO为复用推挽、配时基结构体预分频、自动重装载值、计数模式、配输出比较结构体PWM模式、占空比、极性、使能。预分频和重装载值的计算假设系统时钟72MHz你要1kHz的PWM频率公式是72M / ((prescaler1) * (period1)) 1000。取prescaler71则period999。占空比用TIM_SetCompare1(TIM3, value)设置value从0到999对应0%到100%。输入捕获测频率超声波模块的Echo引脚接定时器通道配置为输入捕获模式上升沿触发。捕获到上升沿时记录CCR1值下降沿时再记录一次两次差值乘以计数周期就是高电平时间。热搜里“stm32定时器捕获测频率”和“stm32超声波测距”就是这个套路。注意输入捕获的中断里要清除标志位否则会反复进中断。4.2 USB虚拟串口F103的USB设备开发F103C8T6有USB外设但只能做全速设备12Mbps。做虚拟串口CDC需要ST的USB库或者用CubeMX生成。热搜里“stm32 如何做usb设备”和“stm32 usb虚拟串口发送数据”是很多人的痛点。关键点USB时钟必须是48MHz。F103的USB时钟来源是PLLPLL输出72MHzUSB预分频1.5分频得到48MHz。CubeMX里把USB时钟源选PLL然后确认时钟树里USB那栏显示48MHz。CDC虚拟串口的代码结构USB中断处理、CDC类请求处理、数据收发端点。ST的USB库有点老但能用。如果你用HAL库CubeMX勾选USB Device和CDC生成代码后直接调用CDC_Transmit_FS发送数据。注意发送前要判断上一次发送是否完成否则数据会丢。4.3 超声波测距的完整实现HC-SR04超声波模块Trig接GPIO输出Echo接GPIO输入或定时器输入捕获。用GPIO轮询的方式简单但精度低GPIO_SetBits(GPIOA, GPIO_Pin_1); delay_us(10); GPIO_ResetBits(GPIOA, GPIO_Pin_1); while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) 0); TIM_SetCounter(TIM2, 0); while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) 1); uint16_t time TIM_GetCounter(TIM2); float distance time * 0.017;0.017是声速340m/s除以2再换算成cm/us的结果。实际用的时候要加温度补偿声速随温度变化v 331.4 0.6 * T。用输入捕获的方式精度更高但配置复杂。Echo接TIM的通道上升沿捕获时清零计数器下降沿捕获时读CCR值。注意捕获中断里要切换触发极性。5. 常见问题速查与避坑经验5.1 编译报错和烧录问题的快速定位报错信息原因解决undefined symbol库文件没加或路径不对检查C/C选项卡的Include PathsFlash Download failed调试器配置错Options - Debug - Settings里选对Flash算法No target connectedSWD线序错确认SWDIO、SWCLK、GND、3.3V对应HardFault_Handler空指针或数组越界用调试器看LR和PC寄存器程序跑飞中断优先级冲突检查NVIC分组和抢占优先级HardFault是新手最怕的其实定位方法很简单在HardFault_Handler里加死循环调试时看调用栈。或者用__asm(bx lr)把LR的值打出来查LR指向的地址。5.2 标准库和HAL库混用的坑标准库和HAL库不能混在一个工程里因为它们的寄存器定义和中断向量表结构不一样。你如果从网上拷了一个标准库的LED代码又用CubeMX生成了HAL库的初始化编译能过但运行必挂。判断方法看stm32f10x.h和stm32f1xx_hal.h是否同时存在。5.3 开发板挂载Ubuntu和网络更新程序热搜里“开发板挂载ubuntu”和“zu开发板怎么通过网络更新程序”跟F103关系不大那是Zynq和ZU系列的事。F103没有MMU跑不了Linux。如果你想学Linux开发板F103只能当个协处理器通过串口或SPI跟主控通信。热搜里“k210与stm32通讯”就是这个场景K210跑视觉F103跑控制两者串口对接。网络更新程序对F103来说要么用IAP在应用编程通过串口或CAN接收固件包写到Flash的APP区要么加个ESP8266模块通过WiFi下载固件。IAP的关键是中断向量表偏移APP区的代码要重映射中断向量NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x4000);0x4000是APP区的起始地址偏移具体看你的Flash分区。5.4 基于STM32的毕业设计选题建议热搜里“基于stm32的毕业设计”和“stm32项目”是学生党刚需。F103能做的毕设方向智能家居温湿度继电器WiFi、平衡车MPU6050PID电机驱动、鱼缸控制器热搜里“stm32鱼缸”、报站系统热搜里“stm32报站程序完整代码”。选题目注意三点工作量够、有实物演示、代码自己能讲清楚。别选太偏的答辩老师问“你这个创新点在哪”你说“用了STM32”那基本就凉了。6. 从F103到更复杂的开发板学习路径怎么走F103玩熟了之后下一步通常是F407Cortex-M4带FPU和DSP指令或者H750M7480MHz。再往上就是Linux开发板比如imx6ull、T113、RK3588。热搜里“3588开发板”和“t113开发板”就是这类。从单片机到Linux的跨度在于操作系统、设备树、驱动模型、多进程。你在F103上写的裸机代码在Linux里就是一个字符设备驱动。如果对无线感兴趣ESP32-S3是个好跳板。热搜里“esp32-s3开发板硬件解析与lorawan实战指南”就是LoRaWAN方向。ESP32-S3自带WiFi和蓝牙双核240MHz用ESP-IDF开发跟STM32的HAL库思路类似但API更现代。RoboMaster开发板C型热搜里“robomaster开发板c型数据手册”是F407为主控跑RT-Thread或FreeRTOS适合学实时操作系统。从裸机到RTOS的关键是理解任务调度、信号量、消息队列。你在F103上可以用FreeRTOS练手C8T6的20KB RAM跑FreeRTOS够用但任务别开太多3个以内。我个人在实际操作中的体会是F103最大的价值不是性能而是让你把嵌入式的基本概念都踩一遍时钟树、中断、DMA、ADC、通信协议。这些概念在更高级的芯片上是一样的只是寄存器名字变了。所以别急着换板子把F103的每个外设都手写一遍寄存器操作比用CubeMX生成十遍代码都有用。最后再分享一个小技巧买板子的时候顺手买一个ST-Link V2调试器和一个USB转TTL模块这两个东西能帮你省下大量排查硬件问题的时间。
返回列表