STM32H7 软件使用手册#

1. 工程目录导航#

驱动层 (Drivers) → 中间件层 (Middlewares) → 应用层 (Projects)

1.1 Drivers (驱动层)#

  • BSP (Board Support Package): 核心层。对底层 HAL 库进行二次封装,提供 UARTDI/DOADC/DACSDRAM 等标准工控接口。

  • Components: 外部元器件驱动(如以太网 PHY LAN8742、存储芯片 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 / 继电器)#

函数原型

功能描述

参数说明

返回值

BSP_DO_Write

控制单路输出状态

DOx: 通道(DO1~DO32),State: 1-吸合, 0-释放

BSP_DO_WriteAll

高效批量同步输出

Value: 32位掩码(bit0=DO1)

BSP_DO_Toggle

翻转指定输出状态

DOx: 通道枚举

BSP_DO_Init

初始化 数字输出

3.1.4 数字输入 (DI / 开关量)#

函数原型

功能描述

参数说明

返回值

BSP_DI_Read

读取单路物理电平

DIx: 通道枚举 (DI1~DI32)

1-高电平, 0-低电平

BSP_DI_ReadAll

全通道同步读取

uint32_t: 32路状态掩码

BSP_DI_Init

初始化 数字输入

3.1.5 指示灯与报警器 (LED & Buzzer)#

函数原型

功能描述

参数说明

返回值

BSP_LED_Toggle

翻转 LED (系统心跳灯)

Led: LED枚举 (如 LED1)

BSP_BUZZER_On

开启蜂鸣器

BSP_BUZZER_Toggle

间歇鸣叫控制


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_IDUART10_ID(UART1~UART10,具体取决于 MCU 型号) 标识不同的物理端口。

  • 缓冲区配置:每个串口拥有独立的发送/接收环形缓冲区,大小由 UARTx_TXBUF_SIZE 宏决定。

3.2.3 串口基础操作#

函数原型

功能描述

参数说明

返回值

BSP_UART_Init

初始化 串口

UART_ID: 串口 ID (UART1_ID ~ UART10_ID)

0-成功, 1-失败

BSP_UART_Write

向指定串口发送数据

UART_ID: 串口 ID, pData: 数据指针, Len: 发送长度

BSP_UART_Read

从接收缓冲区读取数据

UART_ID: 串口 ID, pData: 存储指针, Len: 读取长度

uint32_t: 实际读取到的字节数

BSP_UART_GetRxLength

获取当前接收缓冲区数据长度

UART_ID: 串口 ID

uint32_t: 缓冲区待处理字节数

3.2.4 缓冲区管理#

函数原型

功能描述

参数说明

返回值

BSP_UART_ClearRxBuffer

清空指定串口的接收缓冲区

UART_ID: 串口 ID

BSP_UART_ClearTxBuffer

清空指定串口的发送缓冲区

UART_ID: 串口 ID

BSP_UART_GetTxStatus

检查当前发送是否完成

UART_ID: 串口 ID

1-空闲, 0-忙碌


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_IDCAN2_ID 标识不同的物理端口。

  • 硬件接口:STM32H7 系列采用 FDCAN 控制器,支持经典 CAN 和 CAN FD 协议。

3.3.3 CAN 基础操作#

函数原型

功能描述

参数说明

返回值

BSP_CAN_Init

初始化 CAN

CAN_ID: 通道 ID (CAN1_ID/CAN2_ID)

0-成功, 1-失败

BSP_CAN_Write

发送一条 CAN 消息

CAN_ID: 通道 ID, pTxMsg: 发送结构体指针 (CAN_TX_MSG)

0-成功, 1-失败

BSP_CAN_Read

从接收缓冲区读取数据

CAN_ID: 通道 ID, pRxMsg: 接收结构体指针 (CAN_RX_MSG)

0-成功, 1-无数据

BSP_CAN_GetRxMsgNum

获取当前缓冲区未读消息数

CAN_ID: 通道 ID

uint32_t: 消息数量

3.3.4 消息结构定义#

结构体名称

核心成员说明

备注

CAN_TX_MSG

TxHeader: 发送属性 (ID/长度/格式), Data[8]: 8字节数据

用于 BSP_CAN_Write

CAN_RX_MSG

RxHeader: 接收属性 (ID/时间戳/长度), Data[8]: 8字节数据

用于 BSP_CAN_Read


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_ENAI8_EN)。

  • 量程配置:支持多种模式,由 AIx_RANGE 宏指定:

  • 0: 原始采样值 (0~4095)

  • 1: 0~+10V

  • 2: -10V~+10V

  • 3: 0~5V

  • 5: 0~+20mA

