1. 项目概述
在嵌入式系统开发中,DMA(Direct Memory Access,直接存储器访问)技术是一项至关重要的性能优化手段。本章将基于普中DSP28335开发板,深入探讨如何利用DMA实现ADC采样数据的自动传输,从而释放CPU资源用于其他关键任务。通过本实验,开发者将掌握DMA在TI C2000系列DSP中的实际应用技巧。
2. 核心需求解析
2.1 实验目标
本实验旨在实现ADCINA0通道的模拟信号采样,并通过DMA通道1将转换结果自动传输至指定内存区域。整个过程无需CPU介入数据传输,仅需在DMA传输完成后通过中断通知CPU处理数据。系统通过LED闪烁指示运行状态,开发者可通过CCS调试界面实时观察采样数据。
2.2 技术难点
- DMA与ADC的硬件同步机制
- 内存地址指针的自动增量控制
- 传输过程中的数据一致性保障
- 多任务环境下的资源冲突避免
3. 硬件设计要点
3.1 开发板资源分配
普中DSP28335开发板为本实验提供以下硬件支持:
- 可编程LED(D1)用于系统状态指示
- 12位精度ADC模块(最大采样率12.5MSPS)
- 6个独立DMA通道(本实验使用CH1)
- 片上SARAM(L4-L7)作为数据缓冲区
3.2 关键电路说明
ADC输入电路采用RC滤波设计(R=1kΩ,C=100nF),可有效抑制高频噪声。开发板提供电位器用于模拟信号输入,电压范围0-3V对应ADC采样值0-4095(12位分辨率)。
注意:实际应用中建议在ADC输入端添加保护二极管,防止过压损坏芯片。
4. 软件架构设计
4.1 程序流程图
plaintext复制开始
├─ 系统时钟初始化
├─ 外设时钟使能(ADC/DMA)
├─ ADC模块配置
│ ├─ 采样周期设置
│ ├─ 序列器模式选择
│ └─ 触发源配置
├─ DMA通道初始化
│ ├─ 地址指针设置
│ ├─ 传输参数配置
│ └─ 中断使能
├─ 启动ADC采样
└─ 主循环待机
4.2 内存管理策略
采用双缓冲机制防止数据竞争:
c复制#pragma DATA_SECTION(DMABuf1, "DMARAML4");
volatile Uint16 DMABuf1[DMA_BUF_SIZE];
此配置将缓冲区固定在L4 SARAM区域,确保DMA访问效率。缓冲区大小应根据实际采样需求调整,本例使用40字深度。
5. 关键代码实现
5.1 DMA初始化函数
c复制void DMACH1_ADC_Init(volatile Uint16 *DMA_Dest, volatile Uint16 *DMA_Source)
{
// 时钟使能
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1;
EDIS;
// ADC配置
InitAdc();
AdcRegs.ADCTRL1.bit.ACQ_PS = 0x0F; // 采样窗口=16个SYSCLK周期
AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x01; // ADC时钟=HSPCLK/2
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0; // 单通道转换
// DMA通道配置
DMACH1AddrConfig(DMA_Dest, DMA_Source);
DMACH1BurstConfig(15, 0, 1); // 16字/突发,目标地址自增
DMACH1ModeConfig(DMA_SEQ1INT, PERINT_ENABLE, ONESHOT_DISABLE,
CONT_DISABLE, SYNC_DISABLE, SYNC_SRC,
OVRFLOW_DISABLE, SIXTEEN_BIT, CHINT_END, CHINT_ENABLE);
StartDMACH1();
}
5.2 中断服务程序
c复制interrupt void local_DINTCH1_ISR(void)
{
// 清除中断标志
DmaRegs.DMAINTFLG.bit.INT1 = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
// 数据处理逻辑可在此添加
ProcessADCData(DMABuf1);
}
6. 参数配置详解
6.1 DMA传输模式选择
| 模式选项 | 配置值 | 说明 |
|---|---|---|
| 触发源 | DMA_SEQ1INT | ADC序列器1中断触发 |
| 数据宽度 | SIXTEEN_BIT | 16位传输模式 |
| 突发长度 | 16字 | 每次触发传输16个采样值 |
| 地址增量 | 目标地址+1 | 自动指向下一个存储位置 |
| 中断触发 | CHINT_END | 传输完成后产生中断 |
6.2 ADC关键参数
c复制AdcRegs.ADCTRL1.bit.ACQ_PS = 0x0F; // 采样保持时间=16*SYSCLK
AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x01; // ADC内核时钟=HSPCLK/2
AdcRegs.ADCTRL1.bit.SEQ_CASC = 0; // 双序列器独立模式
7. 调试技巧与问题排查
7.1 CCS调试方法
-
添加变量到Watch窗口:
- 右键点击变量 → Add Watch Expression
- 输入"DMABuf1"观察采样数据
-
实时监控技巧:
- 使用Graph功能可视化数据波形
- 设置Memory Browser查看指定地址数据
7.2 常见问题解决方案
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| DMA不触发 | 时钟未使能 | 检查PCLKCR3.DMAENCLK位 |
| 数据传输出错 | 地址指针配置错误 | 验证SRC/DST_ADDR寄存器值 |
| 采样值不稳定 | ADC输入阻抗不匹配 | 减小信号源输出阻抗 |
| 中断无法进入 | PIE未正确配置 | 检查IER/PIEIER寄存器设置 |
8. 性能优化建议
- 使用32位传输模式:
c复制DMACH1ModeConfig(..., THIRTYTWO_BIT, ...);
可将传输效率提升约50%,但需确保地址按32位对齐。
- 乒乓缓冲策略:
- 配置双缓冲区交替工作
- 在DMA中断中切换活跃缓冲区
- 实现零等待时间的连续采样
- 时钟优化:
c复制SysCtrlRegs.HISPCP.all = 0; // HSPCLK = SYSCLKOUT/1
在满足采样要求的前提下提升ADC时钟频率。
9. 实验现象验证
成功配置后应观察到:
- 开发板D1指示灯以200ms间隔稳定闪烁
- CCS调试窗口中DMABuf1数组显示实时采样值
- 调节电位器时采样值在0-4095范围内线性变化
- CPU利用率显著降低(可通过Profile功能验证)
10. 扩展应用
10.1 多通道采样
修改ADC配置实现多通道轮询:
c复制AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 3; // 4通道转换
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // CH0
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // CH1
// 依次配置其他通道
10.2 内存到内存传输
将外设触发源改为软件触发:
c复制DMACH1ModeConfig(DMA_CPU_T1, ...); // 使用CPU定时器1触发
实现高速数据块搬移功能。
通过本实验的深入学习,开发者可掌握DSP28335的DMA子系统设计精髓,为构建高效实时信号处理系统奠定坚实基础。建议在实际项目中结合具体需求灵活运用乒乓缓冲、优先级调度等高级特性,充分发挥DMA的性能优势。