You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dsPIC33EP512GM604 ADC1转换值异常 首次采样准后续偏差大

问题根因

你的ADC配置存在3个核心错误,直接导致连续采样时结果异常:

    1. ADC转换时钟(ADCS)配置违反器件电气规范
      dsPIC33EP系列12位ADC要求转换时钟周期TAD最小为118ns,你将AD1CON3bits.ADCS = 0时,TAD = 1*Tcy(指令周期)。如果芯片运行在常规70MIPS主频下,Tcy≈14.3ns,对应TAD仅14.3ns,远低于最小要求。ADC内部采样保持电容、比较器电路没有足够时间完成电荷建立和转换,第一次转换前你手动延时了25us,电容刚好充到接近真实输入电压,所以第一次结果偏差小,后续连续转换时电路始终处于未建立状态,结果就卡在偏高的固定值。
    1. 采样触发模式和手动操作逻辑冲突
      你配置SSRC = 7对应自动转换模式:硬件会在SAMP位置1后,按照SAMC位设定的采样时长自动计数,到时间后自动清零SAMP位启动转换,不需要手动操作SAMP位。你在代码里手动在置位SAMP后延时5us就清零SAMP,直接打断了硬件自动采样的时序逻辑,导致采样时长完全不满足要求。
    1. 参考电压配置和硬件不匹配
      AD1CON2bits.VCFG = 0b001对应选择外部VREF+引脚作为正参考、AVSS作为负参考,如果你的硬件板卡没有在VREF+引脚连接独立精准参考源、而是打算使用AVDD作为ADC参考,这个配置是错误的,会因为VREF引脚电平不稳定引入额外误差。
  • 额外问题:你代码里的5us采样延时是硬编码值,没有和TAD绑定,一旦主频调整,采样时长就会不满足要求。
修正方案

按以下步骤修改配置即可解决问题:

  1. 重新计算并设置ADCS值,保证TAD在120ns~200ns区间(兼顾速度和精度)。以70MIPS主频为例,Tcy≈14.3ns,根据TAD计算公式TAD = Tcy*(ADCS+1),将ADCS设置为8时,TAD = 9*14.3≈129ns,符合规范。
  2. 如果你要使用手动控制采样启动的逻辑,把SSRC改为0(手动清零SAMP启动转换);如果要使用自动采样模式,就删掉手动清零SAMP和对应的延时代码,等待DONE标志位即可。
  3. 确认硬件参考源连接:如果使用AVDD作为参考,将VCFG改为0b000;如果确实使用外部参考,需在VREF引脚加100nF去耦电容保证电平稳定。
  4. 采样时长通过SAMC位配置(自动模式)或按TAD倍数计算延时(手动模式),保证采样时间至少10个TAD,让采样电容充分充电。
修正后的参考代码
/*  Setup ADC1 for measuring R  */
ANSELBbits.ANSB3 = 1;       // RB3/AN5设为模拟模式
TRISBbits.TRISB3 = 1;        // RB3/AN5设为输入

AD1CON1 = 0;
AD1CON1bits.ADSIDL = 1;      // 空闲模式下停止ADC
AD1CON1bits.AD12B = 1;       // 12位转换模式
AD1CON1bits.FORM = 0;        // 结果为无符号整数格式,右对齐
AD1CON1bits.SSRC = 0;        // 手动清零SAMP位启动转换,和手动操作逻辑匹配
AD1CON2 = 0;
AD1CON2bits.VCFG = 0b000;    // 使用AVDD/AVSS作为参考源,若用外部参考改回0b001
AD1CON2bits.SMPI = 0;        // 每完成1次转换触发中断
AD1CON3=0;
AD1CON3bits.SAMC = 0b11111;  // 自动模式下采样31TAD,手动模式下该位不生效
AD1CON3bits.ADCS = 8;        // 70MIPS下TAD≈129ns,符合电气要求
AD1CON4 = 0;                // 不使用DMA

AD1CHS0bits.CH0NA = 0;      // 负输入选择AVSS
AD1CHS0bits.CH0SA = 5;      // 正输入选择AN5

IFS0bits.AD1IF = 0;         // 清ADC中断标志
IEC0bits.AD1IE = 0;         // 不使能ADC中断
    
/*  Read voltage value  */    
AD1CON1bits.ADON = 1;       // 使能ADC
__delay_us(25);             // 等待ADC上电稳定
for (N=0; N<10; N++) {
    AD1CON1bits.SAMP = 1;   // 启动采样
    __delay_us(2);          // 2us≈15.5TAD,源阻抗<10k时满足采样电容充电要求
    AD1CON1bits.SAMP = 0;   // 手动启动转换
    while (!AD1CON1bits.DONE);  // 等待转换完成
    res[N] = (double) ADC1BUF0;

    /* --- test log ---*/
    sprintf(deb,"ADC1BUF0 = %.0f\r\n", res[N]);
    WriteStringUART1(deb);
    /* ---- end of test ----*/
}

注:如果你的芯片主频不是70MIPS,需要重新按公式计算ADCS值,始终保证TAD≥118ns即可;如果输入信号源阻抗超过10k,需要适当加长采样延时。

内容的提问来源于stack exchange,提问作者Guille

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:24:41