尝试在MSPM0G3507实现6路ADC DMA采样。

TI单片机的ADC DMA与FIFO高度绑定,一开始不了解FIFO,以为只是单纯的先进先出队列,后在使用时发现数据错乱的问题。
翻阅数据手册发现

ADC 的 FIFO 总是将两个样本打包成一个 32 位的 Word 数据。当你读取 FIFODAT 寄存器(无论是 CPU 还是 DMA),你总是会得到一个 32 位的 Word

也就是说DMA读取的FIFO结果不能直接使用,需要处理,分离高16位与低16位。

分离示例

void extract_samples(void)
{
    for (int i = 0; i < ADC_FIFO_WORD_COUNT; ++i) {
        uint32_t word = gADCWordBuffer[i];
        gADCSamples[i * 2]     = word & 0xFFFF;
        if ((i * 2 + 1) < ADC_CHANNEL_COUNT) {
            gADCSamples[i * 2 + 1] = (word >> 16) & 0xFFFF;
        }
    }
}

另外sysconfig工具中DMA Samples Count比较有迷惑性。官方文档中对 DMA Samples Count 的定义:

Set number of ADC results to be transferred on a DMA trigger.

它不是指“DMA 一次搬运多少数据”,而是:ADC FIFO 每累计 N 个样本,就触发一次 DMA 请求,而不是采完一个完整序列才触发。

实际应用中与adc采样通道数相同即可(其实只要有值就可以)

Transfer Size项才是真真有用的,因为FIFO将两个样本打包成一个 32 位的 Word 数据,所以Transfer Size应该为样本数的一半。一般建议在主程序调用DL_DMA_setTransferSize实现

全功能示例代码

#include "ti_msp_dl_config.h"

#define ADC_CHANNEL_COUNT 6
#define ADC_FIFO_WORD_COUNT ((ADC_CHANNEL_COUNT + 1) / 2)  // 每个Word打包2个样本

volatile uint32_t gADCWordBuffer[ADC_FIFO_WORD_COUNT]; // 每个word包含两个样本
volatile uint16_t gADCSamples[ADC_CHANNEL_COUNT];      // 提取后的样本数组

void extract_samples(void)
{
    for (int i = 0; i < ADC_FIFO_WORD_COUNT; ++i) {
        uint32_t word = gADCWordBuffer[i];
        gADCSamples[i * 2]     = word & 0xFFFF;
        if ((i * 2 + 1) < ADC_CHANNEL_COUNT) {
            gADCSamples[i * 2 + 1] = (word >> 16) & 0xFFFF;
        }
    }
}

int main(void)
{
    SYSCFG_DL_init();

    // 设置 DMA
    DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) DL_ADC12_getFIFOAddress(ADC12_0_INST));
    DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) gADCWordBuffer);
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, ADC_FIFO_WORD_COUNT);

    // 启用 DMA
    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

    // 启动 ADC 转换
    DL_ADC12_startConversion(ADC12_0_INST);

    while (1) {
        // 每次 DMA 更新完 gADCWordBuffer,手动提取 16位样本
        extract_samples();
        // 你可以在这里使用 gADCSamples[0..2] 的数据

        __NOP();  // 仅用于调试打断点
    }
}

标签: 单片机, TI MSPM0, DMA ADC, FIFO

添加新评论