STM32 单片机两层学习规划
一、总体目标
本阶段只学习 STM32 单片机开发,不延伸到 FreeRTOS、Linux、U-Boot。
最终目标不是"看完课程"或"跑通例程",而是具备面向单片机/嵌入式软件岗位的基本能力:
- 能根据需求独立完成外设初始化和基本功能;
- 能脱离教程写代码、调试代码和修改功能;
- 遇到问题能查数据手册、参考手册和库函数文档;
- 能使用串口打印、断点、单步、寄存器窗口和逻辑分析仪定位问题;
- 第一层能够熟练使用库函数;
- 第二层能够理解库函数背后的寄存器配置,并独立实现关键底层代码。
整体学习原则:
20% 看原理和例程,80% 自己写、自己改、自己调。
推荐学习顺序:
text
RCC
↓
GPIO
↓
UART
↓
SPI
↓
SPI Flash
↓
第一层核心测试
↓
I2C
↓
ADC
↓
CAN
↓
补齐第一层
↓
第二层寄存器学习
↓
第二层 SPI 测试
第一层:外设应用层
1. 阶段目标
系统学习并会使用以下 7 个外设:
- RCC
- GPIO
- UART
- SPI
- I2C
- ADC
- CAN
这一层的核心目标是:
给出一个基本外设需求,能够查资料并使用 HAL 或其他库函数独立实现,而不是依赖教程逐行照抄。
第一层暂时不要求完整掌握寄存器位定义和库函数内部实现。只需要理解必要的工作原理、配置关系和调用流程。
不要在第一层投入大量时间逐位研究寄存器,否则容易在掌握基本开发能力之前陷入底层细节。
2. 第一层通用学习方法
每个外设按照以下步骤学习:
text
理解基本原理
→ 阅读并运行例程
→ 整理初始化流程
→ 关闭例程,自己重新实现
→ 修改参数或功能
→ 主动制造故障并调试
→ 完成独立小练习
→ 总结常见问题
建议每个外设建立一页笔记,至少记录:
- 外设用途;
- 使用了哪些引脚;
- GPIO复用关系;
- 外设时钟来源;
- 初始化步骤;
- 核心发送、接收或采集函数;
- 阻塞、中断、DMA方式的区别;
- 常见错误及排查方法;
- 本次实验中实际遇到的问题。
"学会"的判断标准不是看懂,而是:
不看原例程,能够根据自己的流程笔记和官方资料重新实现。
3. RCC
学习内容
- STM32基本时钟树;
- HSI、HSE、PLL的作用;
- SYSCLK、HCLK、PCLK之间的关系;
- AHB、APB总线与外设时钟;
- GPIO和其他外设时钟使能;
- 不同外设挂在哪条总线上;
- 基本时钟频率计算;
- 使用库函数配置系统时钟。
学到什么程度
第一层不要求熟记所有时钟寄存器。
需要做到:
- 知道外设使用前为什么必须开启时钟;
- 能从时钟树判断CPU和外设的大致工作频率;
- 能修改系统时钟配置;
- 能确认UART、SPI、ADC等外设的时钟来源;
- 出现波特率、SPI速率异常时,知道检查时钟配置。
练习任务
- 分别使用内部时钟和外部晶振运行程序;
- 修改系统主频,并通过串口打印当前时钟频率;
- 开启和关闭某个GPIO端口时钟,观察现象;
- 计算并验证APB总线时钟;
- 修改主频后重新检查UART波特率和延时是否正常。
通过标准
不参考原例程时,能够:
- 完成基本系统时钟配置;
- 正确开启指定GPIO和外设时钟;
- 说清楚系统时钟到外设时钟的大致路径;
- 根据配置计算主要总线频率;
- 定位"忘记开时钟"或"时钟频率配置错误"问题。
预计时间
约2~3天。
4. GPIO
学习内容
- 输入、输出、复用和模拟模式;
- 推挽输出与开漏输出;
- 上拉、下拉和浮空;
- 输出速度;
- GPIO读取和写入;
- 外部中断的基本使用;
- 引脚复用与外设连接关系。
学到什么程度
需要做到:
- 独立配置LED输出和按键输入;
- 理解上拉、下拉的作用;
- 知道推挽和开漏的主要区别;
- 能根据原理图确认LED、按键和外设对应引脚;
- 能判断高低电平是否有效;
- 能完成轮询和外部中断两种按键检测。
练习任务
- LED周期闪烁;
- 按键控制LED;
- 使用一个按键切换LED状态;
- 使用外部中断响应按键;
- 修改引脚、有效电平和输出模式;
- 故意配置错误引脚或关闭GPIO时钟,然后定位问题。
通过标准
给出LED和按键对应引脚后,能够脱离教程独立完成:
- GPIO时钟使能;
- 输入输出配置;
- 电平读取和输出;
- 简单按键消抖;
- 基本外部中断功能。
预计时间
约2~3天。
5. UART
学习内容
- 串口基本通信原理;
- 波特率、数据位、停止位和校验位;
- TX和RX引脚;
- 阻塞发送与接收;
- 中断接收;
- 重定向
printf; - 串口调试输出;
- 接收不定长数据的基本思路;
- 常见乱码、丢数据和接收失败问题。
学到什么程度
需要做到:
- 独立完成UART初始化;
- 使用串口发送和接收数据;
- 使用串口打印变量及调试信息;
- 完成简单命令接收;
- 知道阻塞、中断和DMA方式的差异;
- 能定位波特率错误、接线错误和收发引脚错误。
第一层不要求立即掌握复杂协议解析和高性能串口框架。
练习任务
- 周期发送字符串;
- 串口接收一个字节并回传;
- 接收一行字符后统一回传;
- 用串口命令控制LED;
- 打印系统时钟、ADC数值和Flash数据;
- 故意设置错误波特率并分析乱码原因。
通过标准
不看原例程时,能够:
- 初始化串口;
- 完成基本收发;
- 实现
printf输出; - 使用串口辅助调试其他外设;
- 编写简单的串口命令交互功能。
预计时间
约3~4天。
6. SPI
学习内容
- SPI主机和从机;
- SCK、MOSI、MISO、CS信号;
- 全双工通信;
- CPOL和CPHA;
- SPI模式0~3;
- 数据位宽;
- MSB/LSB传输顺序;
- SPI时钟分频;
- 硬件片选与软件片选;
- 阻塞式发送、接收和收发;
- SPI时序与逻辑分析仪观察方法。
学到什么程度
需要做到:
- 独立配置STM32为SPI主机;
- 根据从设备手册选择SPI模式;
- 控制CS引脚;
- 完成单字节和多字节收发;
- 理解"写命令---写地址---发送或接收数据"的通信流程;
- 能使用逻辑分析仪检查SPI波形;
- 知道为什么硬件SPI能否正常工作不仅取决于初始化。
练习任务
- 创建硬件SPI工程;
- 完成单字节发送与接收函数;
- 修改SPI时钟频率;
- 修改CPOL、CPHA并观察通信变化;
- 使用逻辑分析仪查看CS、SCK、MOSI、MISO;
- 故意设置错误SPI模式并定位故障。
通过标准
给出从设备的基本时序说明后,能够:
- 独立完成硬件SPI初始化;
- 正确配置通信模式和速度;
- 控制片选信号;
- 发送命令、地址和数据;
- 结合返回值和波形定位通信问题。
预计时间
约3~4天。
7. SPI Flash
学习内容
以常见W25Q系列Flash为例:
- JEDEC ID读取;
- Flash容量和地址组织;
- 页、扇区、块的概念;
- 读数据命令;
- 写使能命令;
- 页编程命令;
- 扇区擦除命令;
- 状态寄存器;
- BUSY状态轮询;
- NOR Flash写入前为什么可能需要擦除;
- 页写边界问题;
- 命令、地址和数据的发送顺序。
学到什么程度
需要做到:
- 根据Flash数据手册查找命令;
- 独立读取Flash ID;
- 独立读取指定地址的数据;
- 完成写使能、擦除、写入和读回;
- 轮询BUSY状态;
- 正确处理片选;
- 理解Flash数据只能从1写成0,恢复为1通常需要擦除;
- 不能只会调用老师已经封装好的完整Flash驱动。
练习任务
- 读取并打印JEDEC ID;
- 读取指定地址的若干字节;
- 擦除一个测试扇区;
- 向指定地址写入固定数据;
- 读回并逐字节比较;
- 测试不同长度的数据;
- 测试跨页写入并观察问题;
- 故意遗漏写使能或BUSY等待,分析失败原因。
通过标准
不参考原例程时,能够根据Flash数据手册完成:
text
读ID
→ 读取指定地址
→ 擦除
→ 写使能
→ 写入数据
→ 等待完成
→ 读回数据
→ 比较结果
预计时间
约3~5天。
8. 第一层核心测试:硬件SPI读写Flash
测试目标
使用STM32硬件SPI和库函数完成Flash实际读写验证。
测试时:
- 不参考原来的SPI Flash例程;
- 可以查芯片手册、Flash手册和库函数文档;
- 可以使用HAL或老师指定的库函数;
- 必须自己组织初始化和读写流程;
- 不能直接复制已经封装好的完整答案。
测试流程
选择一个安全的测试地址,执行:
text
1. 初始化时钟、GPIO、UART和硬件SPI
2. 读取测试地址的原始数据
3. 通过UART打印原值
4. 必要时擦除测试地址所在扇区
5. 向同一地址写入新值
6. 等待Flash操作完成
7. 再次读取相同地址
8. 通过UART打印读回值
9. 比较写入值和读回值
10. 输出PASS或FAIL
建议输出形式:
text
SPI Flash Test Start
Address : 0x001000
Old Data: 12 34 56 78
Write : A5 5A 11 22
Readback: A5 5A 11 22
Result : PASS
通过标准
以下条件必须全部满足:
- 使用硬件SPI;
- 能读取并打印原值;
- 能向同一地址写入新值;
- 能重新读取并打印结果;
- 能自动比较;
- 输出明确的
PASS或FAIL; - 断电重启后仍能读到已写入的数据;
- 测试过程中没有参考原例程;
- 能解释写使能、擦除、页编程和BUSY等待的作用;
- 如果测试失败,能通过串口信息、返回值和波形逐步定位问题。
第一层预计总时间
如果每天学习2~3小时:
- 核心链路RCC→GPIO→UART→SPI→SPI Flash:约2~3周;
- 补充I2C、ADC、CAN:约1~2周;
- 第一层完整完成:约3~5周。
如果第一层测试是近期主要目标,可先完成核心链路并参加测试,再补齐I2C、ADC和CAN。
9. I2C
学习内容
- SDA和SCL;
- 主机与从机;
- 起始、停止和应答;
- 设备地址;
- 7位地址及读写位;
- 寄存器地址;
- 开漏输出和上拉电阻;
- 阻塞式读写;
- 超时和总线忙问题。
学到什么程度
需要做到:
- 根据设备手册确认I2C地址;
- 独立初始化I2C;
- 读取和写入从设备寄存器;
- 理解设备地址和寄存器地址的区别;
- 能处理地址位移问题;
- 能排查没有应答、线路没有上拉和总线被占用。
练习任务
选择EEPROM、温度传感器或其他I2C器件:
- 扫描I2C设备地址;
- 读取器件ID;
- 读取一个数据寄存器;
- 修改并读回一个可写寄存器;
- 断开设备或修改地址,观察并分析错误。
通过标准
给出器件手册后,能独立完成:
- 接线和地址确认;
- I2C初始化;
- 寄存器读写;
- 数据解析;
- 基本故障排查。
预计时间
约3~4天。
10. ADC
学习内容
- 模拟量和数字量;
- ADC分辨率;
- 参考电压;
- ADC时钟;
- 采样时间;
- 转换时间;
- 单通道和多通道;
- 单次与连续转换;
- 轮询、中断和DMA方式;
- 原始值到实际电压的换算;
- 输入阻抗和采样稳定性。
学到什么程度
需要做到:
- 独立配置一个ADC通道;
- 获取原始采样值;
- 换算实际电压;
- 理解分辨率和参考电压对结果的影响;
- 知道采样时间过短可能导致误差;
- 能完成简单的多次采样和平均滤波。
练习任务
- 读取电位器电压;
- 串口打印ADC原始值;
- 换算并打印实际电压;
- 使用不同采样时间比较结果;
- 完成多次平均滤波;
- 设置简单阈值控制LED。
通过标准
能够独立完成:
text
ADC初始化
→ 选择通道
→ 启动转换
→ 等待完成
→ 读取结果
→ 换算电压
→ 串口输出
并能说明结果异常时应检查参考电压、引脚模式、采样时间和接线。
预计时间
约2~3天。
11. CAN
学习内容
- CAN基本用途;
- 差分信号CAN_H和CAN_L;
- 标准帧与扩展帧;
- 数据帧结构;
- 标识符;
- 仲裁基本概念;
- 波特率与位时序;
- 过滤器;
- 发送邮箱;
- 接收FIFO;
- 轮询和中断接收;
- 终端电阻;
- CAN控制器和CAN收发器的区别。
学到什么程度
需要做到:
- 独立配置基本CAN通信;
- 正确设置波特率;
- 构造并发送标准数据帧;
- 接收并解析数据帧;
- 配置一个基本过滤器;
- 知道CAN总线必须使用收发器;
- 能排查终端电阻、波特率不一致和过滤器错误。
练习任务
最好使用两块开发板或一块板配合CAN工具:
- 节点A周期发送数据;
- 节点B接收并串口打印;
- 节点B修改数据后回复;
- 设置过滤器,只接收指定ID;
- 修改一端波特率,观察通信失败现象;
- 检查发送状态和错误状态。
通过标准
能够脱离教程完成:
- CAN初始化;
- 过滤器配置;
- 标准帧发送;
- 数据帧接收;
- 串口打印接收内容;
- 常见物理层和配置问题排查。
预计时间
约4~6天。
第二层:寄存器与库函数底层理解
1. 阶段目标
第二层不再满足于"会调用HAL"。
需要结合:
- 芯片数据手册;
- 芯片参考手册;
- 启动文件;
- CMSIS设备头文件;
- HAL或标准外设库源码;
- 调试器的寄存器窗口;
深入理解第一层7个外设的底层配置过程。
核心目标是:
看到一个库函数调用,能够大致说出它修改了哪些寄存器、为什么这样配置,以及硬件将如何响应。
第二层也不要求脱离库函数重写整个STM32工程。重点是研究核心初始化和数据通路,建立从"需求"到"寄存器位"的映射能力。
2. 第二层通用学习方法
每个外设都按照以下流程研究:
text
运行第一层可用例程
→ 在初始化函数处设置断点
→ 单步进入HAL或库函数
→ 对照参考手册查看寄存器
→ 记录寄存器修改前后的值
→ 理解关键位的作用
→ 用寄存器方式重写最小功能
→ 与库函数版本进行对照验证
每个外设至少整理一张配置表:
| 功能需求 | 对应寄存器 | 关键位 | 库函数 | 实际作用 |
|---|---|---|---|---|
| 开启外设时钟 | RCC相关寄存器 | 外设使能位 | RCC/HAL宏 | 给外设提供时钟 |
| 配置引脚复用 | GPIO相关寄存器 | MODER/AF等 | GPIO初始化函数 | 将引脚连接到外设 |
| 启用外设 | 外设控制寄存器 | EN位 | HAL初始化 | 启动外设 |
不要求死记全部寄存器名称,但必须能够从参考手册中找到并解释关键配置。
3. RCC第二层要求
学习内容
- 时钟控制相关寄存器;
- 振荡器启用与就绪标志;
- PLL输入、倍频和分频;
- 系统时钟切换;
- AHB/APB分频;
- 外设时钟使能和复位;
- SystemCoreClock的更新过程;
- HAL时钟配置函数内部流程。
学到什么程度
- 能对照手册解释系统时钟配置顺序;
- 能说明为什么需要等待时钟就绪;
- 能解释系统时钟切换和总线分频;
- 能直接使用寄存器开启某个GPIO或SPI时钟;
- 能根据寄存器值计算主要时钟频率。
练习任务
- 单步进入系统时钟配置函数;
- 观察关键RCC寄存器变化;
- 用寄存器方式开启GPIO时钟;
- 用寄存器方式完成一个简单主频配置;
- 验证配置后的系统频率。
通过标准
能根据参考手册独立找到并配置关键RCC寄存器,并解释配置顺序。
4. GPIO第二层要求
学习内容
根据具体STM32系列研究:
- 模式寄存器;
- 输出类型寄存器;
- 输出速度寄存器;
- 上下拉寄存器;
- 输入、输出数据寄存器;
- 原子置位/复位寄存器;
- 复用功能寄存器;
- 外部中断映射相关寄存器。
学到什么程度
- 能通过寄存器配置输入、输出和复用;
- 理解库函数如何计算引脚对应的寄存器位;
- 能使用原子置位/复位方式控制GPIO;
- 能根据外设复用表选择正确AF编号。
练习任务
- 不调用GPIO初始化函数,用寄存器点亮LED;
- 用寄存器读取按键;
- 用寄存器配置UART或SPI复用引脚;
- 单步分析库函数如何配置一个GPIO引脚。
通过标准
能独立用寄存器完成GPIO最小输入、输出和复用配置。
5. UART第二层要求
学习内容
- UART控制寄存器;
- 波特率寄存器;
- 状态标志;
- 发送和接收数据寄存器;
- 发送数据寄存器空、发送完成、接收非空等标志;
- UART使能、发送使能和接收使能;
- 中断使能和中断处理流程;
- HAL超时机制和状态管理。
学到什么程度
- 能从外设时钟和目标波特率推导波特率配置;
- 能解释发送一个字节时寄存器发生的变化;
- 能使用寄存器轮询方式完成基本收发;
- 能理解HAL发送函数为什么要等待状态标志。
练习任务
- 单步进入UART初始化函数;
- 跟踪波特率寄存器的计算与写入;
- 用寄存器实现发送一个字符;
- 用寄存器实现阻塞接收一个字符;
- 对比发送寄存器空和发送完成两个标志。
通过标准
能够使用寄存器方式完成最小UART收发,并解释关键状态位。
6. SPI第二层要求
学习内容
- SPI控制寄存器;
- 主机模式选择;
- CPOL、CPHA;
- 波特率分频;
- 数据位宽和位序;
- 软件片选管理;
- 发送缓冲区空标志;
- 接收缓冲区非空标志;
- BUSY标志;
- 数据寄存器;
- 溢出错误及清除方法;
- SPI使能和关闭顺序;
- HAL SPI初始化和收发函数内部流程。
学到什么程度
- 能根据Flash时序配置SPI模式;
- 能通过寄存器完成SPI初始化;
- 能轮询状态位发送和接收一个字节;
- 能处理全双工收发关系;
- 能理解为什么只接收数据时仍然需要发送空字节;
- 能判断一次传输何时真正结束;
- 能处理常见错误状态。
练习任务
- 单步进入HAL SPI初始化;
- 记录关键寄存器配置结果;
- 用寄存器实现SPI单字节收发;
- 用寄存器实现多字节发送和接收;
- 使用逻辑分析仪对比HAL版本和寄存器版本的波形;
- 故意制造错误配置并观察状态位。
通过标准
不调用HAL SPI初始化和HAL SPI收发函数,能够根据参考手册完成硬件SPI控制器的初始化及基本收发。
7. I2C第二层要求
学习内容
- I2C时序配置;
- 起始、停止、地址和应答控制;
- 发送、接收和状态寄存器;
- 总线忙状态;
- 应答失败、仲裁丢失和总线错误;
- 不同STM32系列I2C外设结构差异;
- HAL I2C状态机和超时处理。
学到什么程度
- 能结合状态位理解一次完整寄存器读写;
- 能说明起始、地址、应答、数据和停止之间的顺序;
- 能用寄存器完成一个简单设备寄存器读取;
- 能识别无应答和总线忙问题。
练习任务
- 单步分析HAL I2C寄存器读取;
- 记录每个阶段的状态位;
- 用寄存器实现设备地址发送;
- 用寄存器读取一个从设备寄存器;
- 分析无应答时的错误状态。
通过标准
能对照参考手册解释一次I2C读写事务,并实现最小寄存器版本。
8. ADC第二层要求
学习内容
- ADC时钟配置;
- 分辨率设置;
- 通道选择;
- 转换序列;
- 采样时间;
- ADC使能和校准;
- 启动转换;
- 转换完成标志;
- 数据寄存器;
- 连续转换和扫描模式。
学到什么程度
- 能解释ADC初始化中的关键寄存器;
- 能计算采样和转换所需时间;
- 能通过寄存器选择通道和采样时间;
- 能启动转换、等待完成并读取结果;
- 能理解HAL校准和转换函数的基本流程。
练习任务
- 单步分析HAL ADC初始化;
- 用寄存器配置单通道ADC;
- 用寄存器启动单次转换;
- 读取并换算电压;
- 修改采样时间并比较结果。
通过标准
能用寄存器完成单通道、单次ADC采集,并解释关键配置。
9. CAN第二层要求
学习内容
具体寄存器随bxCAN或FDCAN而不同,需要以实际芯片为准:
- 工作模式控制;
- 初始化模式进入和退出;
- 位时序配置;
- 过滤器配置;
- 发送邮箱;
- 接收FIFO;
- 中断和状态标志;
- 错误计数和错误状态;
- HAL CAN初始化、发送和接收的内部流程。
学到什么程度
- 能根据时钟和目标波特率理解位时序配置;
- 能解释发送邮箱的使用方法;
- 能理解接收FIFO和过滤器的关系;
- 能通过寄存器观察发送、接收和错误状态;
- 能完成最小寄存器方式的发送或接收实验。
练习任务
- 单步分析CAN初始化;
- 记录位时序寄存器;
- 观察发送邮箱状态变化;
- 观察接收FIFO状态变化;
- 查看通信失败时的错误状态;
- 用寄存器完成一次标准帧发送。
通过标准
能根据参考手册找到并解释CAN关键寄存器,完成最小发送或接收功能。
第二层核心测试:寄存器方式实现硬件SPI
测试目标
仍然使用STM32硬件SPI控制器与SPI Flash通信,但SPI核心部分必须根据芯片参考手册使用寄存器实现。
"寄存器方式"不等于软件模拟SPI。测试要求使用芯片内部的硬件SPI控制器。
可以沿用的部分
允许沿用原工程中的:
- 启动文件;
- 链接脚本;
- 系统基础代码;
- UART打印;
- 延时函数;
- Flash命令定义;
- Flash地址定义;
- 测试数据;
- 必要的板级GPIO框架;
- 非SPI部分的辅助功能。
必须自己实现的部分
以下内容必须依据芯片手册用寄存器方式实现:
- SPI外设时钟使能;
- SPI相关GPIO复用配置;
- SPI主机模式配置;
- CPOL和CPHA配置;
- SPI速度分频;
- 数据位宽和传输顺序;
- SPI外设使能;
- SPI单字节发送和接收;
- SPI多字节读写核心流程;
- 发送、接收和BUSY状态判断;
- 必要的错误处理;
- CS控制应能够说明实现方式。
不得在核心路径中调用:
- HAL SPI初始化函数;
- HAL SPI发送函数;
- HAL SPI接收函数;
- HAL SPI收发函数;
- 已经完整封装好的寄存器SPI答案。
测试流程
text
1. 根据参考手册配置SPI相关时钟
2. 配置SCK、MOSI、MISO对应GPIO复用
3. 配置CS引脚
4. 配置硬件SPI为主机模式
5. 设置CPOL、CPHA、分频和数据位宽
6. 启用SPI
7. 使用自己实现的寄存器收发函数读取Flash ID
8. 读取指定地址的原值并打印
9. 擦除测试区域
10. 写入新数据
11. 等待Flash完成操作
12. 读回相同地址
13. 比较数据
14. 输出PASS或FAIL
通过标准
以下条件必须全部满足:
- 使用硬件SPI控制器,而不是GPIO模拟SPI;
- SPI初始化由自己根据手册使用寄存器实现;
- SPI收发核心函数由自己使用寄存器实现;
- 实际读取到正确的Flash ID;
- 完成指定地址的实际写入和读回;
- 自动比较并输出PASS或FAIL;
- 能解释每个关键SPI寄存器的作用;
- 能解释发送和接收状态位;
- 能说明CPOL、CPHA和分频值的选择依据;
- 能使用寄存器窗口和逻辑分析仪排查问题;
- 能指出HAL实现与自己的寄存器实现之间的对应关系。
预计时间
完成第一层后,第二层建议安排4~7周:
- RCC、GPIO:约4~6天;
- UART:约4~5天;
- SPI与第二层测试:约7~10天;
- I2C:约5~7天;
- ADC:约3~5天;
- CAN:约6~9天;
- 综合复习与查漏补缺:约4~7天。
时间取决于具体STM32系列、调试设备和每天投入时间。
两层边界
| 对比项 | 第一层 | 第二层 |
|---|---|---|
| 核心目标 | 会正确使用外设 | 理解并控制外设底层 |
| 主要资料 | 教程、例程、库函数文档、器件手册 | 芯片参考手册、数据手册、库源码 |
| 编程方式 | HAL或其他库函数 | 研究库源码并实现关键寄存器代码 |
| 学习重点 | 初始化流程、功能实现、实际调试 | 寄存器配置、状态变化、底层执行流程 |
| 是否研究寄存器 | 只了解必要概念 | 必须系统研究关键寄存器 |
| 是否进入库源码 | 非必要 | 必须单步进入并分析 |
| 测试重点 | 脱离教程,用库函数完成Flash读写 | 不调用SPI核心HAL函数,用寄存器完成Flash读写 |
| 常见错误 | 过度研究底层,迟迟不能独立做功能 | 仍停留在调用HAL,无法解释底层行为 |
第一层完成的标志:
我能用库函数独立把功能做出来,遇到问题也能逐步排查。
第二层完成的标志:
我不仅能把功能做出来,还知道库函数配置了哪些关键寄存器,并能自己实现核心底层代码。
建议执行节奏
每次学习建议分成三个部分:
- 20%:学习原理、阅读手册和分析例程;
- 60%:关闭教程,自己实现和调试;
- 20%:修改需求、制造错误、总结问题。
每个外设至少完成三轮:
第一轮:照着做
理解基本原理,运行官方或老师的例程。
第二轮:脱离教程重写
只保留需求、芯片手册和自己的流程笔记,重新建立工程并实现。
第三轮:修改和排错
主动改变:
- 引脚;
- 时钟频率;
- 通信速度;
- 工作模式;
- 数据长度;
- 设备地址;
- 中断或轮询方式。
然后处理实际出现的问题。
自我检查清单
每学完一个外设,检查自己能否回答:
- 这个外设解决什么问题?
- 它需要开启哪些时钟?
- 使用哪些引脚和复用功能?
- 初始化顺序是什么?
- 最核心的发送、接收或采集函数是什么?
- 怎样判断操作成功或失败?
- 常见故障有哪些?
- 出现问题时先检查什么?
- 能否脱离原例程重新实现?
- 能否修改引脚、速度或功能?
- 能否使用串口、断点或逻辑分析仪定位问题?
- 第二层时,能否找到相应的关键寄存器?
如果只能讲原理但写不出来,说明练习不足;如果只能复制代码但不能修改,也不算通过。
最终能力标准
完成两层学习后,应达到以下水平:
- 能独立完成常见STM32外设功能;
- 能根据原理图确认引脚和硬件连接;
- 能查阅STM32数据手册、参考手册和外设器件手册;
- 能使用HAL快速开发;
- 能阅读HAL或标准库源码;
- 能通过寄存器理解外设底层工作过程;
- 能独立实现关键寄存器驱动;
- 能使用串口日志、断点、单步、寄存器窗口和逻辑分析仪定位问题;
- 能解释自己写过的代码,而不是只展示运行结果;
- 面对一个陌生外设,具备"查资料---写代码---调试---验证---总结"的完整解决问题能力。
求职时真正有价值的,不只是"学过GPIO、UART和SPI",而是能够拿出具体证据说明:
我可以脱离教程,根据手册独立完成外设功能;出现通信失败时,我能够从时钟、GPIO、配置、协议时序、状态位和硬件波形逐层定位问题。