TMS320F28335:ADC采样随通道数增加采样数字值也随之增加

用28335的ADC进行差分采样时遇到一个问题:我用ADC的A0和B0同时采两路信号如下图的黄色波形和紫色波形

img


具体是捕获绿色波形的下降沿,进中断触发ADC采样黄色波形和紫色波形8次,ADC采样的配置如下

    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;

但结果却不一致

img

ADC采样的数字值随转换通道编号的增加而增加

我采的为固定电平,ADC采样的数字结果不应该都一致才对嘛,怎么会出现上面的现象呢?求解答

问题解决了,ADC采样端口外有一低通滤波器,滤波器电容有点大导致采样变化

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    该现象可能是由于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中断服务程序之外进行,以免对采样精度产生影响。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^