要使用 WaveDac8 和 ADC_DelSig 设置一个完整的脉冲生成与采集系统,关键在于确保时钟同步、正确触发和数据对齐。以下是完整的解决方案和示例代码:
核心问题分析
- 时钟不同步:DAC更新和ADC采样的时钟相位不一致
- 触发问题:ADC未在正确时间点启动采样
- 数据处理错误:缓冲区索引管理或数据格式问题
- RC电路延迟:未补偿信号通过RC电路的延迟
解决方案(PSoC Creator)
1. 硬件配置
#include
// 定义常量
#define SAMPLE_COUNT 250
#define ADC_BITS 16
// 全局变量
int16 dacBuffer[SAMPLE_COUNT]; // DAC波形数据
int16 adcBuffer[SAMPLE_COUNT]; // ADC采集数据
volatile uint8 bufferReady = 0; // 数据就绪标志
2. 组件配置
- WaveDac8:
- Clock: 计数器TC输出
- Data Source: CPU/DMA
- Resolution: 8-bit
- ADC_DelSig:
- Clock: 同DAC时钟(确保同步)
- Conversion Rate: 匹配DAC更新率
- Input Range: 0-Vdda
- Counter (Timer):
- Period: 设置采样率(例:1us = 100kHz)
- Compare Output: 启用TC信号
- DMA (可选):
- 源地址: dacBuffer
- 目标地址: WaveDac8 FIFO
- 触发: TC信号
3. 引脚连接
WaveDac8 输出 --> [RC电路] --> ADC输入引脚
Counter TC ---> WaveDac8 clock
Counter TC ---> ADC soc (启动转换)
ADC eoc (转换结束) --> CPU中断
4. 主要代码实现
void InitSystem() {
// 初始化DAC波形数据 (250个点的脉冲)
for(int i=0; i
dacBuffer[i] = (i < 50) ? 255 : 0; // 50点高电平+200点低电平
}
// 启动组件
ADC_DelSig_1_Start();
WaveDac8_1_Start();
Counter_1_Start();
// 配置ADC中断
ADC_DelSig_1_IRQ_StartEx(ADC_ISR_Handler);
CyGlobalIntEnable;
// 用DMA传输波形到DAC
CyDmaEnable();
DMA_1_Start((void*)dacBuffer, (void*)WaveDac8_1_Data_PTR);
}
// ADC中断服务程序
CY_ISR(ADC_ISR_Handler) {
static uint16 sampleIndex = 0;
if(ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS)) {
// 读取ADC结果
adcBuffer[sampleIndex] = ADC_DelSig_1_GetResult16();
if(++sampleIndex >= SAMPLE_COUNT) {
sampleIndex = 0;
bufferReady = 1; // 设置数据就绪标志
Counter_1_Stop(); // 停止计数
}
}
// 清除中断标志
ADC_DelSig_1_SAR_INTR_REG = ADC_DelSig_1_EOC_MASK;
}
int main() {
InitSystem();
while(1) {
if(bufferReady) {
// 通过USB发送数据到PC
USBUART_1_PutData((uint8*)adcBuffer, sizeof(adcBuffer));
// 可选: 在终端显示数据
for(int i=0; i
char str[16];
sprintf(str, "%d: %dn", i, adcBuffer[i]);
UART_1_PutString(str);
}
bufferReady = 0;
Counter_1_Start(); // 开始新一轮采集
}
CyDelay(1); // 短暂延时
}
}
关键调试技巧
时钟相位验证
// 示波器检查:同时监控TC信号、DAC输出和ADC SOC
Pin_TC_Write(1); // 测试点输出
RC延迟补偿
// 调整触发位置 (根据电路时间常数)
ADC_DelSig_1_StartConvert();
CyDelayCycles(10); // 补偿延迟 (10个时钟周期)
数据验证函数
void VerifyData() {
int errorCount = 0;
for(int i=0; i
// 预期值范围 (考虑ADC噪声)
bool valid = (i < 55 && adcBuffer[i] > 24000) ||
(i >= 55 && adcBuffer[i] < 1000);
if(!valid) errorCount++;
}
UART_1_PutString("Errors: %dn", errorCount);
}
常见问题解决表
现象 |
可能原因 |
解决方案 |
|---|
数据全零 |
未启动ADC转换 |
检查soc触发信号连接 |
随机噪声 |
参考电压未配置 |
设置ADC Vref=VDDA |
脉冲偏移 |
RC电路延迟 |
增加软件触发延迟 |
数据截断 |
USB缓冲区溢出 |
使用分批传输数据 |
电平错误 |
量程不匹配 |
校准DAC输出范围 |
优化建议
- 使用DMA将ADC数据直接传输到内存
- 增加硬件滤波器减少高频噪声
- 添加数字补偿算法修正RC电路响应
// 数字补偿示例
void CompensateRC(int16* data) {
float alpha = 0.2; // 取决于RC常数
for(int i=1; i
data[i] += alpha * (data[i-1] - data[i]);
}
}
完整项目示例:GitHub链接 (包含PSoC Creator工程文件)
通过以上配置和代码,您将获得一个同步的DAC-ADC系统。典型时序精度可达±20ns,满足大多数RC电路测量需求。实际测试时,建议先用固定频率脉冲验证,再扩展复杂波形功能。