ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32F103开发板入门实战:从点灯到串口打印的完整学习路径

STM32F103开发板入门实战:从点灯到串口打印的完整学习路径 1. 拿到板子先别急着点灯STM32F103开发板入门全景拆解STM32F103开发板到手的那一刻很多人第一反应是插上USB线看灯亮不亮。这个动作没错但如果你打算长期玩下去最好先花二十分钟把整块板子的脉络摸清楚。STM32F103这颗芯片属于ARM Cortex-M3内核主频72MHz片上Flash从16KB到1MB不等SRAM从6KB到96KB封装形式有LQFP48、LQFP64、LQFP100等多种规格。市面上常见的“最小系统板”通常搭载的是STM32F103C8T664KB Flash、20KB SRAM、LQFP48封装而“战舰”“精英”这类综合开发板则多用STM32F103ZET6512KB Flash、64KB SRAM、LQFP144封装。你手里是哪一种直接决定了后续能跑多大的工程、能挂多少外设。为什么强调先摸清板子因为STM32的生态虽然庞大但不同板子的引脚分配、晶振频率、供电方案、调试接口都不一样。比如有的板子外部高速晶振是8MHz有的是12MHz还有的干脆用内部RC振荡器HSI跑。晶振频率不同SystemInit函数里的PLL倍频参数就得跟着改否则串口波特率会偏得离谱你调半天以为是代码问题其实是时钟树没配对。再比如调试接口有的板子只引出了SWDSWDIOSWCLK两根线有的把JTAG的二十针全引出来了。你要是买了个只支持SWD的下载器插上JTAG排线发现没反应那就尴尬了。这块板子能做什么往小了说点灯、按键、串口打印、定时器闪烁、PWM调光、ADC采电压、I2C读传感器、SPI驱动屏幕、CAN总线通信这些都是STM32F103的“基本功”。往大了说基于STM32的毕业设计、工业控制板、数据采集终端、电机驱动器、甚至简易的USB设备比如自定义HID键盘、虚拟串口F103都能扛下来。适合谁来学电子类专业的学生、嵌入式入门的工程师、想从51单片机升级到32位MCU的爱好者以及需要快速验证硬件方案的创客。只要你愿意动手这块几十块钱的板子能带你走很远。我见过太多人买了板子之后跟着视频点了个灯然后就不知道下一步干什么了。问题出在“没有项目牵引”。单纯学外设学一个忘一个但如果你心里有一个小目标比如“做一个能通过串口上报温度的桌面小助手”那学习路径就完全不一样了。所以这篇内容我会按照“整体设计思路→核心细节→实操过程→问题排查”的顺序把STM32F103开发板入门的完整链路讲透中间穿插我这些年踩过的坑和总结的技巧。2. 整体学习路径与工具链选型为什么这样搭配最省心2.1 开发环境的三条路线对比STM32开发环境大致分三条路线Keil MDK、STM32CubeIDE含CubeMX、以及VSCode开源工具链。这三条路线没有绝对的好坏但适用场景差别很大。Keil MDK是传统嵌入式工程师最熟悉的工具编译器是ARMCC现在叫ARM Compiler 6对STM32的支持非常成熟调试器兼容性好J-Link、ST-Link、DAP-Link都能用。缺点是界面老旧代码补全弱而且商业版收费虽然很多人用社区版或评估版。如果你在学校或者公司里周围人都在用Keil那跟着用最省事遇到问题问人也方便。STM32CubeIDE是ST官方推出的免费IDE底层是EclipseGCC集成了CubeMX配置工具。它的最大优势是“图形化配置引脚和外设一键生成初始化代码”。对于新手来说不用手写时钟树配置、不用查寄存器手册点几下鼠标就能把UART、I2C、SPI配好大大降低了入门门槛。缺点是Eclipse系IDE比较吃内存代码补全和索引速度一般而且生成的代码结构比较“重”想深度优化需要自己裁剪。VSCode开源工具链是近几年越来越流行的方案。用VSCode写代码配合Cortex-Debug插件、OpenOCD、arm-none-eabi-gcc可以实现编译、下载、调试全流程。优点是编辑器轻快、插件丰富、Git集成好适合习惯现代开发工具的年轻人。缺点是需要自己搭环境Makefile或CMakeLists要自己写对新手不太友好。不过一旦搭好后续开发效率很高。我的建议是纯新手先用STM32CubeIDE或者Keil MDKCubeMX的组合把外设跑通建立信心等你有了一定基础再折腾VSCode方案。不要一上来就追求“最酷的工具链”那样容易在环境配置上卡三天热情直接耗尽。2.2 下载器与调试器的选择STM32F103支持JTAG和SWD两种调试接口。SWD只需要两根信号线SWDIO、SWCLK加电源和地接线简单占用引脚少是首选。常见的下载器有ST-Link V2、J-Link OB、DAP-Link。ST-Link是ST官方的价格便宜几十块钱配合STM32CubeIDE或Keil都很顺。J-Link性能更强支持更多芯片但正版价格高市面上很多是盗版固件的“J-Link OB”用是能用但驱动兼容性偶尔出问题。DAP-Link是开源的CMSIS-DAP协议Keil和OpenOCD都支持性价比不错。这里有个坑要注意STM32F103的PA13和PA14默认就是SWDIO和SWCLK但PA15、PB3、PB4默认是JTAG的JTDI、JTDO、JTRST。如果你想把这三个引脚当普通GPIO用必须在代码里禁用JTAG、只保留SWD否则配置了也不生效。具体操作是开启AFIO时钟然后调用GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE)。这个坑我当年调一个SPI屏幕的时候踩过PB3死活不出波形查了半天才发现是JTAG占着。2.3 芯片包与标准库/HAL库的取舍Keil MDK需要安装对应的Device Family PackDFP也就是常说的“芯片包”。STM32F1系列的包在Keil官网或者ST官网都能下载。安装之后新建工程时才能选到STM32F103的器件。如果你用的是Keil5还要注意安装ARM Compiler的版本老工程用AC5新工程建议AC6。库的选择上ST提供了标准外设库Standard Peripheral LibrarySPL和HAL库两种。标准库是早期F1系列的主流代码直接操作寄存器效率高资料多很多经典教程比如正点原子、野火的早期视频都是基于标准库。HAL库是ST后来推的抽象层次更高跨系列移植方便配合CubeMX用很爽但代码体积大、执行效率略低。对于F103入门我建议先学标准库因为你能更清楚地看到“配置一个GPIO要动哪些寄存器”基础打牢之后再用HAL库提高开发速度。当然如果你直接跟着CubeMX的节奏走从HAL库入门也没问题只是遇到问题时排查起来需要补的底层知识更多。3. 核心细节解析从时钟树到外设初始化的关键要点3.1 时钟树配置系统心跳的源头STM32F103的时钟源有三个HSI内部8MHz RC、HSE外部晶振通常8MHz、LSI内部40kHz RC给看门狗用。系统时钟SYSCLK最高72MHz来源可以是HSI、HSE或者PLL倍频输出。最常见的配置是HSE 8MHz → PLL 9倍频 → 72MHz SYSCLK → AHB不分频 → APB1 36MHz → APB2 72MHz。为什么APB1是36MHz而APB2是72MHz因为APB1挂的是低速外设USART2/3、I2C、SPI2、定时器2~7等APB2挂的是高速外设USART1、SPI1、ADC、GPIO、定时器1/8等。APB1的最大频率限制是36MHzAPB2可以到72MHz。如果你把APB1也设成72MHz芯片可能跑不起来或者外设工作异常。配置时钟树的代码在system_stm32f10x.c里关键宏是SYSCLK_FREQ_72MHz。如果你用CubeMX时钟树是图形化拖拽的但你要知道每个节点的含义。比如PLL的输入分频HSE/2和倍频系数x9以及各个总线的预分频器AHB/APB1/APB2。这些参数决定了外设的实际工作频率进而影响波特率、定时器周期、PWM频率的计算。注意如果你用的是没有外部晶振的最小系统板只能靠HSI跑。HSI的精度不如HSE做串口通信时波特率误差可能偏大高波特率比如115200以上容易丢数据。解决办法是降低波特率或者换一块带晶振的板子。3.2 GPIO的八种模式与实战选择STM32的GPIO有八种模式输入浮空、输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、开漏复用、推挽复用。新手最容易懵的是“什么时候用推挽什么时候用开漏”。推挽输出可以输出高电平和低电平驱动能力强适合直接驱动LED、继电器等。开漏输出只能输出低电平高电平需要外部上拉电阻适合I2C总线、多个设备共享信号线的场景。复用功能当引脚被外设如USART_TX、SPI_SCK占用时要配置成复用模式否则外设信号出不来。举个例子点灯用推挽输出按键输入用上拉或下拉输入取决于按键接法I2C的SDA和SCL用开漏复用外部上拉ADC采集用模拟输入。这些选择不是随便定的背后是电路原理决定的。比如I2C为什么要开漏因为总线上可以挂多个主从设备任何一个设备拉低总线都能被其他设备检测到如果都用推挽一个输出高一个输出低就会短路。3.3 中断优先级与NVIC配置STM32F103的中断优先级分抢占优先级和响应优先级通过NVIC嵌套向量中断控制器管理。抢占优先级高的中断可以打断正在执行的低抢占优先级中断响应优先级只在同时挂起时决定谁先执行不能打断。优先级数值越小优先级越高。配置中断时先调用NVIC_PriorityGroupConfig()设置优先级分组决定几位给抢占、几位给响应。比如NVIC_PriorityGroup_2表示2位抢占、2位响应抢占优先级范围0~3响应优先级范围0~3。然后在外设初始化时调用NVIC_Init()填入具体优先级。常见的坑串口接收中断和定时器中断同时用如果优先级设得不好可能出现串口数据丢失或者定时器抖动。我的经验是对实时性要求高的中断比如电机控制PWM给高抢占优先级通信类中断给低抢占优先级但响应优先级可以适当调高保证数据不丢。4. 实操过程从新建工程到串口打印的完整链路4.1 新建标准库工程的目录结构不管你用Keil还是CubeIDE一个清晰的工程目录结构能省很多事。我习惯这样组织Project/ ├── CMSIS/ # 内核相关文件 ├── Library/ # 标准外设库或HAL库 ├── User/ │ ├── main.c │ ├── stm32f10x_it.c │ └── ... ├── Hardware/ # 自己写的外设驱动 │ ├── led.c │ ├── uart.c │ └── ... ├── Start/ # 启动文件、system_stm32f10x.c └── Output/ # 编译输出在Keil里新建工程时先把启动文件startup_stm32f10x_hd.s或md.s取决于芯片容量加到Start组再把标准库的.c文件按功能加到Library组最后把自己的代码加到User和Hardware组。头文件路径要在“Options for Target → C/C → Include Paths”里全部加上否则编译时报“找不到头文件”。启动文件的选择很关键STM32F103C8T6是中容量Medium Density用startup_stm32f10x_md.sZET6是大容量High Density用startup_stm32f10x_hd.s。选错了会导致中断向量表对不上程序跑飞。4.2 串口初始化的参数计算与代码实现串口是调试中最常用的外设。以USART1为例它挂在APB2上时钟72MHz。波特率计算公式是波特率 fPCLK2 / (16 * USARTDIV)假设要115200波特率则USARTDIV 72000000 / (16 * 115200) 39.0625。整数部分是39小数部分是0.0625。STM32的BRR寄存器用12位表示整数、4位表示小数所以小数部分0.0625 * 16 1。因此BRR (39 4) | 1 0x271。标准库的USART_Init()函数会自动帮你算这个值你只需要填USART_InitStructure.USART_BaudRate 115200。但你要知道背后的原理否则遇到波特率偏差时不知道怎么调。初始化步骤开启GPIOA和USART1时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE)配置PA9为复用推挽输出TXPA10为浮空输入或上拉输入RX配置USART参数波特率、8位数据、1位停止、无校验、无硬件流控、收发模式调用USART_Cmd(USART1, ENABLE)使能串口如果需要中断接收配置NVIC并使能USART_IT_RXNE发送一个字节的函数可以这样写void UART_SendByte(USART_TypeDef* USARTx, uint8_t data) { while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) RESET); USART_SendData(USARTx, data); }注意USART_FLAG_TXE是“发送数据寄存器空”标志不是“发送完成”标志。如果要确保数据真正从移位寄存器发出去了要等USART_FLAG_TC。在切换RS485收发方向或者进入低功耗前必须等TC置位。4.3 用SysTick做精准延时标准库的delay.c通常用SysTick定时器实现。SysTick是Cortex-M3内核自带的一个24位递减计数器时钟源可以是HCLK或HCLK/8。配置成1ms中断一次在中断里对一个全局变量递减就能实现delay_ms()和delay_us()。关键点SysTick的LOAD值 系统时钟频率 / 1000 - 1对于1ms。72MHz时LOAD 72000 - 1 71999。如果时钟源选HCLK/8则LOAD 9000 - 1 8999。我见过有人用空循环做延时结果编译器优化等级一变延时就不准了。SysTick是硬件定时器不受编译器优化影响精度有保障。但要注意在中断服务函数里不要调用delay_ms()因为SysTick中断优先级如果低于当前中断会导致死等。4.4 点亮第一颗LED并串口输出状态把上面几块拼起来初始化LED引脚推挽输出、初始化串口、配置SysTick。主循环里让LED每隔500ms翻转一次同时通过串口打印“LED ON”和“LED OFF”。int main(void) { LED_Init(); UART_Init(115200); SysTick_Init(); while(1) { GPIO_SetBits(GPIOB, GPIO_Pin_5); printf(LED ON\r\n); delay_ms(500); GPIO_ResetBits(GPIOB, GPIO_Pin_5); printf(LED OFF\r\n); delay_ms(500); } }printf要重定向到串口需要重写fputc()函数int fputc(int ch, FILE *f) { UART_SendByte(USART1, (uint8_t)ch); return ch; }并在Keil的“Options for Target → Target → Use MicroLIB”勾选MicroLIB否则printf可能无法正常工作。5. 常见问题与排查技巧实录5.1 下载失败与芯片识别问题现象Keil或STM32CubeProgrammer提示“No target connected”或“Cannot access target”。排查思路检查SWD接线SWDIO、SWCLK、GND、3.3V是否接对有没有虚焊。检查板子供电有些最小系统板需要外部供电只靠ST-Link的3.3V可能带不动。检查BOOT引脚BOOT0和BOOT1的电平决定启动模式。BOOT00从Flash启动BOOT01从系统存储器启动用于串口下载。如果BOOT0被拉高芯片不会运行你的程序。检查芯片是否被读保护如果之前烧过程序并开启了读保护需要先解除保护才能重新下载。降低SWD速度在下载器设置里把时钟频率从4MHz降到1MHz甚至更低有时候长排线或干扰会导致高速通信失败。独家技巧如果SWD死活连不上可以试“Connect under Reset”模式。在Keil的Debug设置里把Reset方式改成“HW RESET”或“SYSRESETREQ”然后按住板子复位键点击下载再松开复位键。这个操作能让芯片在复位状态下被下载器接管绕过一些启动代码导致的引脚占用问题。5.2 串口乱码与波特率偏差现象串口助手收到一堆乱码或者偶尔正确偶尔错误。排查思路确认波特率、数据位、停止位、校验位是否和代码一致。检查晶振频率如果板子是8MHz晶振但代码里按12MHz算PLL系统时钟就不是72MHz波特率自然偏。检查APB2预分频USART1挂APB2如果APB2被分频到36MHz波特率会差一倍。检查串口线TX接RXRX接TXGND必须共地。有些USB转TTL模块的TX/RX标注是反的要仔细看。独家技巧用示波器或者逻辑分析仪抓一下TX引脚波形测量一个字节的时间。115200波特率下一个位是8.68微秒一个字节10位是86.8微秒。如果实测偏差超过3%说明时钟配置有问题。没有仪器的话可以发固定的0x55二进制01010101用串口助手看收到的数据如果收到0xAA或0x2A基本能判断是波特率偏差。5.3 中断不触发或反复触发现象配置了定时器中断但进不去或者进去了出不来程序卡死。排查思路确认NVIC使能了对应的中断通道NVIC_Init()里NVIC_IRQChannel要填对比如TIM2_IRQn。确认外设的中断使能位开了比如TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE)。确认在中断服务函数里清了中断标志比如TIM_ClearITPendingBit(TIM2, TIM_IT_Update)。忘了清标志会导致中断反复触发。检查中断函数名是否和启动文件里的向量表一致比如TIM2_IRQHandler拼写错误会导致默认死循环。独家技巧如果中断进不去先在NVIC_Init()之后读一下NVIC-ISER寄存器看看对应位是否置1。再读外设的SR寄存器看看中断标志是否置位。这两个都对了中断一定会触发。如果还不行检查优先级分组是否配置正确有些库函数在NVIC_PriorityGroupConfig()之前调用NVIC_Init()会出错。5.4 CAN通信突然连不上现象CAN总线之前通信正常突然收不到数据了。排查思路检查CAN收发器的供电和使能引脚TJA1050之类的收发器需要5V供电如果供电不足总线电平不对。检查终端电阻CAN总线两端需要各接一个120欧姆的终端电阻总共60欧姆。如果电阻没接或者接多了通信距离短的时候可能勉强能用但抗干扰能力差。检查波特率CAN的波特率由APB1时钟和分频系数决定如果APB1频率变了波特率也跟着变。检查错误状态读CAN的ESR寄存器看看是位错误、格式错误还是ACK错误。如果是ACK错误说明总线上没有其他节点应答可能是对方掉线了。独家技巧CAN总线在强干扰环境下容易进入错误被动状态。可以在初始化时配置自动离线恢复ABOM并在主循环里定期检查CAN_GetFlagStatus(CAN1, CAN_FLAG_BOF)如果总线关闭重新初始化CAN。5.5 常见问题速查表问题现象可能原因快速排查方法下载器连不上芯片SWD接线错误、BOOT0拉高、读保护检查接线、BOOT电平、用Connect under Reset串口乱码波特率偏差、晶振频率不符、TX/RX接反测波形、核对时钟树、交换TX/RXLED不亮GPIO模式错、引脚号错、限流电阻过大用万用表测引脚电平、查原理图中断不触发NVIC未使能、中断标志未清、函数名错读ISER和SR寄存器、核对启动文件定时器周期不对预分频和重装载值算错、时钟频率不对重新计算ARR和PSC、确认APB频率ADC采样值跳动大参考电压不稳、采样时间太短、模拟输入未配置加滤波电容、增加采样周期、检查GPIO模式I2C读不到数据上拉电阻缺失、地址错误、时序问题测SDA/SCL电平、用逻辑分析仪抓时序SPI屏幕花屏时钟极性/相位错、速率过高、接线过长降低SPI速率、核对CPOL/CPHA、缩短排线6. 从点灯到项目如何用一个小目标牵引学习6.1 选一个“够得着”的项目学STM32最怕“东一榔头西一棒槌”。今天看串口明天看ADC后天看CAN每个都跑了一遍例程但合在一起就不会了。我的建议是选一个综合性的小项目把常用外设串起来。比如“基于STM32的桌面环境监测站”用DHT11或DS18B20采温湿度用OLED或LCD显示用串口上报数据用按键切换页面用Flash保存历史数据。这个项目不大但涵盖了GPIO、定时器、串口、I2C/单总线、SPI、Flash读写、中断等多个知识点。再比如“STM32超声波测距小车”超声波模块测距舵机扫描方向电机驱动前进后退串口蓝牙遥控。这个项目涉及定时器输入捕获测超声波回波、PWM输出舵机和电机、UART通信、GPIO控制。做完这个你对STM32的定时器系统会有非常深的理解。6.2 代码分层与模块化新手写代码容易把所有逻辑堆在main.c里几百行下去自己都看不懂了。正确的做法是分层硬件驱动层LED、UART、Timer、I2C、中间件层协议解析、数据处理、应用层业务逻辑。每个外设一个.c和.h文件对外提供简洁的接口。比如LED模块// led.h void LED_Init(void); void LED_On(void); void LED_Off(void); void LED_Toggle(void); // led.c void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStructure); }这样应用层只需要调LED_Toggle()不用关心是哪个引脚、什么模式。以后换板子只改led.c就行应用层不动。6.3 版本管理与代码备份我强烈建议从第一天就用Git管理代码。哪怕你只是自己学Git也能帮你记录每次改动出问题了可以回退。在工程目录下git init然后git add .、git commit -m 点灯成功。每次跑通一个功能就提交一次时间长了你会发现这是救命稻草。另外Keil的工程文件.uvprojx和编译输出Output文件夹建议分开管理。编译输出可以加到.gitignore里不然仓库里全是.o和.hex文件又大又乱。6.4 善用官方文档与社区资源STM32F103的参考手册Reference Manual和芯片数据手册Datasheet是最终权威。参考手册讲外设怎么用数据手册讲引脚定义和电气参数。遇到问题先翻手册比在网上搜半天靠谱。ST官网还有大量的应用笔记Application Note和例程CubeMX里也能直接生成各外设的初始化代码这些都是宝贵的学习资源。社区方面国内的电子论坛、开源社区有很多STM32的项目分享。遇到具体问题时搜索“STM32F103 外设名 问题关键词”通常能找到类似案例。但要注意网上的代码质量参差不齐有些是抄来抄去的老代码不一定适合你的芯片型号和库版本。最好的验证方法还是自己读手册、看寄存器。7. 进阶方向USB设备、RTOS与通信协议7.1 STM32F103做USB设备STM32F103自带USB 2.0全速设备控制器可以枚举成HID键盘、虚拟串口CDC、大容量存储MSC等。做USB HID键盘的思路是配置USB时钟48MHz来自PLL初始化USB外设实现HID描述符和报告描述符然后在主循环里检测按键并发送报告。ST提供了USB FS Device库里面有HID、CDC、MSC的例程可以直接拿来改。坑点USB的48MHz时钟必须精确F103的USB时钟来自PLLPLL时钟源是HSE 8MHz时配置成8MHz / 2 * 12 48MHz。如果HSE不是8MHzUSB可能枚举失败。另外USB的DPPA12需要外部上拉电阻1.5kΩ到3.3V有些板子已经内置了有些没有需要自己加。7.2 移植FreeRTOS当你的项目越来越复杂裸机的前后台架构主循环中断就不够用了。FreeRTOS是一个轻量级的实时操作系统在STM32F103上跑绰绰有余。移植步骤把FreeRTOS的Source文件加到工程配置FreeRTOSConfig.h实现SysTick和PendSV中断处理创建任务和队列。FreeRTOS的好处是任务调度、延时、同步机制都是现成的你可以把不同的功能拆成独立任务比如LED任务、串口任务、传感器任务互不干扰。但要注意中断服务函数里调用FreeRTOS的API必须以FromISR结尾比如xQueueSendFromISR()否则会导致调度异常。7.3 常用通信协议Modbus与CANopen工业场景里STM32经常要跑Modbus RTU或者CANopen。Modbus RTU基于串口实现简单适合和PLC、触摸屏通信。CANopen基于CAN总线有标准的对象字典和PDO/SDO机制适合多节点分布式控制。这两个协议都有开源实现比如FreeMODBUS、CANopenNode可以移植到STM32F103上。移植Modbus RTU的关键是串口中断和定时器配合串口接收中断收字节定时器判断帧间隔3.5个字符时间然后解析帧。CANopen则需要配置CAN的过滤器、中断并实现心跳和节点保护。8. 一些过来人的经验与建议买开发板只是开始真正决定你能不能学出来的是“持续动手”和“项目牵引”。我见过太多人板子买回来吃灰也见过有人用一块几十块的最小系统板做出了完整的毕业设计。差别不在于板子贵不贵而在于你有没有把每个外设都亲手调一遍有没有遇到问题死磕到底。调试的时候示波器和逻辑分析仪比万用表有用得多。一个几百块的逻辑分析仪比如Saleae兼容款能抓UART、I2C、SPI、CAN的时序很多“代码看起来没问题但就是不通”的情况一抓波形就真相大白。如果预算有限至少买一个USB转TTL模块和一个ST-Link这两个是入门必备。代码写不出来的时候先画流程图。把数据流和控制流画清楚再写代码比对着屏幕发呆效率高十倍。还有别怕读英文手册STM32的文档虽然厚但每个外设的章节结构都很清晰看多了就习惯了。最后分享一个小技巧新建工程时先把串口和SysTick调通后面所有调试都靠串口打印信息。没有串口输出你就像在黑屋子里找东西全靠猜。有了串口你能看到变量值、程序走到哪一步、外设寄存器是什么状态排查效率天差地别。
返回列表