ARTICLE DETAIL

资讯详情

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

STM32入门理论框架:从时钟树到外设模型,别急着买板子

STM32入门理论框架:从时钟树到外设模型,别急着买板子 很多朋友加我微信第一句话都是想学STM32买哪块板子合适代码从哪抄我的回答通常是你先别急着下单也别急着复制粘贴先把STM32理论这块地基搞清楚。这里说的理论不是让你啃完上千页芯片手册而是把系统架构、时钟树、外设模型、中断机制这几根大梁立起来。我见过太多人拿着例程能跑一旦让他换一个引脚、改一个波特率、加一个定时器就当场卡死根子就是只记住了代码没建立起理论模型。这篇文章就当是我陪你把STM32的骨架过一遍把那些热点问题一次性说透。1. STM32到底学的是什么先建立整体框架1.1 芯片家族与内核别一上来就挑花眼STM32是个大系列不是一款芯片。我经常跟新手说STM32的灵魂是ARM的Cortex-M内核ST做的事情是在这个内核外面铺上各种外设GPIO、定时器、串口、ADC、DMA、USB等等。同一个内核配上不同的外设组合和主频就变成了F1、F4、H7这些家族。拿最常见的三条产品线来比STM32F103Cortex-M3内核72MHz主频F1系列是入门神板教材最多能搜到的例程也最全适合用来学原理。STM32F407Cortex-M4内核168MHz主频带FPU浮点运算单元和DSP指令做电机控制、简易信号处理都够用。STM32H743Cortex-M7内核480MHz主频属于高性能旗舰适合做视频、工业互联、复杂算法这些重活。选型有个特别实际的建议新手不要一上来就追高配。F103的资源在2025年的今天看确实不豪华但学习价值一点没缩水——你把它吃透了换F4、H7也就是换个包、改个配置的事。反过来如果你在H743上靠HAL库的图形化配置把代码堆了起来但不知道时钟树怎么走的、DMA怎么就触发了那换个芯片照样会傻眼。外设是多变的而那套“看总线、看时钟、看中断、看数据通路”的思维方法永远不变。1.2 系统架构与存储器映射看手册先找地图芯片手册动辄上千页第一次翻开谁都会头大。我建议你拿到任何一款STM32先翻到“System architecture”和“Memory map”这两节这就像是拿到了一张城市地图。举个例子F103内部不只是一条总线而是有I-Code总线去Flash取指令、D-Code总线去Flash取常量、System总线访问SRAM和外设、DMA总线外设与内存间搬运数据这些总线通过总线矩阵仲裁访问。为什么要关心这个因为当年F103的12位ADC有个著名的“串门”现象——DMA在搬运数据时如果总线仲裁配置不当采样结果会带毛刺。你要是连DMA走的是哪条总线都不懂遇到这种问题就只会换电阻、加滤波电容白白浪费时间。存储器映射也得记几个关键地址F103的Flash从0x0800 0000开始SRAM从0x2000 0000开始外设寄存器从0x4000 0000开始。GPIOA在F1系列挂在APB2总线上基地址是0x4001 0800到了F4系列则移到了AHB1总线基地址变成0x4002 0000。同样的GPIO在不同系列里“搬家”了这就是为什么F1的代码移植到F4不能直接编译。把这些地址记清楚你在Debug窗口里盯着寄存器看电平变化的时候才不会被一串十六进制吓退。还有一个关键概念是总线分级AHB是主干道APB1和APB2是支路。F103里APB1是低速支路上限36MHz挂串口2/3、定时器2到7这些APB2是高速支路72MHz挂GPIO、串口1、高级定时器TIM1。外设挂在哪个桥直接决定了它的工作时钟上限。很多新人以为只要把主频配置成72MHz所有外设都是72MHz——这是大错。APB1下面的外设如果不单独处理默认就只有36MHz串口波特率算出来的误差会让你在115200以下看着正常一上460800全是乱码。2. 时钟树芯片的“心跳”设计2.1 时钟来源与PLLMHz到底从哪来时钟是嵌入式开发里最容易被忽略、也最容易出问题的一环。STM32的时钟来源有四个HSE外部高速晶振板上一般焊8MHz、HSI内部高速RC振荡器约8MHz精度差、LSE外部低速晶振32.768kHz给RTC用、LSI内部低速RC约40kHz给独立看门狗用。系统主时钟通常走这条路8MHz的外部晶振HSE进入PLL锁相环经过倍频得到高频再由PLL输出作为系统时钟SYSCLK。F103把8MHz在PLL里乘以9就得到了72MHzF407可以配到168MHzH743的PLL链路更复杂PLLM分频、PLLN倍频、PLLP分频但思路一模一样。为什么很多开发板上晶振都选8MHz而不是别的高频晶振就是因为这个频率配合手册推荐的PLL配置能直接得到72MHz或168MHz这些标准主频整数计算误差最小。我自己调试时有个习惯凡是程序一开始就跑飞、串口乱码、定时器时间不对第一件事永远是进Debug看一眼RCC_CR寄存器确认HSEON位有没有变成1、PLLRDY位有没有置位。很多网上下的工程模板SystemInit函数被改了或者根本没跑芯片一直用HSI的内部8MHz跑外设还按72MHz去配置结果就是延时函数卡死、波特率全错。这就好比你按每天8小时的工作量排计划结果公司实际只给你半天时间全乱套。2.2 分频链与总线时钟配置错误最容易卡死从SYSCLK到外设中间还有一道分频链SYSCLK经过AHB预分频得到HCLK内核、内存、SysTick用HCLK再分别经过APB1预分频和APB2预分频得到PCLK1和PCLK2。F103常见的配置是SYSCLK72MHzAHB不分频HCLK72MHzAPB1二分频PCLK136MHzAPB2不分频PCLK272MHz。标准库对应的写法是这样RCC_DeInit(); RCC_HSEConfig(RCC_HSE_ON); RCC_WaitForHSEStartUp(); RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); RCC_PLLCmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) RESET); RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div2); RCC_PCLK2Config(RCC_HCLK_Div1);这段代码值得你一行一行读而不是从工程模板里当黑盒复制。这里藏着一个ST官方设置的精妙点当APB1预分频系数不是1的时候挂在APB1上的定时器时钟会自动变成PCLK1的两倍。也就是说PCLK1明明是36MHzTIM2到TIM5却是按72MHz跑的。这是ST为了保证定时器能用高精度计数而特意加入的逻辑。你要是不知道这个规则后面计算PWM频率和捕获频率的时候分母一填错输出波形和预期差一整倍。3. 外设理论基础GPIO、定时器与串口3.1 GPIO的8种工作模式为什么一个引脚能亮灯也能读按键GPIO是所有人第一个接触的外设但很少有人把8种模式讲清楚。STM32的每个引脚F1系列在配置寄存器里由CNF和MODE两个位域控制组合出四种输入和四种输出输入有浮空、上拉、下拉、模拟输出有开漏、推挽、复用开漏、复用推挽。简单理解就是推挽输出是引脚被内部一个强上拉管和一个强下拉管交替驱动点亮LED、驱动蜂鸣器这些“有劲儿”的活就靠它开漏输出是只有下拉管工作高电平靠外部上拉电阻拉起来适合I2C这类多设备共享总线的场景也方便和不同电压的器件对接复用模式则是把引脚的控制权交给串口、定时器这些外设比如USART的TX引脚就要配成复用推挽输出而不是普通推挽。有次一个朋友告诉我串口调不出来我一看代码TX引脚配成普通推挽输出数据只能看到乱码就是不懂复用模式的含义。输入这边按键模块电路设计是最常见的应用。按键一端接地、另一端接GPIO配置上拉输入平时引脚读到高电平按下读到低电平。直接在悬空引脚上读按键是最容易犯的错误浮空输入的电平完全取决于引脚附近的感应干扰手一靠近就翻转消抖都救不回来。F4系列的GPIO配置换成了MODER、OTYPER、OSPEEDR、PUPDR四个寄存器相比F1的CNF/MODE组合更直观但模式概念同根同源学F1再迁移过去半天就能上手。这里也顺便回答那个高频问题“为什么我的程序在A板子上正常换到B板子就不动”——先查两件事一是板的晶振是不是8MHz二是你的GPIO有没有用到被调试接口占用的特殊引脚。PA13/PA14是SWD下载引脚PA15/PB3/PB4是JTAG引脚你要是把它们当普通IO用下载器一连就打架程序自然跑得不正常。3.2 定时器从延时到捕获与编码器定时器是STM32外设里最值钱的一块也是理论密度最大的部分。F1家族分三档基本定时器TIM6/TIM7只有计数功能通用定时器TIM2到TIM5加了输入捕获、输出比较和PWM高级定时器TIM1/TIM8又加了互补输出和死区控制可以直接驱动电机逆变桥。理解定时器其实只需要一个模型预分频器PSC把定时器时钟分频后给计数器CNT计数计数值和自动重装载值ARR相等时产生更新事件同时清零重新开始。定时时长公式是t (PSC1) × (ARR1) / 定时器时钟。以72MHz时钟、要出1ms中断为例可以配置PSC7172分频计数频率变成1MHz、ARR999计1000个数1MHz除以1000正好就是1000次每秒。为什么PSC不是给个72因为要保证计数器精度到微秒级你要是PSC719720分频、ARR99定时时长一样但分辨率只有10微秒后面做输入捕获就吃亏了。输入捕获是测频率和测脉宽的利器超声波测距HC-SR04就是靠它Trig引脚发一个10微秒以上的高电平触发信号Echo引脚会返回一个宽度和距离成正比的高电平用定时器捕获这个高电平的宽度距离厘米 脉宽微秒/ 58。公式的来源就是声速340m/s来回走一趟除以58比除以再乘回更顺手。测频率的方法要看信号频率段来选。低频信号用捕获周期法捕获两次上升沿的计数值差值频率 时钟 / 差值适合几百赫兹到几十千赫兹高频信号更好用的是闸门计数法让被测信号作为外部时钟源直接驱动计数器同时用另一个定时器开一个准确的1秒时间窗时间窗内计了多少个数就是多少赫兹。两种思路涉及捕获模式和外部时钟模式两种定时器用法能把这两个模式打通定时器这块就算入门了。编码器程序也是热词里的常客。正交编码器A相B相分别接TIM的CH1和CH2配置定时器工作在编码器模式硬件会自己判断是正转还是反转CNT的值会随着旋转增加或减少。这样你在电机控制里就能实时得到角位移配合定时中断算速度再做PID闭环。很多两轮差速小车的毕业设计核心就是“PWM模块控制驱动芯片 编码器模式测轮速 PID调平”一套理论全部用上。3.3 USART串口从轮询到中断再到DMA串口调试是嵌入式开发的呼吸机不会串口几乎等于没入门。USART的骨架一句话能讲清一个移位寄存器负责并串转换收发由状态寄存器里的TXE发送数据寄存器空和RXNE接收数据寄存器非空标志驱动波特率由一个分频寄存器决定。标准库初始化的核心参数是波特率、字长、停止位、校验位和收发模式。波特率计算是理论考点公式是USARTDIV 外设时钟 /16 × 波特率。F1的USART1挂在APB2上时钟72MHz想配115200USARTDIV就等于72M /16 × 115200≈39.06拆成整数部分39和小数部分0.06写入BRR寄存器。如果外设时钟不准比如APB2配成了36MHz还按72M算波特率误差直接翻倍高速下必然乱码。这也是为什么串口调不通时我总要先看一眼RCC时钟配置。收发方式有三档轮询适合“发送一条调试信息”代码最简单中断接收适合“收到一帧数据再处理”不阻塞CPUDMA收发适合大数据量场景比如从串口接收完整的OTA固件包CPU做别的事数据自己往内存里搬。热词里“stm32 usb虚拟串口发送数据”其实就是另一条路把STM32的USB外设配置成CDC类设备电脑端会识别成一个COM口不用额外接USB转串口芯片就能通信。这个方法在大学实验里很受欢迎但你先得把USB设备枚举、CDC描述符这些概念搞明白不然插上电脑没反应排查起来比普通串口麻烦得多。4. 开发环境与库的选型标准库、HAL库、寄存器怎么选4.1 Keil MDK、芯片包与ST-Link Utility开发环境是绕不开的“第一道门槛”。目前绝大多数教程还是基于Keil MDK这套IDE的问题在于界面老气、编译速度一般但生态太成熟遇到问题一搜就有答案。新手装环境时有两个高频坑一是Keil MDK和Keil C51可以装在同一台电脑上但一定要分别安装、路径分开License可以在同一套界面里同时添加千万不要图省事覆盖安装二是MDK5之后必须单独安装芯片支持包DFP这就是热词里“keil5安装stm32芯片包”的来源。你在Pack Installer界面里搜索STM32F1装上对应的Device Family Pack新建工程才能选到STM32F103C8T6这些型号。配套工具里ST-Link Utility是个容易被人忽略的老伙计。它的作用是烧录、查看Flash内容、还是解除芯片读保护的利器。当你遇到Keil下载时报“RDDI-DAP Error”或者提示“Connection error”时多半不是代码问题而是调试口被占用、接触不良或读保护被打开了。用ST-Link Utility连上芯片做一个Full Chip Erase很多疑难杂症当场解决。现在越来越多朋友转向VSCode插件来写STM32常用的组合是Arm GNU ToolchainOpenOCDCortex-Debug插件配合CMake或者EIDE插件管理工程。VSCode的补全和Git集成体验确实比Keil舒服但对新手有个前提你得理解编译链接的基本流程知道启动文件、链接脚本是用来干什么的否则配置报错时你连错误信息都看不懂。4.2 标准库与HAL库到底有什么区别“库函数和标准库有什么区别”这个问题我隔三差五就会被问到。严格说“标准库”指的是ST官方早期的外设标准库SPLStandard Peripheral Library也就是stm32f10x_gpio.c、stm32f10x_rcc.c这一堆文件。很多老教程里说的“库函数开发”指的就是拿这个库的函数去操作寄存器本质是在寄存器之上做了一层C语言封装让你不用记寄存器位。HAL库Hardware Abstraction Layer是ST后来主推的硬件抽象层库特点是封装得更彻底每个外设是一个句柄结构体初始化时先填句柄成员再调用HAL_XXX_Init函数。CubeMX可以图形化配置引脚和时钟直接用HAL库生成初始化代码开发速度快代码在不同系列之间移植也方便。但代价是代码量大、函数调用层次深在性能敏感或中断频繁的场景里直接翻寄存器底层反而更可控。LL库则是夹在中间的选择只做极薄的寄存器封装函数名很接近寄存器名字效率高又能少写点重复代码。我的建议很直接学原理用标准库或者直接寄存器因为寄存器操作会让你真正理解硬件做产品用HAL库加CubeMX快速出活但在关键路径上改用LL库追求极致性能或精简代码时果断用LL或者寄存器。网上老说“HAL库慢”实际上很多场景慢的是没关掉断言、用了阻塞式延时关键代码改成寄存器访问性能差距并不大。4.3 新建工程模板里的关键坑用标准库新建工程这件事既是入门必修课也是劝退一大波人的地方。以STM32F103ZE大容量芯片为例一个能跑的工程至少包含启动文件startup_stm32f10x_hd.s、系统初始化文件system_stm32f10x.c、标准库核心文件stm32f10x.c/h、以及你正在用的外设源文件rcc、gpio、usart等。在Keil的设置里还需要定义两个宏USE_STDPERIPH_DEVICE和STM32F10X_HD前者是告诉库函数处理“设备类型”的断言开关后者决定启动文件按多大Flash和RAM来配置堆栈。新手最典型的翻车场景是从网上下了一个“通用模板”把启动文件选成md中等容量却拿去烧录在大容量芯片上程序运行到一半跳飞或者忘了定义宏编译时崩出一堆assert_param相关的警告甚至报错。所以“新建工程”这件事别嫌麻烦最好自己从头到尾建一次你就知道启动文件、宏定义、头文件路径、Flash下载算法这四样东西是缺一不可的配套关系。Debug设置里记得勾选“Reset and Run”和正确的Flash算法如STM32F10x 512KB Flash不然下载后程序不自动运行还得手动按一下复位键。5. 从理论到实践最小系统板与三个经典实验5.1 最小系统板原理图一块芯片要跑起来的最小配置理论说再多最终都要落到一块板子上。STM32最小系统板的核心器件其实很少一个3.3V稳压芯片AMS1117最常见、一颗8MHz主晶振、可选的一颗32.768kHz RTC晶振、BOOT0和BOOT1跳线、SWD四线调试接口SWDIO/SWCLK/GND/3.3V、复位按键与RC复位电路以及每个VDD引脚旁边的0.1uF去耦电容。电源部分是新手画板时最不在乎、实际最容易出问题的地方。数字电路里电源引脚的0.1uF电容不能省作用是为芯片内部高速翻转提供就近的能量缓冲否则一路走线供电会在引脚上形成电压跌落。还有VDDA引脚要单独接滤波最好串一个磁珠或者小电感与数字电源隔开ADC采样的稳定性很大程度上就看这个。另一个常见坑是晶体振荡器——8MHz晶振的两个负载电容不是随便选的要看晶振规格书上写的负载电容值一般12pF到20pF。选错负载电容多余的功耗会消耗在晶振上长期运行可能出现起振慢甚至不振。买板子时也有个建议选那种板上自带USB转串口CH340或者CP2102和ST-Link SWD下载口的一体板一根Type-C线搞定供电、下载和串口输出少接一半杜邦线。调试体验直接决定你入坑第一周是产生兴趣还是想退坑。5.2 点亮LED与按键输入第一个能“动手”的程序点亮一颗LED虽然简单但它是检验“时钟、GPIO、调试下载”这三件事有没有跑通的最好办法。我给的标准库示例是PA5接一个LED推挽输出高电平点亮串联一个330欧限流电阻。配置代码只有三行核心逻辑先打开GPIOA的外设时钟再配置引脚为推挽输出、50MHz速度最后调用GPIO_SetBits输出高电平。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, 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(GPIOA, GPIO_InitStructure); GPIO_SetBits(GPIOA, GPIO_Pin_5);如果你点不亮先查三件事GPIO时钟开没开所有总线默认时钟全关不开时钟写寄存器是无效的这是STM32著名的低功耗设计引脚号对不对杜邦线插错脚是最经典的“Bug”芯片型号对不对C8T6的主频、Flash容量与ZE型号不同启动文件的配置也不同。按键实验则要配内部上拉输入读取输入数据寄存器IDR判断电平加上“按下去延时20ms再确认”的软件消抖防止机械按键的抖动被当成多次触发。这里再提一个容易踩的坑如果你把板子自带的用户按键接在PA0上恰好又把PA0配成了模拟输入或者浮空输入那么按键操作就会时灵时不灵。模拟输入模式下引脚连接到ADC的采样开关电平读出来的结果根本不是你想象的那个逻辑值。5.3 串口通信与USB虚拟串口让芯片有话可说点亮LED属于“动手”串口输出才算“表达”。串口实验的经典流程是配置USART1为115200、8N1TX引脚复用推挽输出RX引脚浮空输入然后重定向printf到串口发送函数让你的程序直接能用printf打印调试信息。int fputc(int ch, FILE *f) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); USART_SendData(USART1, (uint8_t)ch); return ch; }printf重定向有一个隐藏条件必须在Keil里勾选“Use MicroLIB”否则你的程序会在第一次printf时跳进半主机模式的HardFault表现为“程序一执行到printf就卡死”。这个问题在老教程评论区反复出现我强烈建议新人先把这一个坑记住能省一整晚排查时间。刚刚说的USB虚拟串口是对串口认识的再一次升维。STM32内部有USB设备控制器通过配置为CDC类可以在电脑上枚举出一个虚拟COM口。好处是省掉USB转串口芯片还不用管RS232电平关系坏处是USB协议栈的理解门槛比UART高。新手想一次调通重点检查USB_DM和USB_DP走线是不是等长、有没有上拉电阻、电源供电稳定不稳定。这个实验如果做通了你就同时理解了USB设备枚举、描述符、端点和CDC类的基本模型后续再做USB鼠标、USB键盘这些设备就会轻松很多。6. 高频问题排查与进阶路线6.1 延时函数卡死最容易被忽视的“理论事故”“delay函数卡死”是我见过提问频率最高的问题之一。如果你用的是基于SysTick的延时卡死原因通常逃不出这几类第一SysTick没有初始化就直接调用延迟而SysTick的时钟源又配置错了第二HSE没起振系统实际跑在8MHz内部RC上延时的循环次数是按72MHz算的时间完全不对看起来像“卡死”其实只是极慢第三在中断服务函数里调用了延时而SysTick的中断优先级又比当前中断低导致延时等待的那次中断永远来不了形成死锁。排查方法很简单但被很多人忽略进入Debug模式暂停程序看PC指针停在哪一行。如果停在delay函数的循环里去查RCC_CR寄存器确认HSEON和PLLRDY是否都为1如果停在HardFault_Handler里多半是中断向量表中SysTick_Handler没有实现。我自己后来写延时直接改用Cortex-M内核里的DWT计数器做微秒延时它不依赖SysTick中断也就不存在中断优先级死锁的问题。一键初始化DWT CYCCNT然后读取计数值做循环等待实测精度可以到微秒级项目里一直用到现在。6.2 JTAG禁用与下载失败成了大问题后悔晚矣把PA15/PB3/PB4这几个JTAG引脚当普通GPIO使用时必须先禁用JTAG复用功能只保留SWD下载口。标准库的写法是RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);新手容易犯的错误是干脆把SWJ全部禁用GPIO_Remap_SWJ_Disable结果把SWD下载口也关了芯片再也连不上调试器。遇到这个情况不要慌有两个自救办法按住板子上的复位键不放在Keil里点下载听到连接提示音的同时松开复位键有时能抢到下载窗口或者把BOOT0拉高进入系统存储器启动模式用串口ISP把Flash擦除掉让那段禁用代码不再执行。这个教训的深层理论还是那个JTAG/SWD引脚是芯片出厂时默认功能你抢过来当GPIO用必须清楚调试口的优先级这属于“引脚复用”理论的实际案例。下载失败的另一个高频错误是“Error: Flash Download failed - Cortex-M3”。我整理过一张速查表Flash算法没有选择或型号不匹配在Debug设置里的Flash Download勾选正确的编程算法。芯片读保护打开用ST-Link Utility整片擦除或关闭读保护。ST-Link固件太老升级ST-Link固件到最新版本。接线太长或接触不良SWD四根线尽量在10厘米以内线序不要接反GND必须共地。目标板供电不足ST-LinkV3可以给板子供电但而且大电流外设要靠外部电源电压不足也会导致下载失败。6.3 从这里往哪走基础理论永远是最值钱的底盘把前面这些理论吃透之后STM32的进阶方向其实自己会长出来。想做智能家居就去啃I2CBH1750光强传感器、OLED屏、SPI、WiFi模块ESP8266的通信协议栈想做机器人就去啃电机驱动、编码器测速、PID闭环最后组成两轮差速小车那样的完整系统想做工业控制就去看Modbus RTU通过RS485控制伺服、甚至EtherCAT从站方案。热词里的“STM32 OTA固件升级”也是一个很有价值的进阶方向核心是Bootloader加App的分区管理再加上串口或网络传输和固件校验这需要你对存储器映射、中断向量重定位、Flash擦写生命周期都有认知而这些全部建立在本文前面说的理论上。如果你发现自己在这些方向里卡住了往回倒退一步大概率还是总线时钟配置错了、中断优先级没理顺、DMA数据通路没打通。STM32的优势从来不是单点技术有多高深而是它把“底层硬件可控、上层协议可跑”这件事做得足够平衡。你越早接受“理论先行的效率高于盲目试错”这个观念后面走得就越快。最后分享一点个人体会带过不少人入门STM32后我最大的感受是点亮一颗LED真的不能证明你入门了能说清楚为什么这个LED亮、为什么改了引脚就不亮、为什么换成F4系列要加内部上拉才能亮这才算摸到了门槛。我的调试习惯很朴素看到任何异常先问四个问题——这个外设在哪个总线上、时钟是多少、事件走的是中断还是DMA、寄存器配置和物理引脚的默认功能冲不冲突。把这四个问题作为肌肉记忆STM32对你来说就不再是一堆需要背的寄存器而是一套可以推演的体系。如果你正准备买第一块板子记得我说的先别急着收藏一堆例程静下心来把这篇文章里提到的几个理论点自己推算一遍你的STM32之路会顺很多。
返回列表