3.4.3 核心 API#

函数原型

功能描述

参数说明

返回值

BSP_ADC_Init

初始化 ADC, DMA

0: 成功, 1: 失败

BSP_ADC_Read

从缓冲区读取滤波后的各通道采样值

pBuf: 指向存储数组的指针, len: 读取通道的数量

0: 成功, 1: 失败

BSP_ADC_DMA_Start

启动 ADC 的 DMA 连续采样模式

0: 成功, 1: 失败

BSP_ADC_DMA_Abort

停止 ADC 的 DMA 采样

0: 成功, 1: 失败


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 (严格对齐源码)#

函数原型

功能描述

参数说明

返回值

BSP_DAC_Init

初始化 DAC

0-成功, 1-失败

BSP_DAC_Start

开启指定通道的 DAC 输出转换

id: 通道 ID (AO1_ID/AO2_ID)

0-成功, 其他-失败

BSP_DAC_Stop

关闭指定通道的 DAC 输出转换

id: 通道 ID

0-成功, 其他-失败

BSP_DAC_SetValue

手动输出模式:设置 12 位数值

id: 通道 ID, Value: 0~4095

0-成功, 其他-失败

BSP_DAC_SetWave

波形模式:启动 DMA 循环发送数据

id: ID, pData: 数据指针, Length: 长度

0-成功, 其他-失败

BSP_DAC_Ctrl

DAC 综合控制接口 (调频、启停)

id: 通道 ID, Cmd: 命令枚举, Value: 参数

0-成功, 其他-失败

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 (驱动层接口)#

函数原型

功能描述

参数说明

BSP_PWM_Init

初始化 PWM

BSP_PWM_Start

开启指定通道的 PWM 输出

pwm_id: PWM1~4_ID, Channel: 通道1~4

BSP_PWM_Stop

停止指定通道的 PWM 输出

pwm_id, Channel

BSP_PWM_ConfigFreq

动态修改 PWM 的输出频率

pwm_id, PWM_Freq (Hz)

BSP_PWM_ConfigDutyCycle

修改占空比

pwm_id, Channel, PWM_Rate (0-1000)

BSP_PWM_Set

一键设置频率与四个通道的占空比

pwm_id, Freq, Rate


3.7. FCLK 操作#

3.7.1 功能模式定义#

模式编号

模式名称

功能描述

有效通道

0

FCLK_MODE_COUNT

计数模式:记录脉冲总数

CH1

1

FCLK_MODE_DECODE

编码器模式:支持正交编码器 A/B 相计数

CH1(A), CH2(B)

2

FCLK_MODE_FREQ

测频模式:测量输入信号频率 (Hz)

CH1~CH4

3

FCLK_MODE_PWMRATE

占空比测量:测量脉冲的占空比百分比

CH1

3.7.3 核心 API (驱动层接口)#

函数原型

功能描述

BSP_FCLK_Init

初始化 FCLK 对应的定时器硬件及 GPIO 模式。

BSP_FCLK_ReadCount

读取计数模式下的脉冲计数值。

BSP_FCLK_ReadFreq

读取指定通道的实时频率值(单位:Hz)。

BSP_FCLK_ReadPwmRate

读取指定通道的 PWM 占空比(0~1000 代表 0.0%~100.0%)。

3.9. I2C 操作#

3.9.1 功能模式#

3.9.2 核心 API 定义#

函数原型

功能描述

参数说明

返回值

BSP_I2C_Init

初始化 I2C

I2C_ID: 实例ID (如 I2C1_ID)

HAL_StatusTypeDef: 状态 (0为OK)

BSP_I2C_WriteData

向寄存器写入单字节

I2C_ID: 实例ID,Addr: 设备地址,Reg: 寄存器地址,Value: 写入数据

HAL_StatusTypeDef: 状态

BSP_I2C_WriteBuffer

批量写入 数据流

