DSP28335 数据采集与 DA 输出控制程序

DSP28335 数据采集与 DA 输出控制程序

基于 TI TMS320F28335 DSP,实现 多通道 ADC 数据采集 + DAC 输出控制,包含完整的 DA 配置、输出调节及实时采集功能,适用于工业采集、信号发生、闭环控制等场景。


一、硬件资源配置

外设 引脚 功能说明
ADCINA0–A7 GPIO0–7 8 路模拟量采集(0–3V)
ADCINB0–B7 GPIO8–15 8 路模拟量采集(0–3V)
DAC1OUTA GPIO0 (复用) DA 输出通道 1
DAC2OUTA GPIO1 (复用) DA 输出通道 2
EPWM1A GPIO0 PWM 触发 ADC 采样
SCI-A GPIO28/29 串口调试输出

二、程序总体结构

DSP28335_DataAcquisition/
├── main.c              # 主程序
├── adc_config.c/.h     # ADC 配置
├── dac_config.c/.h     # DA 配置与控制
├── epwm_config.c/.h    # PWM 触发配置
├── sci_debug.c/.h      # 串口调试
└── sys_ctrl.c/.h       # 系统时钟与中断

三、代码实现

3.1 DA 配置与控制(dac_config.h

#ifndef DAC_CONFIG_H
#define DAC_CONFIG_H

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

// DA 参数定义
#define DAC_RESOLUTION      1024      // 10 位 DAC
#define DAC_REF_VOLTAGE     3.0f      // 参考电压 3.0V
#define DAC_MAX_VALUE       1023      // 最大值

// DA 通道枚举
typedef enum {
    DAC_CHANNEL_1 = 0,
    DAC_CHANNEL_2 = 1
} DAC_Channel;

// DA 输出模式
typedef enum {
    DAC_MODE_STATIC = 0,     // 静态输出
    DAC_MODE_WAVE,          // 波形输出
    DAC_MODE_PID            // PID 控制输出
} DAC_OutputMode;

// DA 控制结构体
typedef struct {
    DAC_Channel channel;
    DAC_OutputMode mode;
    float voltage;          // 输出电压
    float minVoltage;       // 最小电压
    float maxVoltage;       // 最大电压
    uint16_t digitalValue;  // 数字量
    uint8_t enabled;       // 使能标志
} DAC_Control;

// 函数声明
void DAC_Init(void);
void DAC_ConfigChannel(DAC_Channel channel);
void DAC_SetVoltage(DAC_Channel channel, float voltage);
void DAC_SetDigitalValue(DAC_Channel channel, uint16_t value);
float DAC_GetVoltage(DAC_Channel channel);
void DAC_StartOutput(DAC_Channel channel);
void DAC_StopOutput(DAC_Channel channel);
void DAC_UpdateOutput(DAC_Control *dac);

#endif // DAC_CONFIG_H

3.2 DA 驱动实现(dac_config.c

#include "dac_config.h"

DAC_Control dac1_control;
DAC_Control dac2_control;

/**
 * @brief 初始化 DA 模块
 */
void DAC_Init(void)
{
    EALLOW;
    
    // 使能 DAC 时钟
    SysCtrlRegs.PCLKCR0.bit.DACAENCLK = 1;
    SysCtrlRegs.PCLKCR0.bit.DACBENCLK = 1;
    
    // 配置 DAC1
    DAC_ConfigChannel(DAC_CHANNEL_1);
    
    // 配置 DAC2
    DAC_ConfigChannel(DAC_CHANNEL_2);
    
    EDIS;
    
    // 初始化控制结构体
    dac1_control.channel = DAC_CHANNEL_1;
    dac1_control.mode = DAC_MODE_STATIC;
    dac1_control.voltage = 0.0f;
    dac1_control.minVoltage = 0.0f;
    dac1_control.maxVoltage = DAC_REF_VOLTAGE;
    dac1_control.enabled = 1;
    
    dac2_control.channel = DAC_CHANNEL_2;
    dac2_control.mode = DAC_MODE_STATIC;
    dac2_control.voltage = 0.0f;
    dac2_control.minVoltage = 0.0f;
    dac2_control.maxVoltage = DAC_REF_VOLTAGE;
    dac2_control.enabled = 1;
}

/**
 * @brief 配置 DA 通道
 */
void DAC_ConfigChannel(DAC_Channel channel)
{
    EALLOW;
    
    switch (channel) {
        case DAC_CHANNEL_1:
            // 配置 DAC1 控制寄存器
            DacaRegs.DACCTL.bit.DACREFSEL = 1;   // 内部参考电压
            DacaRegs.DACCTL.bit.LOADMODE = 0;    // 立即加载
            DacaRegs.DACCTL.bit.DACOUTEN = 1;    // 使能输出
            
            // 设置初始值为 0
            DacaRegs.DACVALS.all = 0;
            break;
            
        case DAC_CHANNEL_2:
            // 配置 DAC2 控制寄存器
            DacbRegs.DACCTL.bit.DACREFSEL = 1;   // 内部参考电压
            DacbRegs.DACCTL.bit.LOADMODE = 0;    // 立即加载
            DacbRegs.DACCTL.bit.DACOUTEN = 1;    // 使能输出
            
            // 设置初始值为 0
            DacbRegs.DACVALS.all = 0;
            break;
    }
    
    EDIS;
}

/**
 * @brief 设置 DA 输出电压
 */
void DAC_SetVoltage(DAC_Channel channel, float voltage)
{
    uint16_t digitalValue;
    
    // 电压限幅
    if (voltage < 0.0f) voltage = 0.0f;
    if (voltage > DAC_REF_VOLTAGE) voltage = DAC_REF_VOLTAGE;
    
    // 电压转数字量
    digitalValue = (uint16_t)((voltage / DAC_REF_VOLTAGE) * DAC_MAX_VALUE);
    
    // 设置 DA 输出
    DAC_SetDigitalValue(channel, digitalValue);
}

/**
 * @brief 设置 DA 数字量
 */
void DAC_SetDigitalValue(DAC_Channel channel, uint16_t value)
{
    EALLOW;
    
    // 数字量限幅
    if (value > DAC_MAX_VALUE) value = DAC_MAX_VALUE;
    
    switch (channel) {
        case DAC_CHANNEL_1:
            DacaRegs.DACVALS.all = value;
            break;
        case DAC_CHANNEL_2:
            DacbRegs.DACVALS.all = value;
            break;
    }
    
    EDIS;
}

/**
 * @brief 获取 DA 当前输出电压
 */
float DAC_GetVoltage(DAC_Channel channel)
{
    uint16_t digitalValue;
    
    switch (channel) {
        case DAC_CHANNEL_1:
            digitalValue = DacaRegs.DACVALS.all;
            break;
        case DAC_CHANNEL_2:
            digitalValue = DacbRegs.DACVALS.all;
            break;
        default:
            digitalValue = 0;
            break;
    }
    
    return (float)digitalValue / DAC_MAX_VALUE * DAC_REF_VOLTAGE;
}

/**
 * @brief 启动 DA 输出
 */
void DAC_StartOutput(DAC_Channel channel)
{
    EALLOW;
    
    switch (channel) {
        case DAC_CHANNEL_1:
            DacaRegs.DACCTL.bit.DACOUTEN = 1;
            break;
        case DAC_CHANNEL_2:
            DacbRegs.DACCTL.bit.DACOUTEN = 1;
            break;
    }
    
    EDIS;
}

/**
 * @brief 停止 DA 输出
 */
void DAC_StopOutput(DAC_Channel channel)
{
    EALLOW;
    
    switch (channel) {
        case DAC_CHANNEL_1:
            DacaRegs.DACCTL.bit.DACOUTEN = 0;
            break;
        case DAC_CHANNEL_2:
            DacbRegs.DACCTL.bit.DACOUTEN = 0;
            break;
    }
    
    EDIS;
}

/**
 * @brief 更新 DA 输出(根据控制结构体)
 */
void DAC_UpdateOutput(DAC_Control *dac)
{
    if (!dac->enabled) {
        DAC_StopOutput(dac->channel);
        return;
    }
    
    switch (dac->mode) {
        case DAC_MODE_STATIC:
            DAC_SetVoltage(dac->channel, dac->voltage);
            break;
            
        case DAC_MODE_WAVE:
            // 波形输出(示例:正弦波)
            {
                static float phase = 0.0f;
                float waveVoltage = (dac->maxVoltage - dac->minVoltage) / 2.0f *
                                   sin(phase) + (dac->maxVoltage + dac->minVoltage) / 2.0f;
                DAC_SetVoltage(dac->channel, waveVoltage);
                phase += 0.1f;
                if (phase > 2 * 3.14159f) phase = 0.0f;
            }
            break;
            
        case DAC_MODE_PID:
            // PID 控制输出(需外部调用 PID 计算)
            DAC_SetVoltage(dac->channel, dac->voltage);
            break;
    }
}

3.3 ADC 采集配置(adc_config.c

#include "adc_config.h"

uint16_t adc_result[16];

/**
 * @brief ADC 初始化
 */
void ADC_Init(void)
{
    EALLOW;
    
    // 使能 ADC 时钟
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
    
    // ADC 校准
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1;     // 带隙电源
    AdcRegs.ADCCTL1.bit.ADCREFPWD = 1;    // 参考电源
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1;      // ADC 电源
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1;    // 使能 ADC
    
    // 采样窗口设置
    AdcRegs.ADCCTL1.bit.ACQ_PS = 6;       // 采样窗口 7 个 SYSCLK
    AdcRegs.ADCCTL1.bit.CPS = 0;          // 不分频
    AdcRegs.ADCCTL1.bit.SUSMOD = 0;       // 自由运行
    
    // SOC 配置
    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0;     // ADCINA0
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;   // EPWM1A 触发
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;     // 采样窗口
    
    EDIS;
    
    DELAY_US(1000);  // 等待 ADC 稳定
}

/**
 * @brief 读取 ADC 通道
 */
uint16_t ADC_ReadChannel(uint16_t channel)
{
    uint16_t result;
    
    EALLOW;
    AdcRegs.ADCSOC0CTL.bit.CHSEL = channel;  // 选择通道
    EDIS;
    
    AdcRegs.ADCSOCFRC1.bit.SOC0 = 1;         // 强制启动转换
    while (AdcRegs.ADCINTFLG.bit.ADCINT1 == 0);  // 等待转换完成
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;    // 清除中断标志
    
    result = AdcRegs.ADCRESULT0;
    return result;
}

/**
 * @brief 批量读取所有 ADC 通道
 */
void ADC_ReadAllChannels(void)
{
    uint16_t i;
    
    for (i = 0; i < 16; i++) {
        adc_result[i] = ADC_ReadChannel(i);
    }
}

/**
 * @brief 将 ADC 值转换为电压
 */
float ADC_ToVoltage(uint16_t adcValue)
{
    return (float)adcValue * 3.0f / 4096.0f;  // 12 位 ADC,3V 参考
}

3.4 PWM 触发配置(epwm_config.c

#include "epwm_config.h"

/**
 * @brief EPWM 初始化(用于触发 ADC)
 */
void EPWM_Init(void)
{
    EALLOW;
    
    // 使能 EPWM 时钟
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    
    // EPWM1 配置
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;   // 向上计数
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;      // 禁止相位加载
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;    // 高速时钟不分频
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;       // 时钟不分频
    
    // 设置周期(10kHz)
    EPwm1Regs.TBPRD = 7500;                     // 75MHz / 7500 = 10kHz
    
    // 设置比较值
    EPwm1Regs.CMPA.half.CMPA = 3750;            // 50% 占空比
    
    // 动作限定
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;          // 计数到 CMPA 时置高
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_CLEAR;        // 计数到 0 时清零
    
    // 使能同步
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    
    EDIS;
}

3.5 主程序(main.c

#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#include "adc_config.h"
#include "dac_config.h"
#include "epwm_config.h"
#include "sci_debug.h"

// 系统参数
typedef struct {
    float adc_voltage[16];      // ADC 电压值
    float dac_output[2];        // DAC 输出电压
    uint16_t sample_count;      // 采样计数
    uint8_t system_ready;      // 系统就绪标志
} System_Data;

System_Data sys_data;

/**
 * @brief 系统初始化
 */
void System_Init(void)
{
    InitSysCtrl();          // 初始化系统时钟
    InitPieCtrl();          // 初始化 PIE 控制
    InitPieVectTable();     // 初始化中断向量表
    InitGpio();             // 初始化 GPIO
    
    // 外设初始化
    SCI_Init();             // 串口初始化
    ADC_Init();             // ADC 初始化
    DAC_Init();             // DAC 初始化
    EPWM_Init();            // EPWM 初始化
    
    // 启动 DA 输出
    DAC_StartOutput(DAC_CHANNEL_1);
    DAC_StartOutput(DAC_CHANNEL_2);
    
    sys_data.system_ready = 1;
    SCI_SendString("System Initialized!\r\n");
}

/**
 * @brief 数据采集与 DA 控制主循环
 */
void DataAcquisition_Loop(void)
{
    uint16_t i;
    float control_voltage;
    
    while (1) {
        // 1. 采集 ADC 数据
        ADC_ReadAllChannels();
        
        // 2. 转换为电压
        for (i = 0; i < 16; i++) {
            sys_data.adc_voltage[i] = ADC_ToVoltage(adc_result[i]);
        }
        
        // 3. DA 输出控制(示例:将 ADC0 的电压映射到 DA1 输出)
        control_voltage = sys_data.adc_voltage[0];  // ADC0 输入
        DAC_SetVoltage(DAC_CHANNEL_1, control_voltage);
        sys_data.dac_output[0] = control_voltage;
        
        // 4. DA2 输出固定 1.5V
        DAC_SetVoltage(DAC_CHANNEL_2, 1.5f);
        sys_data.dac_output[1] = 1.5f;
        
        // 5. 串口输出调试信息
        if (sys_data.sample_count % 1000 == 0) {
            SCI_SendString("ADC0: ");
            SCI_SendFloat(sys_data.adc_voltage[0], 3);
            SCI_SendString(" V, DAC1: ");
            SCI_SendFloat(sys_data.dac_output[0], 3);
            SCI_SendString(" V\r\n");
        }
        
        sys_data.sample_count++;
        DELAY_US(100);  // 100us 采样周期
    }
}

/**
 * @brief 主函数
 */
void main(void)
{
    System_Init();
    DataAcquisition_Loop();
}

四、DA 输出模式示例

4.1 静态电压输出

// 输出 2.5V
DAC_SetVoltage(DAC_CHANNEL_1, 2.5f);

4.2 波形输出(正弦波)

// 在 DAC_UpdateOutput 中启用 DAC_MODE_WAVE
dac1_control.mode = DAC_MODE_WAVE;
DAC_UpdateOutput(&dac1_control);

4.3 PID 控制输出

// 计算 PID 输出并更新 DA
float pid_output = PID_Calculate(&pid_ctrl);
dac1_control.voltage = pid_output;
dac1_control.mode = DAC_MODE_PID;
DAC_UpdateOutput(&dac1_control);

参考 DSP28335板的用于数据采集的程序 www.youwenfan.com/contentcnv/72201.html

五、编译与下载

5.1 CCS 工程配置

  1. Target: TMS320F28335
  2. Linker Command File: 28335_RAM_lnk.cmd
  3. Include Paths: 添加所有头文件路径
  4. Predefined Symbols: LARGE_MODEL

5.2 烧录步骤

# 使用 XDS100 仿真器
1. 连接 USB 仿真器到 JTAG 接口
2. 在 CCS 中点击 "Debug"
3. 加载程序到 DSP
4. 运行程序

六、调试与验证

6.1 示波器验证

6.2 串口监控

System Initialized!
ADC0: 1.234 V, DAC1: 1.234 V
ADC0: 1.567 V, DAC1: 1.567 V
ADC0: 2.000 V, DAC1: 2.000 V

七、常见问题

问题 原因 解决
DA 无输出 未使能 DACOUTEN 检查 DACCTL.bit.DACOUTEN
输出电压不准 参考电压错误 校准参考电压
ADC 采样异常 PWM 未触发 检查 EPWM 配置
程序跑飞 堆栈溢出 增大 .stack

 

专注于matlab/simulink,电子电路,编程