ARTICLE DETAIL

资讯详情

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

STM32调试与开发避坑指南:从下载失败到外设驱动全解析

STM32调试与开发避坑指南:从下载失败到外设驱动全解析 1. 下载调试那些事从“连不上”到“乱跑飞”玩STM32的人十个里有八个是在Debug下载阶段被劝退的。剩下的那两个基本都经历过“明明编译通过一烧就废”的至暗时刻。我刚接触STM32那会儿用的还是Keil MDK 4的时代芯片是STM32F103C8T6。有次给板子烧程序突然弹出Error: Flash Download failed - Cortex-M3一脸懵。后来排查到最后原因竟然是Keil里芯片型号选成了F1系列的其它型号导致Flash算法不匹配。这种事情现在看起来低级但当时确实卡了一下午。这篇文章不打算给你讲一堆流水账就按我自己踩过、也帮别人踩过的坑来梳理每个问题都会把“为什么会这样”说清楚再给解决办法尽量让你不重蹈覆辙。1.1 Keil5兼容C51和STM32到底怎么共存很多新手是玩过51单片机再转STM32的电脑上装了Keil C51装Keil MDK的时候发现两个能共存但SDK包却经常不对。原因很简单这两个其实是不同的工具链产品C51用的是A51编译器MDK用的是ARMCC/ARMClang安装目录也不同。但很多人在装MDK时没有注意“安装到与原C51不同的目录”结果就出现互相覆盖的诡异问题。我的建议是Keil5安装路径尽量分开比如C51装到C:\Keil_v5MDK装到D:\Keil_MDK装完MDK后Pack Installer里勾选对应芯片的Pack51单片机的项目用51的打开方式STM32项目用MDK打开。注意打开工程文件时确认选择的IDE是MDK而不是C51否则会提示“Invalid target”。另外MDK5的Pack芯片支持包下载经常慢到怀疑人生。解决办法是在Pack Installer里设置代理或者直接去Keil官网下载对应芯片Pack离线包自己手动安装。用国内镜像或百度网盘分享的Pack包也能省事不少但记得核对版本。1.2 ST-LINK连接失败SWD调试接口居然被禁用“ST-LINK连接失败”这个报错很多人以为是线接错了或者ST-LINK坏了。其实还有一种非常隐蔽的情况你在代码里把SWD引脚关了。怎么关掉的很多工程模板默认会开启GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE)目的是释放PA13/PA14/PA15和PB3/PB4这五个引脚当普通IO用。但我见过有人为了多要几个IO口把这行代码加了进去结果烧录完第二次就再也连不上ST-LINK了。更坑的是有的板子BOOT0本来就是低电平复位后还是跑用户代码SWD口被禁用后调试器完全识别不到芯片。解决办法有几种如果芯片内部Flash里程序还能被擦除用“ST-LINK Utility”连接后选择Target - Erase Chip全片擦除。但此时如果SWD已经被禁用Utility一样连不上。按住复位键点击连接按钮在连接瞬间松开复位键。利用这个时序可以把已经关掉SWD的芯片拉回调试状态。如果还不行把BOOT0拉高重新上电让芯片从系统存储区启动里面是出厂固化的Bootloader这时SWD口会重新释放再用ST-LINK Utility擦除即可。这个坑的根源其实是**“引脚复用和调试功能的冲突”**。串口、USB、SPI这些外设都可以重映射引脚但SWD不是你想关就关的一旦关了程序里又没有预留恢复逻辑就会把自己锁死。我的经验是只要不是特别缺IO口SWD引脚都别去动。真要动就要保证板子上有一个可恢复的方案比如串口IAP、BOOT跳线或者外置的脱机烧录器。1.3 FLASH下载出错Program Algorithm和芯片ID不匹配这个报错我当年也撞过。报错信息中有No Algorithm found for: 08000000H或Error: Flash Download failed翻译一下就是Keil不知道拿什么算法去烧你的Flash。常见原因Debug下拉框里没选对芯片型号。芯片Pack没装全Flash算法里没有对应型号。芯片本身是“国产兼容型号”虽然内核是Cortex-M0/M3但Flash扇区大小、起始地址和ST原厂不一致。尤其是第三点用国产替代片比如GD32、HK32、MM32的时候ST-LINK的算法是按ST芯片的Flash扇区划分去擦写的一旦遇到非ST的Flash就会出现写入校验失败。此时需要在Flash Download页面添加对应厂家的算法或者借助原厂提供的烧录工具来解决。另外经常有人问“怎么知道芯片固件已经被烧过”用ST-LINK Utility能读到Flash内容全0x00说明是空的全0xFF说明是擦除状态。不过对于刚接触的来说更重要的是记住一点先连上再擦除最后再编程。别一上来就点“Download”把“Reset and Run”勾上下载完自动复位跑。2. 工程模板和库的选择一个烂模板毁掉整个周末下载问题解决后接下来陪着你时间最长的就是工程了。STM32类热词里有一种很典型“新建工程模板”“标准库和HAL库的区别”“报错Load axf Failed”。这些都指向同一个核心工程结构混乱 库版本不匹配。2.1 标准库和HAL库到底选哪个这个问题放到现在标准库基本可以被看作是“祖宗级别”的存在了。但还有很多人执着于标准库原因是网上教程多、历史代码多、寄存器透明适合学习。标准库现在官方已经停止支持如果你用的是F1/F4系列老芯片还能玩得转但新出的G0、L4、H7系列标准库根本没有对应版本。HAL库对新手要友好一些它的API抽象度高拿HAL_UART_Transmit来说一个函数就把串口发送的所有寄存器操作包了。缺点是这些函数比较啰嗦经常有回调、句柄、中断回调函数初看非常抽象。我的选型建议很直接学习原理、研究寄存器用标准库或直接操作寄存器毕业设计、产品开发、快速上手用HAL库做OS级、协议栈级需求用HAL库加DSP库加CMSIS-RTOS配套文件多但省事。但不管用哪个新建工程模板一定要保证“可用、可跑、可调”。一个完整的STM32工程模板至少有启动文件startup_M35xxx.s对应具体芯片型号系统初始化system_stm32xxx.c时钟配置文件stm32xxx_hal_conf.h或者标准库的stm32f10x_conf.h分散加载文件.sctMDK会自动管理新手别乱改主循环里至少点亮一颗LED确保整条链路是通着的。2.2 “Load axf Failed”到底是谁的错报错内容一般是load D:\\stm32 project\\Objects\\project.axf Error: Flash Download failed - Cortex-M3有些人是编译都没过项目生成不了.axf文件但Load动作还是会执行于是报这个。有些人是链接时没有生成调试信息或者输出路径改了导致Keil找不到.axf。处理办法先看编译输出窗口有没有0 Error(s)没有的话说明是下载问题有的话先解决编译。在Options for Target - Output里勾选Create HEX File确认Select Folder for Objects路径是存在的。在Utilities - Settings - Flash Download里确认勾选了Reset and Run并且选择的是“Use Debug Driver”而不是“Use External Tool”。说实话这种问题九成是工程配置问题不是芯片坏了。遇到类似报错先别急着换板子按“路径 - 编译输出 - 下载算法 - 复位方式”的顺序排查比我当时乱按一通要高效得多。3. 时钟系统一切外设的心跳之源STM32的坑里时钟绝对是“排第一的隐藏BOSS”。很多人延时不对、串口乱码、定时器频率不对查到最后都是时钟配置出了问题。3.1 时钟树从HSE到AHB/APB的层层分频初学的时候看STM32时钟树图满眼都是PLL、AHB、APB1、APB2根本分不清谁是谁。这里我用自己的话给你理顺一下HSE外部高速时钟芯片外部接8MHz晶振或25MHz进来的信号最稳定通常作为主时钟源HSI内部高速时钟芯片内部自带的8MHz RC振荡器上电默认用它跑精度一般PLL锁相环把HSE或HSI倍频得到SYSCLK系统时钟比如8MHz外部晶振通过PLL×9得到72MHz主频AHB总线时钟SYSCLK经过AHB预分频后给GPIO、Flash、DMA这些APB1总线时钟AHB再分频得到低速外设挂在上面最大36MHzF1APB2总线时钟AHB再分频高速外设挂在上面最大72MHzF1。时钟树配错最常见的后果主频不是72MHz而是8MHz或者36MHz甚至系统卡死。因为外部晶振没起振时PLL不会锁定系统会退回HSI但代码里如果强制等待PLL就绪就会出现死等看现象就是程序跑飞、仿真卡在SystemInit里。3.2 Delay函数卡死多半不是Delay的锅热词里有一项叫“stm32延时函数delay卡死”这个问题我太熟了。很多人用HAL库的HAL_Delay发现程序卡死第一反应是晶振坏了。但真正原因往往是SysTick中断被其他中断抢占或屏蔽了。HAL_Delay的实现原理是设置SysTick计数值然后不断查询计数标志。如果这时候你恰好关了这个中断或者SysTick的优先级设置比某些外设中断还低在外设中断里又调用了HAL_Delay就会死循环——因为SysTick的更新一直被外部中断打断。另外一个卡死原因是HAL_Delay不能用在中断回调里尤其是需要长时间等待的。比如串口空闲中断里调用HAL_Delay(10)如果SysTick中断优先级比串口低等待串口新数据进来时音乐会一直卡住。解决方法是把SysTick中断优先级设为最低或者用HAL_GetTick() while轮询代替HAL_Delay或者在中断里换个基于NOP或DWT的忙等延时。顺便提一下DWT延时这是很多人忽略的好工具用CoreDebug-DEMCR使能DWT然后读DWT-CYCCNT这样能实现微秒级精确延时非常适合超声波测距这种需要看回波宽度的场景。热词里“stm32超声波测距”就在这里踩坑——HC-SR04要求至少10us的TRIG高电平很多人的10us延时不准就是因为系统时钟没有及时更新到DWT。3.3 主频和定时器、串口波特率的三角关系这个问题特别体现“为什么时钟树重要”。你做串口通信波特率要9600或者115200STM32内部是用USART的时钟源除以波特率寄存器BRR的值得到实际波特率。如果主频变了BRR不变波特率就偏了。9600波特率偏100Hz可能还能收115200偏差超过2%就乱码。具体到F1系列APB1的最大频率是36MHz所以USART2/3、TIM2~7都挂在APB1上APB2最大72MHzUSART1、TIM1/TIM8这些挂在这里。如果配置USART1时用的是RCC_APB2PeriphClockCmd但按APB1的36MHz去算波特率出来的结果是错的。这就是为什么一直强调“先看时钟树再算波特率”。我自己调试时习惯在串口助手上先发0x55或0xAA看回显是不是0x55或0xAA。如果收到的是0x5D之类的基本就是波特率对不上或时钟频率不对。再用逻辑分析仪测TX引脚的电平频率立刻能看出实际波特率跟预设差多少。4. 定时器不只是定时还是测频率、解码、PWM的万能砖STM32的定时器是外设里最能体现“模式”概念的。热词“stm32定时器模式”“stm32定时器捕获测频率”“stm32编码器程序”都指向同一个叫TIM的神奇外设。它的功能不只是“延时”它可以定时中断输出PWM输入捕获测脉宽、测频率编码器接口模式接正交编码器霍尔传感器接口模式触发ADC采样。4.1 输入捕获测频率为什么低频率测不准很多人用定时器输入捕获测方波频率程序写完了测1kHz没问题测10Hz就数字乱跳。原因是一个方波周期内两次相邻上升沿之间的计数值可能太小采样间隔太短计数器分辨率根本不够。比如你用72MHz的时钟源、不分频计数频率就是72MHz测1kHz信号时每个周期计72000个值很准测100kHz信号时只有720个数还能看测1MHz信号时只有72个计数值误差自然就大了。解决办法就是根据被测频率动态调整预分频或者使用多个通道交替捕获、取平均。测频率更推荐的方案其实是一个通道测一段固定时间内的上升沿个数用另一个定时器做时间基准。这相当于把定时器当作“闸门计数器”比单次捕获要稳。热词“stm32定时器捕获测频率”被搜得那么多说明这条路坑多但也是刚需。4.2 编码器接口模式两相正交解码的“隐藏绝活”编码器模块大家基本都听过AB相、Z相、计数方向、倍频系数。STM32的定时器编码器模式最大的优势是不用额外IO中断靠硬件自动加减计数。初始化时配置为TIM_ENCODERMODE_TI1或TIM_ENCODERMODE_TI1andTI2配合TIM_ICPolarity_Rising就能根据两路脉冲相位关系判断方向自动增减CNT寄存器值。常见坑有两个第一个是GPIO复用没配对。TIM2的编码器通道通常接PA0/PA1TIM3接PA6/PA7如果你随意指定了两个IO程序跑起来却计不了数多半是引脚没选对。这个时候最好看一下芯片数据表的AFIO复用功能列把引脚对到对应的定时器通道上。第二个是读取计数器前没有锁存导致在电机高速转动时计数器值跳变。多字节读取有原子性问题建议在读取前关定时器中断、或者用TIM_GetCounter连续读两次差值大就重新读。另外编码器Z相零位信号经常被忽略但它对回原点非常关键能省掉一整套机械限位开关。4.3 PWM输出的一些小细节PWM输出看似简单但有几个容易被忽略的细节频率计算PWM频率 定时器时钟 / ((PSC1) * (ARR1))。如果ARR设为0整个周期就是0极容易导致芯片的引脚输出高频抖动。初始极性如果一开始PWM极性是高在还没做额定的占空比赋值之前电机或者LED会直接全开。初始化时务必先设占空比0再启动PWM。互补输出和死区驱动H桥时如果用到TIM1的高级定时器需要配置死区时间。死区时间太小上下桥臂会直通短路死区时间太大音圈电机或开关电源会啸叫。通常设置为1~2us先小后大用示波器观察插入死区后的切换波形。5. 串口通信调试的第一入口也是流氓问题的重灾区串口是STM32开发者最频繁使用的通信接口但它的坑也不少。热词里“stm32串口通信”“stm32串口调试pid”“stm32 usb虚拟串口发送数据”全都指向这里。5.1 printf重定向的两种方式与隐藏问题标准做法是用MicroLIB提供的fputc重定向int fputc(int ch, FILE *f) { while ((USART1-SR USART_FLAG_TXE) 0); USART1-DR (uint8_t)ch; return ch; }然后把编译选项里“Use MicroLIB”打上勾。如果你用HAL库也可以这样写int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xFFFF); return ch; }这个有个坑HAL_UART_Transmit在每发一个字符时都要检查状态标志如果串口断线、对端不读缓冲区满了会卡死。调试时看着没问题一旦跑生产测试接错线程序就死在printf里了。所以重要的代码里尽量少在中断上下文调用printf必须用的话加超时保护或者用DMA。5.2 串口中断和接收不定长数据标志位的两种流派处理串口不定长接收老工程师常用两种方式空闲中断IDLE一帧数据结束后硬件会触发IDLE中断此时就知道一包数据收完了。但IDLE中断与字节中断共享同一个中断向量要区分UART_IT_IDLE和UART_IT_RXNE否则会反复进中断却什么也不处理。DMA 空闲中断DMA把串口数据直接搬到内存空闲中断时读DMA剩余计数器hc-hdmarx-Instance-NDTR得到这次收了几个字节。这个方案吞吐率高适合大数据量传输。我在这块踩过的一个很经典的坑是接收缓冲区用200字节DMA一次传完判断接收长度时误用了HAL_UART_Receive_DMA的返回值而不是读NDTR导致每次收到的都是0字节。后来改成读DMA计数寄存器一切就正常了。这个细节特别容易被人忽视希望你别再掉进去。5.3 USB虚拟串口枚举失败看着像硬件问题“STM32 USB虚拟串口”这个热词点出了一个很现实的需求现在笔记本都没有DB9串口用USB转串口芯片CH340、CP2102当然可以但USB虚拟串口USB CDC更节省成本而且能顺便做USB自定义HID。虚拟串口的坑主要在时钟精度和D上拉电阻。USB协议要求数据速率精度在±0.25%以内所以强烈建议使用外部晶振不要用内部RC振荡器。很多人在F103上用自带USB但怕麻烦没接外部晶振然后发现电脑一直提示“无法识别的USB设备”。一旦把晶振换成8MHz或16MHz外部晶振基本立刻修复。另外在USB的D线上通常需要1.5k上拉电阻有些芯片比如STM32F103内部带了这个上拉电阻但需要软件PULLUP位开启有些则必须板级外接。枚举失败的排查顺序是先看原理图有没有外接上拉再看USB时钟配置是否正确最后查驱动是否装了ST的VCP驱动。6. 外设驱动与常用模块那些教科书上没教的细节这部分汇集了大量热词OLED、I2C、BH1750、DS3231、ESP8266、超声波、按键模块。看起来杂乱但底层逻辑其实是同一个外设驱动的关键不在发送指令而在于时序和电平判断。6.1 I2C总线和OLED的软硬件矛盾BH1750光强传感器、OLED屏这些模块基本都是I2C接口而STM32的硬件I2C因为芯片厂商标注和库函数实现历史上曾被诟病很多老工程师直接放弃硬件I2C改用软件模拟I2C。用GPIO口来模拟SCL和SDA代码虽然“土”但稳。硬件I2C坑的地方在于需要配置I2C_ClockSpeed、I2C_DutyCycle、I2C_Ack、I2C_AcknowledgedAddress这几个参数很多人漏配了ACK位导致发送后总线挂死。多主机或与不同电平外设混接时需要外接上拉电阻。很多模块板子自带4.7k上拉但如果你自己搭板不加这两个电阻I2C波形就是一团糊。软件模拟I2C的注意事项反而好掌握开漏模式、上拉使能、起始条件和停止条件的延时别太短。我一般把延时设在1~2us左右然后拿逻辑分析仪看波形。OLED屏在I2C模式下还有个细节地址引脚通常标SA0决定设备地址是0x78还是0x7A。很多人把地址写错屏幕上就白屏。驱动不亮时先把I2C地址扫描一遍看挂在总线上的设备到底回应哪个地址比盲改代码高效。6.2 ESP8266这类Wi-Fi模块串口透传不是“接上就能用”用STM32控制ESP8266做Wi-Fi透传是常见玩法。但ESP8266模块有它自己的启动时序模块上电需要大约几百毫秒到几秒的串口响应时间如果你在STM32上电后立刻发AT指令大概率会丢掉模块的“ready”或者“AT”响应。我踩过的坑还有电平问题ESP8266的串口电平是3.3V但有些模块套件上集成了电平转换电路有些没有。如果你直接用5V的TTL串口去接模块轻则通信乱码重则烧模块。接之前一定看下模块型号和外围电路。另外一个看着很“低级”但经常发生的坑STM32的TX要接ESP8266的RXESP8266的TX要接STM32的RX交叉连接。很多人做杜邦线连接时习惯性两头对齐结果RX对RX、TX对TX直接全军覆没。每次连线前默念一遍“交叉交叉”。6.3 按键消抖和ADC采样时间基础中的基础却是最多人问的“stm32按键模块电路设计”和“stm32 ad采样时间”都在热词表里。按键消抖最朴实的方法是扫描延时再确认但实际项目中更推荐用定时器中断来做“状态机消抖”10ms扫描一次连续两次读到同一状态再确认变化。这样不阻塞主循环而且还带自动长按、短按判断能力。ADC采样时间的坑在“采样时间太短导致阻抗不匹配”。STM32的ADC采样其实是开关电容结构内部有一个采样电容外部信号源的内阻如果太大采样时间内电容充不满读数就会偏低。解决方法是增大ADC_SAMPLETIME_239CYCLES_5这类采样时间或者在ADC引脚前面加一个100nF的电容。这对于测电池电压、光敏电阻这类高阻信号非常关键。你说你是做“stm32鱼缸”的拿ADC去测水位传感器如果你采样时间配短了读数飘得跟股票一样那种挫败感我特别能体会——把采样时间调到最大试试波形瞬间就稳了。7. 综合项目里的“系统级”问题从合上电到OTA到了这个层面你不再只调试某个外设而是开始面对“系统能不能一起工作”这件事。热词里“基于stm32的毕业设计”“两轮差速小车stm32控制”“stm32 ota”“基于stm32 ethercat”“stm32控制伺服电机485”基本都能归结到几个系统集成的痛点上。7.1 一个工程里多个外设先初始化谁很多人上来就把外设初始化写得密密麻麻结果莫名奇妙的bug此起彼伏。我的习惯是先给系统分层时钟树初始化谁都不先跑先把主频确定GPIO基础初始化关键引脚先设为确定状态尤其LED和电机使能脚防止默认电平乱输出中断控制器NVIC配置把每个外设的中断优先级排好避免嵌套混乱低速外设再高速外设I2C、串口、SPI这类先测试通再开定时器、ADC、DMA。比如做“两轮差速小车”你肯定同时用到左右轮编码器、电机PWM、串口遥控、OLED显示。如果初始化顺序颠倒比如PWM输出前没有把电机使能引脚拉低轮子就会在系统上电瞬间猛冲一下。很多小车项目“一上电就疯跑”根源往往不是算法问题而是初始化顺序和电平状态的问题。7.2 RS485控制伺服和EtherCAT这类工业总线“stm32控制伺服电机485”现在逐渐变成热门需求。RS485是半双工总线所以方向控制引脚DE/RE的控制时机非常重要发送完一帧数据后要立刻把方向切回接收否则对方回的响应你全收不到或者把自己发的数据回环到自己的接收里。我当年在485通信上踩的最深的坑是波特率配置对了、方向也切换了、接线也是好的但就是收不到回复。后来用示波器一看A/B线上没有接终端电阻或者终端电阻匹配不当导致电平飘逸信号反射严重。虽然短距离传输不接也能聊胜于无但一旦距离超过几米或者是总线挂多台设备120欧终端电阻就非常关键。至于EtherCAT这里不多展开简单提一句STM32本身不带EtherCAT从站控制器一般是外接LAN9252这类从站芯片然后通过SPI接口通信。调试的难点更多在“ESC配置”和“邮箱通信”而不是STM32自身。如果你搜这个热词是想做运动控制总线从站建议先去把LAN9252的数据手册读懂再研究是跑官方驱动还是自己二次封装。7.3 OTA升级别把Bootloader和App的地址搞乱OTA热词被搜这么频繁说明现在很多人期待“远程升级”这个功能。但分两个程序、两个Flash区域地址表一旦错乱设备就会变砖。标准方案是Bootloader放在Flash起始地址比如0x08000000App放在0x08008000偏移32KB。App编译时要改三个地方IROM1起始地址改为0x08008000大小为剩余空间中断向量表偏移寄存器SCB-VTOR 0x08008000如果用的是HAL库需要把系统时钟初始化保留起来避免App重新初始化外设时出现“时钟冲突”。变砖后的恢复就要靠Bootloader里的串口或USB下载功能了。所以做OTA时我一般第一步就会写一个极其简单、打死都不会坏的串口Bootloader确保App再怎么乱都能回到工厂状态。这一步省了不知道多少返工成本。8. 常见问题速查表与调试思路整理最后把这几年遇到的典型问题整理成一张速查表方便你直接定位问题现象可能原因快速排查办法ST-LINK连接失败SWD引脚被禁用、连接器接触不良、目标板供电不足逐个测量SWDIO、SWCLK、GND、3V3按住复位连一下下载时报Flash算法错误Keil里芯片型号或者算法不对、国产芯片Flash兼容性问题核对芯片型号换成原厂工具或国产芯片对应算法程序跑飞/仿真卡死时钟配置不对、外部晶振未起振、HAL_Delay死等先检查晶振和外部时钟仿真里看SystemInit是否卡住串口乱码波特率误差大、主频不对、USB转串口线地未共地用逻辑分析仪量TX波形换低速波特率对比定时器测频率不准预分频没调整、计数器溢出未处理、输入捕获配置错误用已知信号源对测检查溢出标志位编码器读数异常引脚复用错、通道映射错、计数器溢出处理缺失核对数据手册引脚复用表旋转编码器逐度观察CNT变化OLED白屏I2C地址错、上电时序不对、SCL/SDA接反用I2C扫描程序打印检测地址检查模块供电和上拉电阻ADC值跳变采样时间过短、线缆引入噪声、参考电压不稳增大采样周期加RC滤波电容用短引线OTA升级失败地址没偏移、中断向量表没重定位、App程序直接覆盖Bootloader先单独验证App能直接从新地址启动再测App跳转ESP8266不响应AT模块启动时序未等待、TX/RX接反、波特率不匹配上电后延时2秒再发AT用USB转串口直接测模块调试这件事说到底拼的是两样东西排查顺序和耐心。排查顺序对了一半的坑其实都能提前避开。比如遇到问题先量电压、再看波形、再查配置而不是上来就改代码乱试。我个人做了这么多年项目最大的体会是不要相信任何外设模块“默认就能工作”的说法。每个模块上电后都要验证通讯每根线都要按信号流向检查每个外设时钟都要按数据手册例程配置ST的参考手册翻得再勤快也不为过。那些看起来神乎其神的“一次性点亮”背后都是早就把坑填平了的经验。如果你现在也被某个诡异bug折磨着不妨把问题拆成“硬件问题”和“软件问题”两块然后用排除法一片片切。对照上面的表先走一遍实在走不通再用示波器、逻辑分析仪去抓信号——工具一上手问题往往就藏不住了。
返回列表