当前位置: 首页 > news >正文

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;// 配置 DAC1DAC_ConfigChannel(DAC_CHANNEL_1);// 配置 DAC2DAC_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;    // 使能输出// 设置初始值为 0DacaRegs.DACVALS.all = 0;break;case DAC_CHANNEL_2:// 配置 DAC2 控制寄存器DacbRegs.DACCTL.bit.DACREFSEL = 1;   // 内部参考电压DacbRegs.DACCTL.bit.LOADMODE = 0;    // 立即加载DacbRegs.DACCTL.bit.DACOUTEN = 1;    // 使能输出// 设置初始值为 0DacbRegs.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 个 SYSCLKAdcRegs.ADCCTL1.bit.CPS = 0;          // 不分频AdcRegs.ADCCTL1.bit.SUSMOD = 0;       // 自由运行// SOC 配置AdcRegs.ADCSOC0CTL.bit.CHSEL = 0;     // ADCINA0AdcRegs.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.5VDAC_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 示波器验证

  • ADC 输入:用信号源输入 0–3V 正弦波
  • DA 输出:用示波器观察 DAC1OUTA 引脚
  • PWM 触发:观察 EPWM1A 波形

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
http://www.jsqmd.com/news/876654/

相关文章:

  • 并发编程学习-Fork-joinBlockingQueue
  • 如何为旧款iPhone降级:使用Legacy-iOS-Kit完整指南
  • Windows 11下搞定Volume Shadow Copy服务,让Arsenal Image Mounter挂载E01镜像不再报错
  • 终极AI换脸指南:用roop-unleashed实现专业级人脸替换的完整教程
  • 2026年北京包包回收避坑要点,连锁经营门店拒绝恶意压价套路 - 薛定谔的梨花猫
  • 荆门黄金回收靠谱指南|福运来报价透明,稳居推荐榜首 - 黄金回收
  • C#实现Windows安全关机:权限、会话与生产级方案
  • GitHub汉化插件终极指南:3分钟打造中文开发环境,提升协作效率
  • 5分钟搭建你的专属DeepL翻译助手:告别网页翻译烦恼
  • FuzzDistill:基于编译时分析与机器学习的定向模糊测试实践
  • 2026年荆州黄金回收靠谱之选:福运来免费上门,价格透明 - 黄金回收
  • 丽江黄金回收就找福运来,免费上门,价格透明 - 黄金回收
  • XXMI启动器:一站式游戏模组管理平台的完整使用指南
  • 2026年5月泸州黄金回收实测:福运来全城免费上门 - 黄金回收
  • 论文反复修改到心累?导师强推这几个AI论文软件
  • 智能文献翻译革命:如何让Zotero研究效率提升300%
  • 别再死记硬背公式了!用Python手把手实现Model-based强化学习(值迭代/策略迭代对比)
  • Android Studio中文界面汉化实战:从英文焦虑到母语开发的高效转型
  • AI自诊合集
  • 2026二手包包回收店怎么选,东莞正规实体店铺变现稳妥不踩雷 - 薛定谔的梨花猫
  • QMC音频解码器实战指南:高效转换加密格式到通用MP3/FLAC
  • 凉山彝族自治州黄金回收星级口碑榜,福运来实力领跑 - 黄金回收
  • GTA5线上小助手:免费开源工具让你的洛圣都冒险更轻松高效
  • 高效AI论文软件综合榜(2026 真实数据)
  • 量子Gibbs采样技术:原理、实现与应用
  • 哔哩下载姬完整使用指南:免费高效管理B站视频的终极方案
  • 铁臂王张宏武:传奇人生,价值非凡 - mypinpai
  • 范畴论与拓扑斯:为神经网络构建形式化语义与逻辑框架
  • 别再只会Win+R了!用Windows任务计划程序实现每天自动关机,告别熬夜刷剧
  • 基于C51单片机的可调色RGB LED呼吸灯程序