4. 目标板硬件初探:认识STM32F407开发板

拿到一块新的开发板,我个人的习惯是先别急着上电。先把它翻来覆去地看一遍,把板子上的每一个芯片、每一个接口都认清楚。这就像你拿到一把新工具,总得先知道哪个是锤子、哪个是扳手吧?

咱们这门课用的是STM32F407开发板,具体型号是STM32F407VGT6。这块板子可以说是嵌入式开发里的“万金油”,性能足够,外设丰富,而且资料特别好找。我当年第一次做OTA升级原型验证,用的就是这块板子。

4.1 板级硬件资源一览

先看看板子上都有些什么。我把核心资源整理成了表格,方便你对照着板子实物看:

资源类别 具体型号/规格 用途说明
主控芯片 STM32F407VGT6 Cortex-M4内核,带FPU,主频168MHz
Flash 1MB 存放程序代码和OTA升级的备份区
SRAM 192KB 运行时数据存储,够跑FreeRTOS+MQTT
以太网接口 RMII接口 + PHY芯片 用于TCP/IP网络通信,OTA下载通道
USB接口 USB_OTG_FS/HS 调试串口、虚拟串口、U盘升级
板载调试器 ST-Link/V2 下载调试,同时提供虚拟串口
用户按键 4个 用于交互控制,比如触发OTA检查
LED指示灯 4个 状态指示,比如升级进度提示
我的经验: 1MB的Flash对于OTA升级来说其实有点紧张。如果你要同时保留出厂固件、当前运行固件和下载固件三个版本,就得精打细算。我建议你提前规划好Flash分区,后面我们会专门讲这个。

4.2 数据手册怎么读?

很多新手拿到几百页的数据手册就头大。其实不用全看,我教你一个“功利”的读法——用到什么查什么。

STM32F407的数据手册主要有两份:

  • 参考手册(Reference Manual):RM0090,讲的是怎么用芯片,比如寄存器怎么配、外设怎么初始化。这份最常用。
  • 数据手册(Datasheet):DS8626,讲的是芯片的电气特性,比如引脚定义、电压范围、功耗参数。画PCB或者做硬件选型时才需要细看。

我一般拿到一个新项目,会先翻数据手册的这几个部分:

  1. 引脚定义表(Pinouts and pin description)—— 确认哪些引脚能复用成什么功能。
  2. 存储器映射图(Memory map)—— 知道外设的基地址在哪,后面写驱动要用。
  3. 时钟树(Clock tree)—— 搞清楚系统时钟怎么配出来的,这是所有外设工作的基础。
  4. 外设寄存器描述(Register description)—— 具体配某个外设时再细看。
注意: 千万不要从第一页开始读!我曾经带过一个实习生,花了一周时间把参考手册从头到尾读了一遍,结果问他SPI怎么配,他说“我还没看到那章”。读手册是查字典,不是看小说。

4.3 GPIO外设梳理

GPIO是STM32最基础的外设。说白了,它就是芯片的“手脚”,用来跟外界打交道。

STM32F407有7组GPIO,从PA到PG,每组16个引脚,总共112个可用IO。每个引脚都可以独立配置成以下模式:

模式 说明 典型用途
输入浮空 引脚高阻态,电平由外部决定 读取按键状态
输入上拉 内部上拉电阻,默认高电平 防止引脚悬空,省外部电阻
输入下拉 内部下拉电阻,默认低电平 同上,但默认低电平
推挽输出 可以输出高/低电平,驱动能力强 控制LED、继电器
开漏输出 只能拉低,不能拉高,需要外部上拉 I2C总线、多设备共享线
复用功能 引脚交给片上外设控制 UART的TX/RX、SPI的SCK/MOSI
模拟模式 引脚直接连到ADC/DAC内部 采集模拟电压

配置GPIO其实就三步:使能时钟、设置模式、设置速度。我写了个最简的初始化代码,点亮板子上的LED:

// 点亮板载LED(假设接在PD12)
void LED_Init(void)
{
    // 1. 使能GPIOD时钟
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
    
    // 2. 配置PD12为推挽输出
    GPIOD->MODER &= ~(3U << (12 * 2));  // 先清零
    GPIOD->MODER |= (1U << (12 * 2));   // 设为输出模式
    
    // 3. 设置输出速度(50MHz够用了)
    GPIOD->OSPEEDR |= (2U << (12 * 2));
    
    // 4. 默认输出低电平(LED灭)
    GPIOD->ODR &= ~(1U << 12);
}

// 点亮LED
GPIOD->ODR |= (1U << 12);
避坑指南: 我曾经犯过一个低级错误——配了GPIO模式但忘了使能时钟。结果折腾了半天,引脚死活没反应。记住:STM32的所有外设,用之前必须先开时钟!这是新手最容易踩的坑。

4.4 UART外设梳理

