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.

TMS320F2812: Some questions about the ADC program

Genius 3095 points
Part Number: TMS320F2812

 Hi team:

I have some questions about the ADC program of F2812, wish you can help me:

       DatQ15 = (AdcRegs.ADCRESULT1>>1)&0x7FFF;    // Convert raw result to Q15 (unipolar signal)
        Tmp = (int32)p->Ch2Gain*(int32)DatQ15;      // Tmp = gain*dat => Q28 = Q13*Q15
        p->Ch2Out = (int16)(Tmp>>13);               // Convert Q28 to Q15

1, DatQ15 = (AdcRegs.ADCRESULT1>>1)&0x7FFF;

// This program is to Convert the ADCRESULT1 raw result to Q15 (unipolar signal), but why it need to move the data one bit to the right? And why it &0x7FFF?

2, Tmp = (int32)p->Ch2Gain*(int32)DatQ15;

// Why convert TMP to Q28?

p->Ch2Out = (int16)(Tmp>>13);

// Also why convert ch1out to Q15?

Best regards

  • F.F.
    Is this a specific project or C file provided by TI? If so, please give the source/pjt and I'll take a look at it on my side. There may be some more

    If this is custom code, I can give some input based on what I know of the ADC:

    The ADCResult register is left justfied giving the 12-bit ADC result in the 16-bit word. For Q notation, the ADC Result can be thought of as a Q4 number, even though the fractional portion will always be 0.

    So a bit shift to the right of 1, would make this a Q3 number; the "&" is just to zero out the MSB in case the shift results in something undefined moving in from the "17th" bit posistion.

    At this point I don't think this code is doing what is intended, at least from the comments.

    Furthermore, the ADC result is not a signed number; my only thought here is that if there were a DC Bias on the ADC input, at mid-rail of the converter, you could easliy remove that with a LEFT shift of 1 bit to give an 11-bit answer; but that would be Q5 format.

    We have Q libraries that will perform this type of opertation for you as well, taking nonQ to Q or different Q bases to one another in our IQMath library.

    If you get more detail, I'll be happy to discuss more; but at this point it would be conjecture without more info.

    Best,
    Matthew
  • Dear Matthew

    This routine of adc04u module comes from BLDC3_1 with F2812 chip.


    #include "DSP281x_Device.h"
    #include "f281xadc04u.h"
    #define CPU_CLOCK_SPEED 6.6667L // for a 150MHz CPU clock speed
    #define ADC_usDELAY 5000L
    #define DELAY_US(A) DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_CLOCK_SPEED) - 9.0L) / 5.0L)
    extern void DSP28x_usDelay(unsigned long Count);
    void F281X_adc04u_drv_init(ADCVALS *p)
    {
    DELAY_US(ADC_usDELAY);

    AdcRegs.ADCTRL1.all = ADC_RESET_FLAG; // Reset the ADC Module
    asm(" NOP ");
    asm(" NOP ");
    AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3; // Power up bandgap/reference circuitry
    DELAY_US(ADC_usDELAY); // Delay before powering up rest of ADC

    AdcRegs.ADCTRL3.bit.ADCPWDN = 1; // Power up rest of ADC
    AdcRegs.ADCTRL3.bit.ADCCLKPS = 6; // Set up ADCTRL3 register
    DELAY_US(ADC_usDELAY);
    AdcRegs.ADCTRL1.all = ADCTRL1_INIT_STATE_UNIPOLAR; // Set up ADCTRL1 register
    AdcRegs.ADCTRL2.all = ADCTRL2_INIT_STATE_UNIPOLAR; // Set up ADCTRL2 register
    AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 3; // Specify four conversions
    AdcRegs.ADCCHSELSEQ1.all = p->ChSelect; // Configure channel selection
    EvaRegs.GPTCONA.bit.T1TOADC = 1; // Set up EV Trigger with Timer1 UF
    }
    void F281X_adc04u_drv_read(ADCVALS *p)
    {
    int16 DatQ15;
    int32 Tmp;
    // Wait until ADC conversion is completed
    while (AdcRegs.ADCST.bit.SEQ1_BSY == 1)
    {};
    DatQ15 = (AdcRegs.ADCRESULT0>>1)&0x7FFF; // Convert raw result to Q15 (unipolar signal)
    Tmp = (int32)p->Ch1Gain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
    p->Ch1Out = (int16)(Tmp>>13); // Convert Q28 to Q15
    DatQ15 = (AdcRegs.ADCRESULT1>>1)&0x7FFF; // Convert raw result to Q15 (unipolar signal)
    Tmp = (int32)p->Ch2Gain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
    p->Ch2Out = (int16)(Tmp>>13); // Convert Q28 to Q15
    DatQ15 = (AdcRegs.ADCRESULT2>>1)&0x7FFF; // Convert raw result to Q15 (unipolar signal)
    Tmp = (int32)p->Ch3Gain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
    p->Ch3Out = (int16)(Tmp>>13); // Convert Q28 to Q15
    DatQ15 = (AdcRegs.ADCRESULT3>>1)&0x7FFF; // Convert raw result to Q15 (unipolar signal)
    Tmp = (int32)p->Ch4Gain*(int32)DatQ15; // Tmp = gain*dat => Q28 = Q13*Q15
    p->Ch4Out = (int16)(Tmp>>13); // Convert Q28 to Q15
    AdcRegs.ADCTRL2.all |= 0x4040; // Reset the sequence


    Best regards
  • FF,
    Thanks for the reference source. While I'm not sure about the comments being exact to the specific lines of source code, I beleive that the end calculation is satisfied by the code. Meaning that the ultimate goal of having a signed, 32-bit Q28 number is fulfilled.

    I looked at the signed implemenation and it is a bit more straightforward, so I think the shifts/lack of shifts have something to do with the bias voltage/board settings.

    Best,
    Matthew