|
|
今天成功的将官方的PA0触发DMA传输的代码改造并跑通了,只不过官方使用的是BDMA,但是原理应该都是一样的。 具体的总结,我就直接把AI的文档贴在这里。
这样距离我完全不用CPU干预,自动采集AD7606数据的功能,更近一步了
# STM32H7 PA0触发DMA传输项目文档
## 项目概述
本项目实现了基于PA0引脚上升沿触发的BDMA自动传输,无需CPU干预。每个触发传输8个半字到GPIOH->ODR,实现PH10引脚的自动翻转。
## 硬件配置
### 主控芯片
- **型号**: STM32H743xx
- **系统时钟**: 400MHz (CPU), 200MHz (HCLK)
### 引脚配置
| 引脚 | 功能 | 配置 | 说明 |
|------|------|------|------|
| PA0 | 输入 | GPIO_MODE_IT_RISING | DMA触发源,上升沿触发 |
| PA8 | 输出 | TIM1_CH1 (AF1) | PWM输出,用于测试触发 |
| PH10 | 输出 | GPIO_OUTPUT_PP | 红色LED,DMA控制翻转 |
| PH11 | 输出 | GPIO_OUTPUT_PP | 绿色LED(备用) |
| PH12 | 输出 | GPIO_OUTPUT_PP | 蓝色LED(备用) |
| PD7 | 输出 | GPIO_OUTPUT_PP | DMA完成指示 |
| PA9 | 输出 | USART1_TX (AF7) | UART发送,调试输出 |
| PA10 | 输入 | USART1_RX (AF7) | UART接收 |
## DMA配置详解
### BDMA Channel 0配置
```c
DMA_Handle.Instance = BDMA_Channel0;
DMA_Handle.Init.Request = BDMA_REQUEST_GENERATOR0;
DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH;
DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE;
DMA_Handle.Init.MemInc = DMA_MINC_ENABLE;
DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; // 16位
DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; // 16位
DMA_Handle.Init.Mode = DMA_CIRCULAR;
DMA_Handle.Init.Priority = DMA_PRIORITY_LOW;
DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
```
### DMAMUX请求生成器配置
```c
dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_EXTI0; // EXTI0信号
dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_RISING; // 上升沿
dmamux_ReqGenParams.RequestNumber = 8; // 每次触发8个请求
```
### 缓冲区配置
```c
// 位于D3 SRAM (0x38000000),BDMA只能访问D3域
const uint16_t SRC_Buffer_LED1_Toggle[128] = {
0, LED_RED_PIN, 0, LED_RED_PIN, ... // 交替模式,64对
};
```
### DMA传输启动
```c
HAL_DMA_Start_IT(&DMA_Handle,
(uint32_t)SRC_Buffer_LED1_Toggle, // 源地址
(uint32_t)&GPIOH->ODR, // 目标地址
128); // 传输128个半字
```
## 工作原理
### 时序图
```
PWM (PA8): ┐ ┐ ┐ ┐ ┐ ┐
│ │ │ │ │ │
└─────┘ └─────┘ └─────┘
100us 100us 100us 100us 100us
触发 (PA0): ┐ ┐ ┐ ┐ ┐ ┐
│ │ │ │ │ │
└─────┘ └─────┘ └─────┘
DMA传输: [0-7] [8-15] [16-23] [24-31] ...
8个半字 8个半字 8个半字
PH10: ×8 ×8 ×8 ×8
快速 快速 快速 快速
翻转 翻转 翻转 翻转
PD7: ┐
┌┘
└─ 16次触发后翻转
```
### 数据流程
1. **PA0上升沿** → EXTI0检测到
2. **EXTI0信号** → DMAMUX请求生成器
3. **RequestNumber=8** → 生成8个DMA请求
4. **BDMA传输** → 从D3 SRAM读取8个半字
5. **写入GPIOH->ODR** → PH10翻转8次
6. **16次触发后** → 128个半字传输完成 → TC中断 → PD7翻转
## 关键配置要点
### 1. D3 SRAM要求
BDMA只能访问D3域的SRAM和外设:
- **D3 SRAM**: 0x38000000 - 0x3800FFFF (64KB)
- **D3外设**: 0x58000000 - 0x5800FFFF
链接脚本必须定义`.RAM_D3`段:
```scatter
RW_IRAM4 0x38000000 0x00010000 {
.RAM_D3 (+RW +ZI)
}
```
### 2. DMAMUX RequestNumber
`RequestNumber`参数控制每个触发信号生成的DMA请求数量:
- `RequestNumber = 8`: 每个PA0上升沿传输8个半字
- `RequestNumber = 1`: 每个PA0上升沿传输1个半字
### 3. 循环模式
`DMA_CIRCULAR`模式下:
- 传输完128个半字后自动从缓冲区开头重新开始
- TC中断在每个完整周期结束时触发
### 4. 中断配置
```c
HAL_DMA_RegisterCallback(&DMA_Handle, HAL_DMA_XFER_CPLT_CB_ID, HAL_TransferComplete);
HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
```
## PWM测试配置 (可选)
PA8输出PWM用于自动测试,连接PA8到PA0:
```c
TIM1时钟: 200MHz
ARR: 19999 (200MHz / 20000 = 10kHz)
CCR1: 2000 (10%占空比)
```
## UART调试输出
UART1配置用于调试:
- **波特率**: 2000000 (2Mbps)
- **数据位**: 8
- **停止位**: 1
- **校验**: 无
启动时自动输出DMA寄存器信息,便于调试。
## DMA寄存器说明
### BDMA Channel 0寄存器
| 寄存器 | 地址 | 说明 |
|--------|------|------|
| CR | 0x58005400 | 控制寄存器 |
| NDTR | 0x58005404 | 剩余传输数量 |
| PAR | 0x58005408 | 外设地址 |
| M0AR | 0x5800540C | 内存0地址 |
### DMAMUX2寄存器
| 寄存器 | 说明 |
|--------|------|
| RGCR0 | 请求生成器0控制寄存器 |
| SIG_ID | 信号ID (EXTI0) |
| NBREQ | 请求数量 (RequestNumber) |
| GPolarity | 极性 (0=上升沿, 1=下降沿) |
| GE | 使能位 |
## 实际应用:AD7606数据采集
本项目可作为AD7606数据采集的参考。AD7606通过FMC SRAM接口连接,需要修改:
### 修改点
1. **触发源**: PA0改为AD7606 BUSY信号(下降沿触发)
2. **触发方式**: 修改`Polarity`为下降沿
3. **数据源**: 从FMC SRAM地址读取,而非D3 SRAM缓冲区
4. **缓冲区**: 扩大到8192 * 2字节
5. **双缓冲**: 实现两个缓冲区交替使用
### 下降沿触发配置
```c
dmamux_ReqGenParams.SignalID = HAL_DMAMUX2_REQ_GEN_EXTI0;
dmamux_ReqGenParams.Polarity = HAL_DMAMUX_REQ_GEN_FALLING; // 改为下降沿
dmamux_ReqGenParams.RequestNumber = 8;
```
## 故障排查
### 问题:DMA传输不工作
**检查清单:**
1. GPIOH时钟是否使能?
2. 缓冲区是否在D3 SRAM (0x38000000)?
3. 链接脚本是否定义了.RAM_D3段?
4. EXTI0是否正确配置为上升沿触发?
5. DMAMUX请求生成器是否使能?
### 问题:传输完成中断不触发
**检查清单:**
1. BDMA Channel 0中断是否使能?
2. TC回调是否正确注册?
3. NVIC优先级是否配置?
4. 传输计数(NDTR)是否递减到0?
## 编译说明
- **IDE**: Keil MDK-ARM
- **编译器**: ARM Compiler 6 (ARMCLANG)
- **目标**: STM32H743xx
完全重新编译项目以确保链接脚本更改生效。
## 文件结构
```
GIPO_DMA/
├── Core/
│ ├── Inc/
│ │ └── main.h
│ └── Src/
│ └── main.c
├── MDK-ARM/
│ └── GIPO_DMA/
│ ├── GIPO_DMA.uvprojx
│ └── GIPO_DMA.sct
├── Drivers/
│ ├── CMSIS/
│ └── STM32H7xx_HAL_Driver/
└── readme.txt
```
## 寄存器的输出值
```
==============================================
DMA Register Dump
=================
=== DMA Handle ===
Instance: 0x58025408
ErrorCode: 0x00000000
State: 2
=== BDMA Channel 0 Registers ===
CNDTR (0x5802540C): 0x00000010
CPAR (0x58025410): 0x58021C14
CM0AR (0x58025414): 0x38000000
=== BDMA Interrupt Status ===
ISR (0x58025400): 0x00000005
GIF0: 1, TCIF0: 0, HTIF0: 1, TEIF0: 0
=== DMAMUX2 Request Generator ===
DMAMUX2 Base: 0x58025800
(RGCR0 at offset 0x100)
=== Buffer Info ===
Buffer Address: 0x38000000
Buffer Size: 128 half-words (256 bytes)
Target Address: 0x58021C14 (GPIOH->ODR)
GPIOH_BASE: 0x58021C00
=== Trigger Configuration ===
Trigger: PA0 (EXTI0 Rising Edge)
DMAMUX: EXTI0 -> BDMA Channel0
RequestNumber: 8 (8 half-words per trigger)
Total Transfers: 128 (16 triggers per complete cycle)
=====================================================
```
## 参考资料
- STM32H743xx Reference Manual
- STM32H7 HAL Driver User Manual
- AN4031: DMA controller introduction
|
|