UART是调试和通信的“生命线”。咱们做OTA升级,UART至少有两个用途:

  • 调试输出:打印日志,看程序跑到哪了、报了什么错。
  • 固件传输:通过串口Ymodem协议下载固件,这是最原始的OTA方式。

STM32F407有8个UART/USART,其中USART1/2/3是通用同步异步收发器,UART4/5/7/8是纯异步的。它们的区别在于:

外设 支持同步模式 支持硬件流控 最大波特率 常用引脚
USART1 是 是 10.5Mbps PA9(TX), PA10(RX)
USART2 是 是 5.25Mbps PD5(TX), PD6(RX)
USART3 是 是 5.25Mbps PD8(TX), PD9(RX)
UART4 否 否 5.25Mbps PA0(TX), PA1(RX)

配置UART的核心是设置波特率。波特率计算公式是:

// 波特率 = 时钟频率 / (16 * USART_BRR)
// 假设时钟84MHz,目标波特率115200
// USART_BRR = 84000000 / (16 * 115200) = 45.57
// 取整:DIV_Mantissa = 45, DIV_Fraction = 0.57 * 16 ≈ 9
// 所以 USART_BRR = (45 << 4) | 9 = 0x2D9

USART1->BRR = 0x2D9;
我的习惯: 调试串口我一般用115200波特率,8位数据位,1位停止位,无校验。这个配置最通用,串口助手、Putty、Minicom都能直接连。别用太冷门的波特率,不然调试的时候还得专门配工具。

4.5 I2C外设梳理

I2C在咱们这个项目里主要用来接传感器和EEPROM。比如你要在板子上挂一个温湿度传感器,或者用外部EEPROM存OTA升级的配置参数,I2C就是首选。

STM32F407有3个I2C外设:I2C1、I2C2、I2C3。它们都支持:

  • 标准模式(100kHz)和快速模式(400kHz)
  • 7位和10位设备地址
  • 主模式和从模式
  • DMA传输

I2C的通信协议其实不复杂,就是两根线:SCL(时钟)和SDA(数据)。通信过程分三步:

  1. 起始条件:SCL高电平时,SDA从高变低。
  2. 数据传输:每8位数据后跟一个应答位(ACK/NACK)。
  3. 停止条件:SCL高电平时,SDA从低变高。

写一个I2C读取传感器数据的函数,核心逻辑是这样的:

// 从I2C设备读取一个字节
uint8_t I2C_ReadByte(uint8_t dev_addr, uint8_t reg_addr)
{
    uint8_t data = 0;
    
    // 1. 发送起始条件
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));  // 等待起始条件完成
    
    // 2. 发送设备地址(写方向)
    I2C1->DR = dev_addr << 1;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));  // 等待地址发送完成
    (void)I2C1->SR2;  // 清除ADDR标志
    
    // 3. 发送寄存器地址
    I2C1->DR = reg_addr;
    while(!(I2C1->SR1 & I2C_SR1_TXE));
    
    // 4. 发送重复起始条件
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    // 5. 发送设备地址(读方向)
    I2C1->DR = (dev_addr << 1) | 0x01;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    // 6. 读取数据
    while(!(I2C1->SR1 & I2C_SR1_RXNE));
    data = I2C1->DR;
    
    // 7. 发送停止条件
    I2C1->CR1 |= I2C_CR1_STOP;
    
    return data;
}
注意: I2C的时序要求很严格。我曾经在项目里遇到一个奇怪的问题——传感器偶尔读不到数据。查了半天,发现是I2C总线上拉电阻选得太大了,导致信号上升沿太慢。后来换成4.7kΩ的电阻,问题就解决了。如果你遇到I2C通信不稳定,先检查上拉电阻和总线电容。

4.6 本章知识结构图

下面这张图把咱们这章讲的核心内容串起来了。你可以把它当成一个“硬件资源地图”,后面写代码的时候随时回来对照:

STM32F407硬件资源与数据手册导读 STM32F407硬件资源与数据手册导读 STM32F407VGT6 板级硬件资源 1MB Flash / 192KB SRAM 以太网 / USB / ST-Link 按键 / LED / 扩展接口 数据手册导读 参考手册 RM0090 数据手册 DS8626 引脚定义 / 存储器映射 外设资源梳理 GPIO:7组112个引脚 UART:8个独立通道 I2C:3个独立外设 OTA升级用途 Flash分区规划 UART固件传输 I2C配置存储 核心原则:用前先开时钟 → 查手册找寄存器 → 配模式/速率/中断 调试技巧:串口打印 + GPIO示波器抓波形 = 解决90%的外设问题

嗯,到这里,咱们对STM32F407开发板的硬件资源就有了一个整体的认识。你可能会问:“这些外设怎么跟MQTT和OTA升级联系起来?”别急,后面几章我们会一步步把今天梳理的这些外设用起来。GPIO用来做状态指示,UART用来打印调试信息和传输固件,I2C用来挂传感器和存储配置参数——每个外设都会在项目中找到它的位置。