DSP28335 多通道ADC采样程序实现

基于 TI DSP28335 芯片的多通道 ADC 采样程序,支持顺序采样和同步采样两种模式,并包含 DMA 传输功能。

程序概述

这个程序实现了以下功能:

  • 多通道ADC初始化配置(支持顺序和同步采样模式)
  • 中断服务程序处理采样数据
  • DMA配置实现自动数据传输
  • PWM触发ADC采样配置
  • 数据转换与处理

核心代码实现

#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#include "math.h"

// 宏定义
#define ADC_MODCLK 0x3     // HSPCLK = SYSCLKOUT/2*ADC_MODCLK = 150/(2*3) = 25.0 MHz
#define ADC_CKPS 0x0       // ADC模块时钟 = HSPCLK/1 = 25.0 MHz
#define ADC_SHCLK 0x1      // 采样保持时间 = 2个ADC周期
#define SAMPLE_NUM 1024    // 采样点数
#define CH_NUM 6           // 采样通道数

// 全局变量
volatile Uint16 AdcBuf[CH_NUM][SAMPLE_NUM];  // ADC采样缓冲区
volatile Uint16 sample_count = 0;            // 采样计数
float32 AdcVoltage[CH_NUM];                  // 转换后的电压值

// ADC初始化函数
void Adc_Init(void)
{
    EALLOW;
    
    // 配置系统时钟
    SysCtrlRegs.HISPCP.all = ADC_MODCLK;  // HSPCLK = SYSCLKOUT/ADC_MODCLK
    
    // 初始化ADC
    InitAdc();
    
    // ADC特定配置
    AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;     // 采样时间选择
    AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;    // ADC内核时钟分频
    AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;           // 1=级联模式(16通道)
    AdcRegs.ADCTRL3.bit.SMODE_SEL = 0;          // 0=顺序采样模式,1=同步采样模式
    
    // 配置采样通道 - 使用6个通道: A0, A1, A2, A3, B0, B1
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;      // ADCINA0
    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;      // ADCINA1
    AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;      // ADCINA2
    AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;      // ADCINA3
    AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4;      // ADCINB0
    AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5;      // ADCINB1
    
    AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = CH_NUM-1; // 设置转换通道数(0起计)
    
    // 中断配置
    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;       // 使能SEQ1中断
    AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0;       // 每个序列结束时产生中断
    
    // 运行模式配置
    AdcRegs.ADCTRL1.bit.CONT_RUN = 1;           // 连续运行模式
    AdcRegs.ADCTRL1.bit.SEQ_OVRD = 1;           // 允许排序器覆盖
    
    EDIS;
}

// DMA初始化函数(用于自动传输ADC数据)
void Dma_Init(void)
{
    volatile Uint16 *DMADest, *DMASource;
    
    // 指向ADC结果寄存器和目标缓冲区
    DMADest = &AdcBuf[0][0];
    DMASource = &AdcMirror.ADCRESULT0;           // 注意:使用ADC镜像寄存器
    
    // DMA通道配置
    DMACH1AddrConfig(DMADest, DMASource);        // 配置DMA源地址和目的地址
    DMACH1BurstConfig(15, 1, 1);                 // 突发配置:每次触发传输16个字
    DMACH1TransferConfig(9, 0, 1);               // 传输配置
    DMACH1WrapConfig(1, 0, 0, 1);                // 环绕配置
    
    // DMA模式配置
    DMACH1ModeConfig(DMA_SEQ1INT, PERINT_ENABLE, ONESHOT_DISABLE,
                     CONT_DISABLE, SYNC_DISABLE, SYNC_SRC,
                     OVRFLOW_DISABLE, SIXTEEN_BIT, CHINT_END, CHINT_ENABLE);
}

// PWM触发ADC采样配置
void PWM_Trigger_Config(void)
{
    // 配置ePWM1作为ADC触发源
    EPwm1Regs.ETSEL.bit.SOCAEN = 1;              // 使能SOCA
    EPwm1Regs.ETSEL.bit.SOCASEL = 4;             // 选择CMPA作为触发源
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;              // 第一次事件产生触发脉冲
    EPwm1Regs.CMPA.half.CMPA = 0x0080;           // 设置比较值
    EPwm1Regs.TBPRD = 0xFFFF;                    // 设置周期值
    
    // 关联PWM触发到ADC
    AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;      // 使能ePWM SOCA触发SEQ1
}

// ADC中断服务程序
interrupt void ADC_ISR(void)
{
    // 读取ADC结果(如果未使用DMA)
    for(int i = 0; i < CH_NUM; i++)
    {
        AdcBuf[i][sample_count] = AdcRegs.ADCRESULT0 >> 4;  // 右移4位获取12位数据
    }
    
    sample_count++;
    if(sample_count >= SAMPLE_NUM)
    {
        sample_count = 0;
    }
    
    // 清除中断标志
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;      // 确认PIE中断
}

