This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

28335AD转换幅值的问题

Other Parts Discussed in Thread: REF3020, CONTROLSUITE

你好!

我在用28335做AD转换时,当AD口输入0V时,AdcRegs.ADCRESULT的值>>4位后为0。当AD口输入3V时,AdcRegs.ADCRESULT的值>>4位后为3800。当AD口输入3.2V时,AdcRegs.ADCRESULT的值>>4位后为4095。我看资料上都写输入3V时就到4095,请教是什么原因?基准电压用REF3020为2.048V,AdcRegs.ADCREFSEL.all = 0x4000。我以前用2808没发现这个问题!

谢谢!

  • 请确认一下:

    1. Adc.Regs.ADCRESULT地址是0x7108-0x7117还是0x0B00-0x0B0F?

    2. 是否有做补偿?特别是零偏补偿。

  • 你好:

    1:Adc.Regs.ADCRESULT地址是0x7108-0x7117

    2:未做补偿, AdcRegs.ADCOFFTRIM.all=0x0;

  • 0位是正确的,输入0V,寄存器中的值是0。问题出在输入3V时,寄存器的值不是4095,只有3840这样,差5%左右.

  • 你量一下ADCLO引脚是电压是多少呢?这个测量请用以下两种方法,同时确保量测时转换值确实有偏移:

    1. 以芯片地为基准,分别测试你的实际信号对地的电压,以及ADCLO对地的电压;

    2. 正端接实际信号,负端接ADCLO,看看电压差是多少?

  • 1. ADCLO(43脚)与44脚是连在一起接模拟地的,所以ADCLO对地的电压是0V。当输入3V时,测量43脚与40脚(AD输入口)电压为3V,此时对应AD寄存器AdcRegs.ADCRESULT>>4值为0x3840,与0x4095有很大差距。
    2:正端接实际信号,负端接ADCLO,电压差是3.0V。

  • 有没有参考datasheet中Figure 4-10. ADC Pin Connections With External Reference对相应的引脚进行对比确定是否符合要求,特别是ADCRESEXT,ADCREFP和ADCREFM这几个。

    另外,有没检查一下ADCOFFTRIM寄存器的值是多少?

  • 你好,经确认:

    ADCRESEXT引脚通过22K电阻接到模拟地

    ADCREFP通过一个2.2uF贴片电容接到模拟地

    ADCREFM通过一个2.2uF贴片电容接到模拟地

    ADCOFFTRIM寄存器的值为0,没做偏移。

    当输入0V时,对应AD寄存器AdcRegs.ADCRESULT>>4值为0,提高输入电压,寄存器的值会线性上升。问题就是输入到了3V,寄存器的值到不了4095,差了200多。

  • 当输入电压达到3.2V时,寄存器的值才到4095。万用表和示波器是绝对没问题的,测量精度很高的,示波器5万多刚买来。

  • 补充下:ADCREFIN引脚接外部基准电压2.048V (选用REF3020芯片),AdcRegs.ADCREFSEL.all = 0x4000; 

  • 那么如果施加电压是1.5V呢?1V或2V呢,误差又有多大?

    如果将输入电压从0开始,以每0.73mV(1LSB)增加,ADC结果寄存器的变化状况如何?

  • 你好,测量43脚(接模拟地)与40脚(测试AD口)电压与 寄存器AdcRegs.ADCRESULT8>>4值对比如下:

    电压        AdcRegs.ADCRESULT8>>4
    0.05V        65
    0.1V          129
    0.2V          256
    0.3V          383
    0.4V          512
    0.5V          640
    0.6V          768
    0.7V          895
    0.8V          1025
    0.9V          1150
    1.0V          1275
    1.1V          1400
    1.2V          1530
    1.3V          1660
    1.4V          1780
    1.5V          1913
    1.6V           2040
    1.7V          2160
    1.8V          2295
    1.9V          2420
    2.0V          2540
    2.1V          2668
    2.2V          2803
    2.3V          2925
    2.4V          3053
    2.5V          3181
    2.6V          3300
    2.7V          3430
    2.8V          3555
    2.9V           3692
    3.0V          3820
    3.1V          3940
    3.2V          4072
    3.22V  4095

     

  • 你可能需要量得小一点,特别关注从0开始,每增加1LSB时(对应0.7mV)对应的ADC结果寄存器。

    另外,这是在单片芯片上出现的,还是几颗都这样?有没有试试有例程看结果如何?

    我分析了一下你的数据(见附表),可以看到其实是线性度有偏移,参考ADC手册提到的对gain进行线性补偿应该就准确了,但初始值偏那么大有点说不通。

    New Microsoft Office Excel Worksheet.xlsx
  • 你好:我做了3片板,每片都是同样的现象。请问哪里有28335的AD例程下载,给个链接,谢谢!

  • 那很可能还是硬件上的问题,建议重新量测一下ADC参考以及供电电源。

    例程可以在下面下载,不过建议还是下载controlsuite,里面包含了所有C2000的资料:

    http://www.ti.com/tool/sprc530

  • 你好:

    我从TI网站下载了例程adc_seqmode_test,运行后发现AD转换正常。

    例程AdcRegs.ADCREFSEL.all用的是默认值,读出为1DA4。我把AdcRegs.ADCREFSEL.all设成0x0000,AD转换的值马上发生误差。由此我把使用外部2.048参考电压的AdcRegs.ADCREFSEL.all=0x5DA4,这样用外部2.048V做参考电压,AD转换值就正常了。请问AdcRegs.ADCREFSEL.all这个寄存器第15和14位是参考电压选择位,其他的位代表什么意思?文档里我找不到说明。谢谢!另外以前用2808时AdcRegs.ADCREFSEL.all=0x4000,AD一直正常

  • 寄存器定义里提到如下说明,代表的意思应该就是内部校准相关的。

    如果你写入0x5DA4可以的话,那就这样处理吧,或者你可以试试AdcRegs.ADCREFSEL.bit.REF_SEL = 1;看看。后者可行的话建议使用后者。

    These bits are reserved for reference calibration data loaded from the Boot ROM. All writes to the ADCREFSEL register should leave the contents of this bit field as is after population by the Boot ROM.

  • Hi  Chen

      你看的那个资料有点旧了

    你可以看看这个!!

    f28027 adc.pdf
  • 我在用F28027的ADC用于采样交流电压和交流电流时也遇到了这种问题,采样得到的结果不稳定,也不太准确!要进行怎么样的处理呢??

  • 不要误导楼主,F2833x的采样范围是0~3V,不同于Piccolo的0~3.3V.

    另外,建议你新建一个帖子提问。

    结果不稳定时,需要确保你的输入信号本身是否稳定,然后看看结果寄存器里的值到底有多大偏差?

    ADC初始化是否正确?这可以参考TI提供的例程进行比较。

    你也可以直接使用例程测试一下。

     

  • 你好,问题已找到。原因在于以前一直用的是2808,2808的AdcRegs.ADCREFSEL.all寄存器从rom读出值基本为0,所以用外部2.048做基准赋值#0X4000没问题。而28335的AdcRegs.ADCREFSEL.all寄存器值为1A54左右,这样就不能直接赋值0X4000。用AdcRegs.ADCREFSEL.bit.REF_SEL=1 这样操作就没问题,AD读出的值处理后很稳定,完全可以达到千分之一的精度。

    谢谢!

  • 你好 请问你的ad精度达到千分之一是怎么弄出来的 

    加了低通滤波吗?  我这飘得狠  用的内部参考  

    难道是参考源的问题吗?  等候解答啊

  • 楼上可否把你初始化AD的函数赛出来,我也想采用28335的AD外部基准,设置了AdcRegs.ADCREFSEL.bit.REF_SEL=1,还是不对

  • extern void DSP28x_usDelay(Uint32 Count);

     AdcRegs.ADCTRL3.all = 0x00c0;  // Power up bandgap/reference/ADC circuits
        DELAY_US(ADC_usDELAY);         // Delay before converting ADC channels
     AdcRegs.ADCTRL3.bit.ADCPWDN = 0x1;
     DELAY_US(ADC_20usDELAY);
     
     EALLOW;
        #if (CPU_FRQ_150MHZ)     // Default - 150 MHz SYSCLKOUT
         #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3)   = 25.0 MHz
       #endif
       #if (CPU_FRQ_100MHZ)
         #define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2)   = 25.0 MHz
        #endif
        EDIS;
        // *IMPORTANT*
     // The ADC_cal function, which  copies the ADC calibration values from TI reserved
     // OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the
     // Boot ROM. If the boot ROM code is bypassed during the debug process, the
     // following function MUST be called for the ADC to function according
     // to specification. The clocks to the ADC MUST be enabled before calling this
     // function.
     // See the device data manual and/or the ADC Reference
     // Manual for more information.

     EALLOW;
     SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; //使能ADC外设内部高速时钟(HSPCLK)
     ADC_cal();
     SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0;
     EDIS;
      
       PieVectTable.SEQ1INT = &adc_isr;
     EDIS;
     PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
     IER |= M_INT1; 

     AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x1;
      //ADCTRL2 Inition
        AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;// Enable SOCA from ePWM to start SEQ1
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)
     AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;
     AdcRegs.ADCTRL2.bit.SOC_SEQ1 =1;
     //ADCTRL1 Inition
      AdcRegs.ADCTRL1.bit.ACQ_PS =0x01 ;
     AdcRegs.ADCTRL1.bit.CPS = 1;
     AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;
     AdcRegs.ADCTRL1.bit.CONT_RUN = 0; 

     AdcRegs.ADCREFSEL.bit.REF_SEL = 0;
     AdcRegs.ADCOFFTRIM.bit.OFFSET_TRIM = 0;
     // Configure ADC
        AdcRegs.ADCMAXCONV.all = 0x000f;       // Setup 16 conv's on SEQ1
        AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;
        AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1;
        AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2;
        AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3;   
        AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4;
        AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5;
        AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6;
        AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7;
        AdcRegs.ADCCHSELSEQ3.bit.CONV08 = 0x8;
        AdcRegs.ADCCHSELSEQ3.bit.CONV09 = 0x9;
        AdcRegs.ADCCHSELSEQ3.bit.CONV10 = 0xa;
        AdcRegs.ADCCHSELSEQ3.bit.CONV11 = 0xb;
        AdcRegs.ADCCHSELSEQ4.bit.CONV12 = 0xc;
        AdcRegs.ADCCHSELSEQ4.bit.CONV13 = 0xd;
        AdcRegs.ADCCHSELSEQ4.bit.CONV14 = 0xe;
        AdcRegs.ADCCHSELSEQ4.bit.CONV15 = 0xf;
    // Assumes ePWM1 clock is already enabled in InitSysCtrl();
        EPwm1Regs.ETSEL.bit.SOCAEN = 1;        // Enable SOC on A group
        EPwm1Regs.ETSEL.bit.SOCASEL = 2;       // Select SOC from from period
      
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;        // Generate pulse on 1st event
     EPwm1Regs.ETPS.bit.SOCACNT = 1;
    // EPwm1Regs.ETFLG.bit.SOCA = 1;
    // EPwm1Regs.ETCLR.bit.SOCA = 1;
    // EPwm1Regs.ETFRC.bit.SOCA = 1;

     //   EPwm1Regs.CMPA.half.CMPA = 0x0080;   // Set compare A value
        EPwm1Regs.TBPRD = 0x271;              // Set period for ePWM1
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;    // count up and start
     EPwm1Regs.TBCTL.bit.CLKDIV = 0;           //default clk=1
    // EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1;
    // EPwm1Regs.CMPCTL.bit.LOADAMODE= 0;
    // EPwm1Regs.CMPCTL.bit.SHDWAMODE= 1;