I2C_ID: 实例ID,Addr: 设备地址,Reg: 起始地址,RegSize: 地址宽度 (8/16Bit),pBuffer: 数据指针,Length`: 长度

HAL_StatusTypeDef: 状态

BSP_I2C_ReadData

读取单字节数据

I2C_ID: 实例ID,Addr: 设备地址,Reg: 寄存器地址

uint8_t: 读取到的数值

BSP_I2C_ReadMultiple

批量读取 寄存器

I2C_ID: 实例ID,Addr: 设备地址,Reg: 起始地址,MemAddress: 地址宽度,Buffer: 接收缓存指针,Length: 读取长度

HAL_StatusTypeDef: 状态

BSP_I2C_IsDeviceReady

检查设备是否在线

I2C_ID: 实例ID,DevAddress: 设备地址,Trials: 尝试次数

HAL_StatusTypeDef: 状态


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_ENSPI2_ENSPI3_EN 控制各路 SPI 是否编译进系统。

  • DMA 支持:每路接口均可独立开启 DMA 加速(如 SPI1_DMA_EN),用于大数据量的高速传输。

  • 超时控制:定义 SPIx_TIMEOUT_MAX(默认 1000ms),防止由于硬件链路故障导致的程序死锁。

3.3.2 核心 API 定义#

函数原型

功能描述

参数说明

返回值

BSP_SPI_Init

初始化 SPI

SPI_ID: 实例 ID (SPI1_ID ~ SPI3_ID)

HAL_StatusTypeDef: 状态

BSP_SPI_WriteData

单向发送 数据流

SPI_ID: 实例 ID, Data: 数据指针, DataLength: 长度

HAL_StatusTypeDef: 状态

BSP_SPI_ReadData

单向接收 数据流

SPI_ID: 实例 ID, Data: 接收缓存指针, DataLength: 长度

HAL_StatusTypeDef: 状态

BSP_SPI_WriteReadData

全双工 同时读写

SPI_ID: 实例 ID, DataIn: 发送指针, DataOut: 接收指针, DataLength: 长度

HAL_StatusTypeDef: 状态

BSP_SPI_SetSpeed

动态切换 时钟速率

SPI_ID: 实例 ID, val: 1(高速 9MHz) / 0(低速)

HAL_StatusTypeDef: 状态

SPI_APPInit

批量初始化已启用的 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)的操作接口:

函数原型

功能描述

参数说明

返回值

BSP_RTC_Init

初始化 RTC

HAL_StatusTypeDef: 0为OK

BSP_RTCSetDateTime

设置 系统日期与时间

rtc: 指向 RTC_TIME 结构体的指针

HAL_StatusTypeDef: 状态

BSP_RTCGetDateTime

读取 当前日期与时间

rtc: 存储结果的 RTC_TIME 结构体指针

HAL_StatusTypeDef: 状态

BSP_RTC_WriteBackUpFlag

向备份寄存器写入数据

BackUpReg: 寄存器索引, BackUpFlag: 写入值

BSP_RTC_ReadBackUpFlag

从备份寄存器读取数据

BackUpReg: 寄存器索引

uint32_t: 寄存器存储的数值


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 定义#

函数原型

功能描述

参数说明

返回值

BSP_SD_Init

初始化 SDMMC 外设及 SD 卡

HAL_StatusTypeDef: 0为OK

BSP_SD_ReadBlocks

读取数据块(同步)

pData: 缓存指针, ReadAddr: 块地址, NumOfBlocks: 块数量, Timeout: 超时时间

uint8_t: 0为成功

BSP_SD_WriteBlocks

写入数据块(同步)

pData: 缓存指针, WriteAddr: 块地址, NumOfBlocks: 块数量, Timeout: 超时时间

uint8_t: 0为成功

BSP_SD_Erase

擦除指定范围的数据块

StartAddr: 起始地址, EndAddr: 结束地址

uint8_t: 0为成功

BSP_SD_GetCardState

获取当前卡传输状态

uint8_t: 0-就绪, 1-忙碌

BSP_SD_Ctrl

SD 卡综合控制/查询接口

Cmd: 控制命令, pData: 数据指针

uint8_t: 执行结果


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=OKAT+SD=ERROR 信息。

3.14 USBH 操作#

本模块驱动基于 STM32H7 的 USB OTG HS 硬件,配置为 MSC (Mass Storage Class) 主机模式。驱动通过状态机管理 U 盘的从物理连接、枚举到原始扇区通信的全过程,不依赖外部文件系统库。


3.14.3 核心 API 定义#

函数原型

功能描述

参数说明

返回值

MX_USB_HOST_Init

初始化 USB 主机库

MX_USB_HOST_Process

主机任务进程轮询

USBH_MSC_Read

读取 U 盘原始扇区

phost: 句柄, lun: 单元号, address: 扇区地址, pbuf: 缓存, length: 扇区数

USBH_StatusTypeDef

USBH_MSC_Write

写入 U 盘原始扇区

phost: 句柄, lun: 单元号, address: 扇区地址, pbuf: 数据源, length: 扇区数

USBH_StatusTypeDef

USBH_MSC_GetLUNInfo

获取磁盘物理参数

phost: 句柄, lun: 单元号, info: 存储结构体指针

USBH_StatusTypeDef

USBH_MSC_IsReady

检查磁盘是否准备就绪

phost: 主机句柄, lun: 逻辑单元号

1: 就绪, 0: 未就绪


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

0xC0000000

4MB

显存第 1 层 (Layer 1)

LCD_BUF2

0xC0040000

4MB

显存第 2 层 (Layer 2)

APP_BUF

0xC0080000

24MB

应用程序通用缓冲区

3.12.3 核心 API 定义#

函数原型

功能描述

参数说明

返回值

SDRAM_APPInit

初始化 SDRAM

BSP_Sdram_Write

批量写入数据

addr: 目标地址, pbuf: 源数据指针, size: 字节数

BSP_Sdram_Read

批量读取数据

addr: 起始地址, pbuf: 接收指针, size: 字节数

BSP_Sdram_Clear

快速填充/清零

addr: 起始地址, size: 长度, data: 填充值

BSP_FMC_SDRAM_Test

内存读写校验测试

test_addr: 测试地址, test_size: 测试长度

0-成功, -1-失败


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 接口定义#

函数原型

功能描述

参数说明

返回值

BSP_LTDC_Init

初始化 LTDC

LCD_ClearScreen

全屏清屏

color: 填充的颜色值 (RGB565)

LCD_DrawPixel

绘制点

x: X坐标, y: Y坐标, color: 颜色

LCD_ReadPixel

读取点颜色

x: X坐标, y: Y坐标

uint16_t: 颜色值

LCD_FillRect

矩形填充

x0, y0: 左上角坐标; x1, y1: 右下角坐标; color: 颜色

LCD_DrawLine

绘制直线

x1, y1: 起点; x2, y2: 终点; color: 颜色

LCD_DrawRect

绘制矩形框

x1, y1: 左上角; x2, y2: 右下角; color: 颜色

LCD_DrawCircle

绘制圆环

x0, y0: 圆心坐标; r: 半径; color: 颜色

LCD_DispChar

显示字符

x, y: 坐标; num: 字符ASCII码; size: 字号; color: 颜色

LCD_DispString

显示字符串

x, y: 坐标; width, height: 区域限制; size: 字号; p: 字符串指针; color: 颜色

LCD_DispNum

显示数字

x, y: 坐标; num: 数值; len: 位数; size: 字号; color: 颜色

LCD_DispBmp

显示位图

_usX, _usY: 坐标; _usWidth, _usHeight: 宽高; _ptr: 图片数据指针

BSP_LTDC_QuitWinMode

退出窗口模式

width, height: 屏幕宽高; layer: 图层索引


3.12 QSPI 操作#

本驱动针对 STM32H7 的 QUADSPI 外设进行了 BSP 级封装。它不仅支持标准的 SPI 指令发送,还通过配置控制逻辑,实现了对外部 Flash 芯片的高速间接访问。


3.12.3 核心 API 定义#

以下 API 屏蔽了复杂的 HAL 库句柄配置,直接面向数据传输和指令交互:

函数原型

功能描述

参数说明

返回值

QSPI_AppInit

QSPI 外设初始化

QSPI_SendCommand

发送 QSPI 指令

cmd: 指令结构体指针, timeout: 超时时间

int: 0为成功

QSPI_WriteBlocking

发送数据流

data: 源数据指针, timeout: 超时时间

int: 0为成功

QSPI_ReadBlocking

接收数据流

data: 接收缓存指针, timeout: 超时时间

int: 0为成功

QSPI_SetSpeed

修改时钟频率

val: 分频系数 (如 QSPI_DIVCLK_4)


3.12.4 QSPI 指令传输逻辑 (Command Structure)#

QSPI 的操作核心在于 QSPI_CommandTypeDef 结构体。不同于传统 SPI 只发字节,QSPI 的一次通信被划分为五个阶段,BSP 通过配置这些阶段来适配不同的 Flash 协议:

  1. 指令阶段 (Instruction):定义操作码(如读 ID、擦除)。

  2. 地址阶段 (Address):发送目标存储地址(支持 24 位或 32 位)。

  3. 交替字节阶段 (Alternate Bytes):用于某些 Flash 的连续读取模式设置。

  4. 空周期阶段 (Dummy Cycles):在高速读取时,给 Flash 留出切换总线方向的时间(本驱动中双线读取通常设为 4)。

  5. 数据阶段 (Data):实际承载读取或写入的载荷。


3.12.5 应用逻辑与物理配置#

  • 双线模式逻辑: 根据 QSPI_IOMODE_2_LINES 的配置,驱动在地址和数据阶段会启用两根数据线(IO0, IO1)同时传输。这使得带宽比标准单线 SPI 提升了一倍,同时相比四线模式具有更好的电磁兼容稳定性。

  • 时钟稳定性调整: 驱动中定义了多种分频系数。根据最新的工程反馈,设置 QSPI_DIVCLK4(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_AppInit

初始化 QSPI 外设

BSP_W25QXX_Init

初始化 Flash 芯片

BSP_W25QXX_Read

读取数据 (2线模式)

ReadAddr: 地址, NumByteToRead: 长度, pBuffer: 接收缓存

BSP_W25QXX_Write

写入数据 (页编程)

pBuffer: 数据源, WriteAddr: 地址, NumByteToWrite: 长度

BSP_W25QXX_SectorErase

扇区擦除 (4KB)

SectorAddr: 扇区起始地址

BSP_W25QXX_ReadID

读取芯片 ID

uint32_t: 制造商及器件ID

QSPI_SendCommand

发送自定义命令

cmd: 命令结构体, timeout: 超时时间

int: 0为成功


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 定义#

函数原型

功能描述

参数说明

返回值

BSP_EEPROM_Init

初始化 EEPROM

0: 成功; 1: 失败

BSP_EEPROM_ReadBuffer

连续读取数据

pBuffer: 接收缓存, ReadAddr: 起始地址, NumByteToRead: 长度

0: 成功; 其他: 错误

BSP_EEPROM_WriteBuffer

跨页连续写入

pBuffer: 源数据指针, WriteAddr: 起始地址, NumByteToWrite: 长度

0: 成功; 其他: 错误

EEPROM_WritePage

单页写入

pBuffer: 数据, WriteAddr: 页起始地址, NumByteToWrite: 页内长度

0: 成功

EEPROM_WaitStandbyState

等待就绪

0: 芯片空闲; 其他: 忙


3.13.2 关键应用逻辑#

  1. 跨页写入算法(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 描述符

  • DMARxDscrTabDMATxDscrTab 被定义在 DMA_SRAM 区域(通常为 D2 域的 SRAM),以确保 DMA 控制器可以访问。

  • 链路检测

  • ethernet_link_check_state() 函数周期性读取 PHY 寄存器。若网线热插拔,驱动会自动停止或重启 MAC 外设,实现链路状态的自适应。

3.15.3 核心应用 API 定义#

为了简化 LwIP Raw API 的使用,驱动封装了统一的读写接口,应用层无需直接处理复杂的 PCB (Protocol Control Block) 回调。

1. 通用初始化

函数原型

功能描述

参数说明

ethernetif_init

协议栈底层初始化

netif: LwIP 网络接口结构体

ethernet_link_check_state

物理链路状态机维护

netif: 需在主循环中轮询

2. TCP 服务端/客户端 (TCP Echo)

函数原型

功能描述

适用模式

tcp_echoserver_init

创建 TCP 监听,绑定本地端口

TCP Server

tcp_echoclient_connect

连接指定 IP 和端口的服务器

TCP Client

TCP_Server_Read

从接收缓冲区读取数据

TCP Server

TCP_Server_Write

发送数据到已连接的客户端

TCP Server

TCP_Client_Read

读取服务器发来的数据

TCP Client

TCP_Client_Write

发送数据到服务器

TCP Client

3. UDP 通信

函数原型

功能描述

适用模式

udp_echoserver_init

初始化 UDP 监听

UDP Server

udp_echoclient_connect

绑定目标 IP 端口

UDP Client

UDP_Server_Read / Write

UDP 数据读写接口

UDP Server

UDP_Client_Read / Write

UDP 数据读写接口

UDP Client

3.15.4 数据流与缓冲机制#

应用层的数据收发采用了双缓冲环形缓冲策略来解耦 LwIP 回调与用户逻辑:

  1. 接收流程 (Rx)

  • LwIP 内核调用 tcp_recvudp_recv 回调函数。

  • 回调函数将 pbuf 中的 payload 数据拷贝到全局缓冲区 recev_buf[NET_RECEIVE_BUF_SIZE] (默认 2KB)。

  • 更新 recev_data_lenrecev_count 标志位。

  • 用户调用 XXX_Read 函数从 recev_buf 取走数据。

  1. 发送流程 (Tx)

  • 用户调用 XXX_Write 函数。

  • 驱动申请一个新的 pbuf,将用户数据填入。

  • 调用 LwIP 原生接口 tcp_writeudp_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 以维护数据一致性。