// 电压值转换函数
void Convert_To_Voltage(void)
{
    for(int ch = 0; ch < CH_NUM; ch++)
    {
        Uint32 sum = 0;
        
        // 计算平均值
        for(int i = 0; i < SAMPLE_NUM; i++)
        {
            sum += AdcBuf[ch][i];
        }
        
        Uint16 average = sum / SAMPLE_NUM;
        
        // 转换为电压值(假设3.0V参考电压)
        AdcVoltage[ch] = (float)average * 3.0 / 4096.0;
    }
}

// 主函数
void main(void)
{
    // 初始化系统控制
    InitSysCtrl();
    
    // 初始化GPIO(注意:ADC引脚通常不需要特别初始化)
    InitGpio();
    
    // 初始化PIE和中断
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();
    
    // 注册ADC中断
    EALLOW;
    PieVectTable.ADCINT = &ADC_ISR;
    EDIS;
    
    // 使能ADC中断
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
    PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
    IER |= M_INT1;
    EINT;
    
    // 初始化ADC
    Adc_Init();
    
    // 初始化DMA(可选)
    Dma_Init();
    
    // 配置PWM触发(可选)
    PWM_Trigger_Config();
    
    // 启动第一个ADC转换
    AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;
    
    // 主循环
    while(1)
    {
        // 处理采样数据
        if(sample_count == 0)
        {
            Convert_To_Voltage();
            
            // 这里可以添加数据处理代码
            // 例如:发送数据到上位机、执行控制算法等
            
            // 延时一段时间
            DELAY_US(10000);  // 10ms延时
        }
    }
}

关键配置说明

  1. 采样模式选择

    • 顺序采样模式 (SMODE_SEL = 0):通道依次采样,适用于大多数应用场景。
    • 同步采样模式 (SMODE_SEL = 1):ADCINAx和ADCINBx同时采样,适合需要相位一致性的应用(如电机控制)。
  2. DMA配置
    使用DMA可以将ADC结果自动传输到内存,减少CPU开销。配置时需要注意源地址应指向ADC结果镜像寄存器。

  3. PWM触发
    配置ePWM模块触发ADC采样,非常适合电力电子和电机控制应用。

  4. 中断处理
    ADC转换完成后产生中断,在中断服务程序中读取数据或处理DMA传输完成标志。

多通道采样配置表

通道编号 ADC引脚 结果寄存器 典型应用
CONV00 ADCINA0 ADCRESULT0 电压检测
CONV01 ADCINA1 ADCRESULT1 电流检测
CONV02 ADCINA2 ADCRESULT2 温度检测
CONV03 ADCINA3 ADCRESULT3 保留
CONV04 ADCINB0 ADCRESULT4 保留
CONV05 ADCINB1 ADCRESULT5 保留

参考代码 TI的 DSP28335 多通道ADC采样程序 www.youwenfan.com/contentcnh/56837.html

注意

  1. ADC精度与校准

    • DSP28335的ADC模块可能存在固定的偏移误差(约0.2V),在实际应用中需要进行软件校准。
    • 使用内部参考电压时,建议定期进行自校准。
  2. 硬件设计考虑

    • ADC输入引脚不应悬空,悬空引脚会产生噪声并影响其他通道的测量精度。
    • 对于未使用的ADC通道,建议接地或通过电阻连接到固定电压。
    • 前端添加RC滤波电路(如51Ω电阻+2.2nF电容)可以提高抗噪声性能。
  3. 采样速率计算

    • ADC时钟最高为25MHz,单通道转换时间约为80ns(12.5MSPS)。
    • 多通道采样时,总吞吐量会随通道数增加而降低。
    • 实际采样率 = 1 / (采样时间 + 转换时间 × 通道数)
  4. 同步采样限制

    • 真正的同步采样只能发生在A组和B组对应的通道上(如ADCINA0和ADCINB0)。
    • 同步采样模式需要配置SMODE_SEL = 1和相应的通道选择寄存器。
  5. DMA使用提示

    • 确保DMA源地址指向ADC结果镜像寄存器(AdcMirror.ADCRESULT0)而不是直接访问ADCRESULT0。
    • 配置适当的突发大小和传输次数以匹配ADC采样序列。

这个程序提供了一个完整的多通道ADC采样框架。特别是在电力电子和电机控制应用中,结合PWM触发和DMA传输可以实现高效的数据采集和处理。

posted @ 2025-09-23 14:39  别说我的眼泪有点咸  阅读(263)  评论(0)    收藏  举报