STM32H7 软件使用手册#
1. 工程目录导航#
驱动层 (Drivers) → 中间件层 (Middlewares) → 应用层 (Projects) 。
1.1 Drivers (驱动层)#
BSP (Board Support Package): 核心层。对底层 HAL 库进行二次封装,提供
UART、DI/DO、ADC/DAC、SDRAM等标准工控接口。Components: 外部元器件驱动(如以太网 PHYLAN8742、存储芯片W25QXX、触摸屏FT5XXX等)。STM32H7XX: 针对具体开发板的硬件层实现。CMSIS: ARM 官方提供的 Cortex-M 内核通用软件接口。
HAL_Driver: ST 官方硬件抽象层库,提供外设最底层的控制接口。
1.2 Middlewares (中间件层)#
ST_USB_Library: 负责 USB Host/Device 通信协议。
FatFs: 轻量级文件系统,用于管理 SD 卡、SPI Flash 中的数据文件。
LwIP: 轻量级 TCP/IP 协议栈,支持 HTTP、MQTT、SNTP 等工业通信协议。
1.3 Projects (项目应用层)#
config: 工程配置中心。
AMKN86xx_Config.h: 板卡引脚定义与功能开关。stm32h7xx_hal_conf.h: HAL 库底层配置。src / inc: 业务逻辑区。包含
main.c(任务调度) 及各功能应用逻辑(如io_app.c)。startup: 芯片启动汇编文件。
2. 框架运行流程#
系统从上电到进入任务轮询的完整逻辑如下:
flowchart TB
subgraph Initialization["系统初始化阶段"]
Vars["APP_UserVars_Init: 加载系统变量"]
APP_Init["<b>APP_Init</b>: 模块化加载入口"]
UART_Init["Uart_APPInit: 串口应用初始化"]
IO_Init["IO_APPInit: IO 硬件属性配置"]
Logo["Logo_Out: 打印版权与版本信息"]
Storage["存储初始化: EEPROM / Flash / SDRAM"]
Periph["外设启动: ADC / DAC / PWM / CAN"]
Middle["中间件启动: LWIP / USBH / WIFI"]
end
subgraph Polling["主循环任务轮询 (while 1)"]
Cnt["UserVars.MCU_RunCnt++ (心跳计数)"]
MainLoop{"任务轮询调度"}
IO_P["IO_Proc: 数字输入输出扫描"]
UART_P["Uart_Proc: 串口协议解析与数据收发"]
NET_P["NET_Proc: 以太网/WIFI 协议栈维护"]
Other_P["其他处理: 模拟量/RTC/存储应用"]
end
Start(("系统上电")) --> MPU["MPU_Config: 内存保护设置(解决 DMA Cache 一致性)"]
MPU --> Cache["使能 I-Cache & D-Cache"]
Cache --> HAL_Init["HAL_Init: 初始化底层库"]
HAL_Init --> SysClock["SystemClock_Config: 时钟树配置(H743 @ 480MHz)"]
SysClock --> APP_Init
APP_Init --> Vars
Vars --> UART_Init
UART_Init --> IO_Init
IO_Init --> Logo
Logo --> Storage
Storage --> Periph
Periph --> Middle
Middle --> Test["硬件自检: 核心存储读写测试"]
Test --> MainLoop
MainLoop --> Cnt
Cnt --> IO_P
IO_P --> UART_P
UART_P --> NET_P
NET_P --> Other_P
Other_P --> MainLoop
3. API 手册#
3.1 DI/DO 操作#
3.1.1 功能使能与引脚定义#
#define LED_EN 1 // 开启 LED 驱动
#define DI_EN 1 // 开启输入扫描 (DI1_PIN 等在下方定义)
#define DO_EN 1 // 开启输出控制 (DO1_PIN 等在下方定义)
#define BUZZER_EN 1 // 开启蜂鸣器
3.1.2 引脚定义#
框架支持多达 32 路 DI/DO。可以直接根据硬件原理图修改引脚映射:
DI 输入:定义引脚及对应的时钟,例如
DI1_PIN对应GPIO_PIN_11。DO 输出:定义引脚及初始状态,支持推挽输出配置。
3.1.3 数字输出 (DO / 继电器)#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
控制单路输出状态 |
|
无 |
|
高效批量同步输出 |
|
无 |
|
翻转指定输出状态 |
|
无 |
|
初始化 数字输出 |
无 |
无 |
3.1.4 数字输入 (DI / 开关量)#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
读取单路物理电平 |
|
|
|
全通道同步读取 |
无 |
|
|
初始化 数字输入 |
无 |
无 |
3.1.5 指示灯与报警器 (LED & Buzzer)#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
翻转 LED (系统心跳灯) |
|
无 |
|
开启蜂鸣器 |
无 |
无 |
|
间歇鸣叫控制 |
无 |
无 |
3.2 UART 串口操作#
3.2.1 功能使能与配置定义#
在 AMKN86xx_Config.h 中,通过宏定义控制各路串口的使能、波特率及功能开关:
#define UART1_EN 1 // 开启 UART1
#define UART1_BAUD 115200 // 设置波特率
#define UART1_RX_EN 1 // 开启接收功能
#define UART1_TX_EN 1 // 开启发送功能
3.2.2 端口定义#
串口 ID:使用
UART1_ID到UART10_ID(UART1~UART10,具体取决于 MCU 型号)标识不同的物理端口。缓冲区配置:每个串口拥有独立的发送/接收环形缓冲区,大小由
UARTx_TXBUF_SIZE宏决定。
3.2.3 串口基础操作#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 串口 |
|
|
|
向指定串口发送数据 |
|
无 |
|
从接收缓冲区读取数据 |
|
|
|
获取当前接收缓冲区数据长度 |
|
|
3.2.4 缓冲区管理#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
清空指定串口的接收缓冲区 |
|
无 |
|
清空指定串口的发送缓冲区 |
|
无 |
|
检查当前发送是否完成 |
|
|
3.3 CAN 通信操作#
3.3.1 功能使能与参数定义#
#define CAN1_EN 1 // CAN1使能, 1:打开, 0:关闭
#define CAN1_BAUD 1000000 // CAN1波特率 (1Mbps)
#define CAN1_SCAN_T 10 // 接收轮询扫描时间间隔 (ms)
#define CAN1_TX_T 1000 // 应用层自动发送测试数据的时间间隔 (ms)
#define CAN2_EN 1 // CAN2使能
#define CAN2_BAUD 1000000 // CAN2波特率 (1Mbps)
3.3.2 引脚与硬件定义#
CAN ID:使用
CAN1_ID和CAN2_ID标识不同的物理端口。硬件接口:STM32H7 系列采用 FDCAN 控制器,支持经典 CAN 和 CAN FD 协议。
3.3.3 CAN 基础操作#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 CAN |
|
|
|
发送一条 CAN 消息 |
|
|
|
从接收缓冲区读取数据 |
|
|
|
获取当前缓冲区未读消息数 |
|
|
3.3.4 消息结构定义#
结构体名称 |
核心成员说明 |
备注 |
|---|---|---|
|
|
用于 |
|
|
用于 |
3.4 ADC 操作#
3.4.1 功能使能与参数定义#
#define ADC_EN 1 // ADC 全局使能 (1:开启, 0:关闭)
#define AI_NUM 8 /* AI 输入端口数量 */
#define AI_SCAN_T 1000 // 定时扫描处理周期 (单位: ms)
#define ADC_AVGNUM 4 // 采样平均次数 (范围 1~64,用于平滑滤波)
#define ADC_SAMPLE_TIME ADC_SAMPLETIME_1CYCLE_5 // 采样间隔配置
3.4.2 量程与引脚配置#
框架支持对每一路 AI 通道进行独立的使能和量程设置。量程(Range)定义了数据的转换逻辑:
通道使能:通过
AIx_EN宏控制(如AI1_EN至AI8_EN)。量程配置:支持多种模式,由
AIx_RANGE宏指定:0: 原始采样值 (0~4095)1: 0~+10V2: -10V~+10V3: 0~5V5: 0~+20mA
3.4.3 核心 API#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 ADC, DMA |
无 |
|
|
从缓冲区读取滤波后的各通道采样值 |
|
|
|
启动 ADC 的 DMA 连续采样模式 |
无 |
|
|
停止 ADC 的 DMA 采样 |
无 |
|
3.5. DAC 操作#
3.5.1 功能使能与参数定义#
#define DAC1_EN 1 // DAC1使能 (AO1)
#define DAC1_MODE 0 // 模式: 0-手动输出; 1-单次波形; 2-持续波形
#define DAC1_FREQ 1000 // 自动输出频率 (Hz)
#define DAC1_SCAN_T 1000 // 定时扫描时间间隔 (ms)
#define DAC2_EN 1 // DAC2使能 (AO2)
#define DAC2_MODE 0 // 模式同上
3.5.3 核心 API (严格对齐源码)#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 DAC |
无 |
|
|
开启指定通道的 DAC 输出转换 |
|
|
|
关闭指定通道的 DAC 输出转换 |
|
|
|
手动输出模式:设置 12 位数值 |
|
|
|
波形模式:启动 DMA 循环发送数据 |
|
|
|
DAC 综合控制接口 (调频、启停) |
|
|
3.6. PWM 操作#
3.6.1 功能使能与参数定义#
#define PWM1_EN 1 // PWM1 使能 (TIM1)
#define PWM1_FREQ 1000 // 初始频率 1kHz
#define PWM1_RATE 500 // 初始占空比 50.0% (范围 0~1000)
#define PWM_SCAN_T 3000 // 应用层自动调整输出的周期 (ms)
3.6.3 核心 API (驱动层接口)#
函数原型 |
功能描述 |
参数说明 |
|---|---|---|
|
初始化 PWM |
无 |
|
开启指定通道的 PWM 输出 |
|
|
停止指定通道的 PWM 输出 |
|
|
动态修改 PWM 的输出频率 |
|
|
修改占空比 |
|
|
一键设置频率与四个通道的占空比 |
|
3.7. FCLK 操作#
3.7.1 功能模式定义#
模式编号 |
模式名称 |
功能描述 |
有效通道 |
|---|---|---|---|
0 |
|
计数模式:记录脉冲总数 |
CH1 |
1 |
|
编码器模式:支持正交编码器 A/B 相计数 |
CH1(A), CH2(B) |
2 |
|
测频模式:测量输入信号频率 (Hz) |
CH1~CH4 |
3 |
|
占空比测量:测量脉冲的占空比百分比 |
CH1 |
3.7.3 核心 API (驱动层接口)#
函数原型 |
功能描述 |
|---|---|
|
初始化 FCLK 对应的定时器硬件及 GPIO 模式。 |
|
读取计数模式下的脉冲计数值。 |
|
读取指定通道的实时频率值(单位:Hz)。 |
|
读取指定通道的 PWM 占空比(0~1000 代表 0.0%~100.0%)。 |
3.9. I2C 操作#
3.9.1 功能模式#
3.9.2 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 I2C |
|
|
|
向寄存器写入单字节 |
|
|
|
批量写入 数据流 |
|
|
|
读取单字节数据 |
|
|
|
批量读取 寄存器 |
|
|
|
检查设备是否在线 |
|
|
3.9.3 关键参数说明#
I2C_ID: 对应硬件物理接口。I2C1_ID: 外部扩展。I2C2_ID: 通常连接板载 EEPROM。RegSize / MemAddress:I2C_MEMADD_SIZE_8BIT: 寄存器地址为 8 位。I2C_MEMADD_SIZE_16BIT: 寄存器地址为 16 位(如大容量 EEPROM)。I2cxTimeout: 驱动内部默认定义为I2C_TIMEOUT_MAX,确保在硬件链路异常时不会导致程序死锁。
3.3. SPI 接口操作#
3.3.1 功能使能与配置定义#
在驱动头文件及配置文件中,通过宏定义精确控制三路 SPI 接口的硬件使能、DMA 模式及超时机制:
硬件开关:通过
SPI1_EN、SPI2_EN、SPI3_EN控制各路 SPI 是否编译进系统。DMA 支持:每路接口均可独立开启 DMA 加速(如
SPI1_DMA_EN),用于大数据量的高速传输。超时控制:定义
SPIx_TIMEOUT_MAX(默认 1000ms),防止由于硬件链路故障导致的程序死锁。
3.3.2 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 SPI |
|
|
|
单向发送 数据流 |
|
|
|
单向接收 数据流 |
|
|
|
全双工 同时读写 |
|
|
|
动态切换 时钟速率 |
|
|
|
批量初始化已启用的 SPI |
无 |
无 |
3.3.4 关键特性说明#
工作模式:默认配置为 主机模式 (Master)、双线全双工、8位数据宽度。
时钟极性/相位:采用 CPOL=1 (High),CPHA=1 (2Edge) 配置,数据在第二个边沿进行采样。
错误自愈机制:内部封装
SPI_Error函数,在通信返回非HAL_OK状态时,会自动尝试HAL_SPI_DeInit并重新执行BSP_SPI_Init以恢复总线。并发保护:通过
SPI_InitFlag标志位确保初始化逻辑在系统运行期间仅执行一次,避免资源冲突。
3.10 RTC 实时时钟操作#
3.10.1 功能使能与配置#
在工程配置文件中,通过宏定义控制 RTC 的硬件使能及任务扫描周期:
#define RTC_EN 1 // RTC 硬件功能使能开关
#define RTC_SCAN_T 1000 // 定时扫描/读取间隔 (单位: ms)
3.10.2 核心 API 定义#
驱动程序提供了完整的日期时间设置、读取以及备份寄存器(BKP)的操作接口:
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 RTC |
无 |
|
|
设置 系统日期与时间 |
|
|
|
读取 当前日期与时间 |
|
|
|
向备份寄存器写入数据 |
|
无 |
|
从备份寄存器读取数据 |
|
|
3.10.3 关键结构体与参数说明#
RTC_TIME结构体定义: 用于统一管理日期和时间数据:year: 年份(相对 2000 年,如 2026 年传 26)month: 月份 (1-12)day: 日期 (1-31)hour: 小时 (0-23)minute: 分钟 (0-59)second: 秒钟 (0-59)weekday: 星期 (1=周一 ~ 7=周日)
3.11 SDIO/SD 卡操作#
3.11.1 功能模式与配置定义#
#define SDCARD_EN 1 // SD卡功能使能 (1: 开启, 0: 关闭)
#define SD_SCAN_T 10 // 定时检测/扫描周期 (单位: ms)
// 工作模式选择
#define SD_MODE_SDCARD 0 // 标准 SD 卡模式
#define SD_MODE_NAND_FLASH 1 // NAND Flash 模式
#define SD_MODE SD_MODE_NAND_FLASH
3.11.3 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 SDMMC 外设及 SD 卡 |
无 |
|
|
读取数据块(同步) |
|
|
|
写入数据块(同步) |
|
|
|
擦除指定范围的数据块 |
|
|
|
获取当前卡传输状态 |
无 |
|
|
SD 卡综合控制/查询接口 |
|
|
3.11.4 关键参数与应用说明#
传输配置:
时钟频率:默认分频系数
ClockDiv = 2。流控:开启硬件流控 (
HardwareFlowControl)。总线宽度:4位模式 (
BusWide = 4B)。状态识别:
MSD_OK (0x00): 操作正常。MSD_ERROR (0x01): 通信异常。MSD_ERROR_SD_NOT_PRESENT (0x02): 未检测到卡。应用逻辑:
在
SD_Proc处理任务中,驱动会根据SD_SCAN_T定时检查卡状态。检测到卡插入后,自动执行
SD_test()进行读写校验,并通过串口输出AT+SD=OK或AT+SD=ERROR信息。
3.14 USBH 操作#
本模块驱动基于 STM32H7 的 USB OTG HS 硬件,配置为 MSC (Mass Storage Class) 主机模式。驱动通过状态机管理 U 盘的从物理连接、枚举到原始扇区通信的全过程,不依赖外部文件系统库。
3.14.3 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 USB 主机库 |
无 |
无 |
|
主机任务进程轮询 |
无 |
无 |
|
读取 U 盘原始扇区 |
|
|
|
写入 U 盘原始扇区 |
|
|
|
获取磁盘物理参数 |
|
|
|
检查磁盘是否准备就绪 |
|
|
3.14.4 应用逻辑与状态管理#
状态机运行机制: USB Host 的核心逻辑由
MX_USB_HOST_Process()驱动,必须在主循环中持续调用。其内部Appli_state决定了当前应用层可执行的操作:APPLICATION_IDLE: 等待 U 盘插入。APPLICATION_START: 硬件层检测到连接,开始 USB 枚举。APPLICATION_READY: 关键状态。此时 MSC 类已激活,允许调用 Read/Write 函数进行数据交换。APPLICATION_DISCONNECT: U 盘被拔出,驱动自动重置状态机并释放资源。应用测试逻辑: 在
USBH_Proc任务中,驱动会实时监控连接状态。一旦检测到状态切换至APPLICATION_READY,会自动触发UDisk_Test()。读写校验:通过原始块读写测试 U 盘的稳定性。
结果输出:成功则串口打印
AT+UDISK=OK,并置位UDISK_OK_FLAG;失败则输出AT+UDISK=ERROR。
3.12 SDRAM 操作#
3.12.1 功能使能与地址映射#
#define SDRAM_ADDR ((uint32_t)0xC0000000) // SDRAM 起始地址 (Bank 5/6)
#define SDRAM_SIZE (32 * 1024 * 1024) // SDRAM 总容量 (32MB)
// 显存与应用缓冲区分配
#define SDRAM_LCD_BUF1 ((uint16_t*)SDRAM_ADDR)
#define SDRAM_LCD_SIZE (4 * 1024 * 1024) // 每层显存大小 (4MB)
#define SDRAM_APP_BUF (SDRAM_ADDR + 8*1024*1024) // 应用数据起始地址
3.12.2 内存布局划分#
区域名称 |
起始地址 |
偏移大小 |
典型用途 |
|---|---|---|---|
LCD_BUF1 |
|
4MB |
显存第 1 层 (Layer 1) |
LCD_BUF2 |
|
4MB |
显存第 2 层 (Layer 2) |
APP_BUF |
|
24MB |
应用程序通用缓冲区 |
3.12.3 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 SDRAM |
无 |
无 |
|
批量写入数据 |
|
无 |
|
批量读取数据 |
|
无 |
|
快速填充/清零 |
|
无 |
|
内存读写校验测试 |
|
|
3.13 LTDC 液晶屏操作#
3.13.1 核心配置与型号适配#
驱动通过宏定义实现对不同分辨率屏幕及显示方向的快速适配,主要参数如下:
型号定义 (
LCD_PRODUCT):0: ATK-MD0700R (800x480 分辨率)1: ATK-MD0700R (1024x600 分辨率)显示旋转 (
LCD_DISP_TYPE):支持 0°、90°、180°、270° 四种显示方向切换。扫描周期 (
LTDC_SCAN_T):默认100ms,用于应用层界面刷新或状态检查。
3.13.2 液晶屏硬件时序 (Timing)#
驱动内置了精准的消隐区时序参数(以 800x480 为例),确保图像在屏幕上精确居中且无闪烁:
时序参数 |
缩写 |
参考值 |
功能说明 |
|---|---|---|---|
Horizontal Sync |
HSYNC |
20 |
行同步脉冲宽度 |
Horizontal Back Porch |
HBP |
46 |
行显示后肩(左边框) |
Horizontal Front Porch |
HFP |
210 |
行显示前肩(右边框) |
Vertical Sync |
VSYNC |
10 |
帧同步脉冲宽度 |
Vertical Back Porch |
VBP |
23 |
帧显示后肩(顶边框) |
Vertical Front Porch |
VFP |
22 |
帧显示前肩(底边框) |
3.13.3 图层架构与显存管理#
驱动采用外部 SDRAM 作为显存(Frame Buffer),支持硬件双图层管理:
图层 1 (Layer 1):全屏背景层。
像素格式:
RGB565(每个像素 16 位,平衡画质与带宽)。起始地址:
0xC0000000(SDRAM 起始位置)。Alpha 混合:默认
0xFF(不透明),支持硬件级透明度调节。显存隔离:每个图层分配
2MB独立空间 (LTDC_BUFFER_SIZE),有效防止多图层操作时的显存溢出。
3.13.4 核心 API 接口定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 LTDC |
无 |
无 |
|
全屏清屏 |
|
无 |
|
绘制点 |
|
无 |
|
读取点颜色 |
|
|
|
矩形填充 |
|
无 |
|
绘制直线 |
|
无 |
|
绘制矩形框 |
|
无 |
|
绘制圆环 |
|
无 |
|
显示字符 |
|
无 |
|
显示字符串 |
|
无 |
|
显示数字 |
|
无 |
|
显示位图 |
|
无 |
|
退出窗口模式 |
|
无 |
3.12 QSPI 操作#
本驱动针对 STM32H7 的 QUADSPI 外设进行了 BSP 级封装。它不仅支持标准的 SPI 指令发送,还通过配置控制逻辑,实现了对外部 Flash 芯片的高速间接访问。
3.12.3 核心 API 定义#
以下 API 屏蔽了复杂的 HAL 库句柄配置,直接面向数据传输和指令交互:
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
QSPI 外设初始化 |
无 |
无 |
|
发送 QSPI 指令 |
|
|
|
发送数据流 |
|
|
|
接收数据流 |
|
|
|
修改时钟频率 |
|
无 |
3.12.4 QSPI 指令传输逻辑 (Command Structure)#
QSPI 的操作核心在于 QSPI_CommandTypeDef 结构体。不同于传统 SPI 只发字节,QSPI 的一次通信被划分为五个阶段,BSP 通过配置这些阶段来适配不同的 Flash 协议:
指令阶段 (Instruction):定义操作码(如读 ID、擦除)。
地址阶段 (Address):发送目标存储地址(支持 24 位或 32 位)。
交替字节阶段 (Alternate Bytes):用于某些 Flash 的连续读取模式设置。
空周期阶段 (Dummy Cycles):在高速读取时,给 Flash 留出切换总线方向的时间(本驱动中双线读取通常设为
4)。数据阶段 (Data):实际承载读取或写入的载荷。
3.12.5 应用逻辑与物理配置#
双线模式逻辑: 根据
QSPI_IOMODE_2_LINES的配置,驱动在地址和数据阶段会启用两根数据线(IO0, IO1)同时传输。这使得带宽比标准单线 SPI 提升了一倍,同时相比四线模式具有更好的电磁兼容稳定性。时钟稳定性调整: 驱动中定义了多种分频系数。根据最新的工程反馈,设置
QSPI_DIVCLK为4(4分频)是兼顾 H7 高主频与外部 Flash 建立/保持时间的最佳平衡点。间接模式 (Indirect Mode): BSP 采用的是“间接模式”。其逻辑是:CPU 将指令、地址和长度填入 QSPI 寄存器后,硬件自动控制 CS 线、产生时钟并完成数据交换。这种方式比软件模拟 SPI 引脚速度快数十倍。
Cache 一致性管理: 由于 QSPI 常结合 DMA 使用,BSP 在高层逻辑中确保了在读取数据前会对相关内存区域进行 Cache 无效化(Invalidate),防止 CPU 读到过期的旧缓存数据。
3.12 QSPI Flash 存储操作#
本模块基于 STM32H7 的 QUADSPI (QSPI) 接口实现,专门用于驱动外部 NorFlash(如 GD25Q64)。驱动支持单线、双线模式,利用 QSPI 的间接模式实现高速数据读写,并集成了自动轮询(Auto-polling)机制以优化写入效率。
3.12.3 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 QSPI 外设 |
无 |
无 |
|
初始化 Flash 芯片 |
无 |
无 |
|
读取数据 (2线模式) |
|
无 |
|
写入数据 (页编程) |
|
无 |
|
扇区擦除 (4KB) |
|
无 |
|
读取芯片 ID |
无 |
|
|
发送自定义命令 |
|
|
3.12.4 关键参数与应用说明#
传输配置:
时钟分频:
QSPI_DIVCLK_4。根据 2025.10.12 的优化建议,4分频在高速通信下更为稳定。IO模式:
QSPI_IOMODE_2_LINES(双线模式)。在BSP_W25QXX_Read中使用 1-2-2 模式(1线指令、2线地址、2线数据),平衡了速度与稳定性。容量定义:固定为
8MB(QSPI_FLASH_SIZE_8MB),匹配 GD25Q64。硬件机制优化:
自动轮询 (Auto-polling):在擦除或编程操作后,驱动调用
BSP_W25QXX_AutoPollingMemReady()。该功能利用 QSPI 硬件自动循环读取 Flash 的状态寄存器,直到BUSY位清零,避免了 CPU 频繁软件查询,显著降低了功耗和 CPU 占用。Dummy Cycles:在双线快速读取模式下配置了
4个空周期,以确保 Flash 芯片有足够时间从地址切换到数据输出。应用逻辑:
写前擦除:NorFlash 物理特性决定了写入前必须先进行擦除(将 0 变为 1)。通常使用
BSP_W25QXX_SectorErase操作 4KB 扇区。页编程限制:每次
BSP_W25QXX_Write写入长度建议不超过 256 字节(一页),若超过需分次写入。
3.13 EEPROM 存储 操作#
本模块驱动基于 STM32H7 的 I2C总线 实现,专门用于驱动外部串行 EEPROM(如 AT24C64)。驱动通过 BSP 层封装,支持跨页连续读写,并集成了硬件忙状态检测机制,确保数据写入的可靠性。
3.13.1 核心 API 定义#
函数原型 |
功能描述 |
参数说明 |
返回值 |
|---|---|---|---|
|
初始化 EEPROM |
无 |
|
|
连续读取数据 |
|
|
|
跨页连续写入 |
|
|
|
单页写入 |
|
|
|
等待就绪 |
无 |
|
3.13.2 关键应用逻辑#
跨页写入算法(Multi-page Write): EEPROM 物理特性限制单次写入不能超过一页(如 32 字节),且不能跨越页边界。
BSP_EEPROM_WriteBuffer内部实现了自动分页逻辑:
计算起始地址在当前页内的偏移。
先填满起始页的剩余空间。
循环处理中间的完整页。
处理最后一页的剩余字节。
3.15 Ethernet 操作#
3.15.1 功能概述与模式配置#
本驱动方案基于 STM32H7 ETH MAC 外设与 DP83848 PHY 芯片,使用 LwIP (Lightweight IP) 开源协议栈。它支持无操作系统(NO_SYS)环境下的 Raw API 编程,能够实现 TCP/UDP 的客户端与服务端通信。
通过 config.h 中的宏定义,可以灵活配置网络的工作模式:
#define LWIP_EN 1 // 协议栈总使能
// 工作模式选择
#define LWIP_WKMODE LWIP_WKMODE_SERVER // 可选: CLIENT(客户端), SERVER(服务端), HTTP(网页)
#define LWIP_NETYPE LWIP_NETYPE_TCP // 可选: TCP, UDP
// 网络地址配置 (静态IP)
#define LOCAL_IP "192.168.1.105" // 本机 IP
#define LOCAL_PORT 5000 // 本机端口
#define LOCAL_GATEWAY "192.168.1.1" // 网关地址
// 目标地址配置 (仅客户端模式有效)
#define DSC_IP "192.168.1.248" // 目标服务器 IP
#define DSC_PORT 5001 // 目标端口
3.15.2 硬件抽象层 (HAL & PHY)#
驱动层 ethernetif.c 实现了 LwIP 与 STM32H7 硬件的对接,主要特性如下:
PHY 接口:使用 RMII (Reduced Media Independent Interface) 接口连接 DP83848,减少引脚占用。
零拷贝接收 (Zero-Copy RX):
定义了专用内存池
RX_POOL和自定义缓冲区RxBuff_t。接收数据时,DMA 直接将数据传输到 LwIP 的 PBUF 内存池中,避免了 CPU 在内存间的数据搬运,显著提高了吞吐量。
DMA 描述符:
DMARxDscrTab和DMATxDscrTab被定义在DMA_SRAM区域(通常为 D2 域的 SRAM),以确保 DMA 控制器可以访问。链路检测:
ethernet_link_check_state()函数周期性读取 PHY 寄存器。若网线热插拔,驱动会自动停止或重启 MAC 外设,实现链路状态的自适应。
3.15.3 核心应用 API 定义#
为了简化 LwIP Raw API 的使用,驱动封装了统一的读写接口,应用层无需直接处理复杂的 PCB (Protocol Control Block) 回调。
1. 通用初始化
函数原型 |
功能描述 |
参数说明 |
|---|---|---|
|
协议栈底层初始化 |
|
|
物理链路状态机维护 |
|
2. TCP 服务端/客户端 (TCP Echo)
函数原型 |
功能描述 |
适用模式 |
|---|---|---|
|
创建 TCP 监听,绑定本地端口 |
TCP Server |
|
连接指定 IP 和端口的服务器 |
TCP Client |
|
从接收缓冲区读取数据 |
TCP Server |
|
发送数据到已连接的客户端 |
TCP Server |
|
读取服务器发来的数据 |
TCP Client |
|
发送数据到服务器 |
TCP Client |
3. UDP 通信
函数原型 |
功能描述 |
适用模式 |
|---|---|---|
|
初始化 UDP 监听 |
UDP Server |
|
绑定目标 IP 端口 |
UDP Client |
|
UDP 数据读写接口 |
UDP Server |
|
UDP 数据读写接口 |
UDP Client |
3.15.4 数据流与缓冲机制#
应用层的数据收发采用了双缓冲或环形缓冲策略来解耦 LwIP 回调与用户逻辑:
接收流程 (Rx):
LwIP 内核调用
tcp_recv或udp_recv回调函数。回调函数将
pbuf中的 payload 数据拷贝到全局缓冲区recev_buf[NET_RECEIVE_BUF_SIZE](默认 2KB)。更新
recev_data_len和recev_count标志位。用户调用
XXX_Read函数从recev_buf取走数据。
发送流程 (Tx):
用户调用
XXX_Write函数。驱动申请一个新的
pbuf,将用户数据填入。调用 LwIP 原生接口
tcp_write或udp_send将数据推入发送队列。对于 TCP,驱动会处理
ERR_MEM(内存不足) 等情况,并在tcp_sent回调中确认发送完成。
3.15.5 关键配置参数 (ethernetif.c)#
ETH_RX_BUFFER_SIZE: 单个 DMA 接收缓冲大小 (1000 Bytes)。ETH_RX_BUFFER_CNT: 接收缓冲数量 (12个)。ETH_DMA_TRANSMIT_TIMEOUT: 发送超时时间 (20ms)。
注意:在 STM32H7 上使用以太网时,由于 D-Cache 的存在,DMA 描述符和缓冲区必须放置在无 Cache 区域(如 SRAM1/2/3)或在操作前后执行 Cache Clean/Invalidate 操作。本驱动在 HAL_ETH_RxLinkCallback 中已包含 SCB_InvalidateDCache_by_Addr 以维护数据一致性。