用28335的ADC进行差分采样时遇到一个问题:我用ADC的A0和B0同时采两路信号如下图的黄色波形和紫色波形
AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK;
AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0x1; //同步采样模式
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; //双排序器模式
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0x7;//最大采样通道
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x0; //使用A0和B0
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x0; //使用A0和B0
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Setup continuous run
采样结果分别放到了下面的变量里:
V_OUTDIFFp1 = AdcRegs.ADCRESULT0>>4;
V_OUTDIFFp2 = AdcRegs.ADCRESULT2>>4;
V_OUTDIFFp3 = AdcRegs.ADCRESULT4>>4;
V_OUTDIFFp4 = AdcRegs.ADCRESULT6>>4;
V_OUTDIFFp5 = AdcRegs.ADCRESULT8>>4;
V_OUTDIFFp6 = AdcRegs.ADCRESULT10>>4;
V_OUTDIFFp7 = AdcRegs.ADCRESULT12>>4;
V_OUTDIFFp8 = AdcRegs.ADCRESULT14>>4;
V_OUTDIFFn1 = AdcRegs.ADCRESULT1>>4;
V_OUTDIFFn2 = AdcRegs.ADCRESULT3>>4;
V_OUTDIFFn3 = AdcRegs.ADCRESULT5>>4;
V_OUTDIFFn4 = AdcRegs.ADCRESULT7>>4;
V_OUTDIFFn5 = AdcRegs.ADCRESULT9>>4;
V_OUTDIFFn6 = AdcRegs.ADCRESULT11>>4;
V_OUTDIFFn7 = AdcRegs.ADCRESULT13>>4;
V_OUTDIFFn8 = AdcRegs.ADCRESULT15>>4;
但结果却不一致
ADC采样的数字值随转换通道编号的增加而增加
我采的为固定电平,ADC采样的数字结果不应该都一致才对嘛,怎么会出现上面的现象呢?求解答
问题解决了,ADC采样端口外有一低通滤波器,滤波器电容有点大导致采样变化
不知道你这个问题是否已经解决, 如果还没有解决的话:该现象可能是由于ADC通道切换时的采样保持时间不同导致的。为了解决这个问题,可以在每次通道切换时,调整采样保持时间来保证采样精度一致。
具体实现方法如下:
// 初始化ADC采样
void adc_init(void) {
// 配置ADC时钟
SysCtrlRegs.LOSPCP.all = 0x0002; // 将LSPCLK设置为80MHz,ADC最大采样速率为2.5Msps
// 选择ADC采样方式,这里选择diff模式
AdcRegs.ADCTRL1.bit.SUSMOD = 3; // 暂停模式下,当且仅当ADCTRL2的ADFM位被置位时有效
AdcRegs.ADCTRL1.bit.ACQ_PS = 63; // 采样保持时间为64个ADC时钟
AdcRegs.ADCTRL1.bit.CPS = 0; // 不分频
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 顺序采样模式
// 配置ADC采样序列,这里指定采样A0和B0两个通道
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // 第一次采样A0通道
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // 第二次采样B0通道
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0; // 第三次采样A0通道
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 1; // 第四次采样B0通道
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0; // 第五次采样A0通道
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 1; // 第六次采样B0通道
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0; // 第七次采样A0通道
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 1; // 第八次采样B0通道
// 启动ADC
AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3; // 为ADC提供参考电压
AdcRegs.ADCTRL1.bit.SEQ_OVRD = 0x8000; // 禁用SEQx_OVRRD寄存器
AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // 连续运行模式
AdcRegs.ADCTRL1.bit.SEQ_ENA = 1; // 启用采样序列
}
// ADC采样中断服务程序
interrupt void adc_isr(void) {
// 读取采样结果
int16 a0_res = AdcResult.ADCRESULT0;
int16 b0_res = AdcResult.ADCRESULT1;
int16 a1_res = AdcResult.ADCRESULT2;
int16 b1_res = AdcResult.ADCRESULT3;
int16 a2_res = AdcResult.ADCRESULT4;
int16 b2_res = AdcResult.ADCRESULT5;
int16 a3_res = AdcResult.ADCRESULT6;
int16 b3_res = AdcResult.ADCRESULT7;
// 处理采样结果
// TODO
// 配置下一次采样,以达到顺序采样的效果
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // 复位SEQ1
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // 启动SEQ1
}
// 在每次通道切换时调整采样保持时间,保证精度一致
interrupt void user_isr(void) {
// 在这里进行通道切换操作
// TODO
// 根据通道编号进行采样保持时间的配置
switch(adc_ch) {
case 0:
AdcRegs.ADCTRL1.bit.ACQ_PS = 63; // 采样保持时间为64个ADC时钟
break;
case 1:
AdcRegs.ADCTRL1.bit.ACQ_PS = 31; // 采样保持时间为32个ADC时钟
break;
case 2:
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // 采样保持时间为16个ADC时钟
break;
case 3:
AdcRegs.ADCTRL1.bit.ACQ_PS = 7; // 采样保持时间为8个ADC时钟
break;
default:
break;
}
}
在上述代码中,我们在user_isr()
中完成通道切换的操作,并在每次通道切换时根据通道编号动态调整采样保持时间。注意到切换通道的操作应该在ADC中断服务程序之外进行,以免对采样精度产生影响。