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.

Capture ADC values on a continuous basis

It’s not clear to me what flag needs to be set to schedule an interrupt … want it to interrupt when the ADC is done taking a measurement… the ISR captures the data and then returns to the ADC to measure new info. Here is a snippet of code ... not sure what to set for ADCINT to interrupt.

//-----------------------------------------------------------------------------
void gInitAdc(void)
{
  EALLOW;
  PieVectTable.ADCINT = &IsrAdc;
  EDIS;
  IER |= M_INT1;
  PieCtrlRegs.PIEIER1.bit.INTx6 = 1;

  AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;
  AdcRegs.ADCTRL1.bit.CONT_RUN = 1;
  AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;
}//gInitAdc
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
interrupt void IsrAdc(void)
{
  Uint16 x = AdcRegs.ADCRESULT0;
  PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}//IsrAdc
//-----------------------------------------------------------------------------

  • One way is to use another interrupt to auto trigger the adc.   This could be either a timer or or interrupt of an external input (like an encoder or external clock)

    In my case I was firing the a2d via an external encoder input  but you could easily make it a timer.  I did this on a 2808.

    interrupt void timer_isr(void)  <- could also be "interrupt void xint1_isr(void)"  if an encoder or external clock input.
    {   
        AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;// Toggle bit to initiate Start of Capture on ADC
        // Acknowledge this interrupt to get more from group 1
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }


    interrupt void  adc_isr(void)
    {

        //grab the samples
        samplea=((AdcRegs.ADCRESULT0 >> 4) - 2048);
        sampleb=((AdcRegs.ADCRESULT1 >> 4) - 2048);//and now read & correct actual

        // Reinitialize for next ADC sequence
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit

        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
        return;
    }

  • My understanding is that the ADC value is not correct until it is done measuring the input.  While the timer starts the ADC, what triggers the ISR when the ADC is done?

  • In the situation I described above the triggering interval was much slower than the a/d conversion time, so it was not a concern.

  • You will need to set the interrupt enable for SEQ1 if you are using your example.  This will be the source of your ADC interrupt to the PIE.

    Secondly, the ADC ISR will need to clear the SEQ1 interrupt flag in the ADC to re-arm the interrupt for the next conversion sequence.

    An example of this is in the C280x, C2801x C/C++ Header Files and Peripheral Examples in the <INSTALL_DIR>\tidcs\c28\DSP280x\v170\DSP280x_examples_ccsv4\adc_soc example.

  • I have read the SPRU doc and reviewed the example code.  Exactly, what code changes should be added / modified?

  • The code example that I highlighted in the previous post has the line in it to enable the SEQ1 interrupt from the ADC to propagate to the PIE.

    Upon adding this line of code to your own application, what results do you get?  Are you getting interrupts now after the sequence of ADC conversions?

  • I don't know what code you highlighted ... don't see any highlighting.  Interrupts do not occur.  What needs to be set for ADCINT to interrupt?

     

  • See post dated Mon, Feb 28 2011 10:18 PM.

    The example which I pointed out (perhaps highlighted was a misleading term) provides an illustration of enabling the SEQ1 interrupt and clearing the appropriate status flag in the interrupt service routine.

  • Please post a snippet of code that would work with the code I posted three day ago.

  • I'm having a hard time understanding the disconnect in looking at the one C source file in the aforementioned example in a prior post.

    <INSTALL_DIR>\tidcs\c28\DSP280x\v170\DSP280x_examples_ccsv4\adc_soc\Example_280xAdcSoc.c

    In this file, you will see in the setup code inside main() a statement with comments like "// Enable SEQ1 interrupt (every EOS)"

       AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS)

    In the ADC interrupt service routine of this file, called adc_isr(), you will see a set of statements which are associated with the comment "// Reinitialize for next ADC sequence"

      // Reinitialize for next ADC sequence
      AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1
      AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE

    Please indicate if this is sufficient.  Again, these were directly taken out of the example referenced a couple of times already.

     

  • The example has code that is not relevant.  Thanks for listing the code that is relevant.

    Unfortunately, it still does not work.  While the interrupts are occurring, the data is always 2048 (after shifting it to the right four places) ... I am changing the voltage to AdcIna0 from 0v to 0.2v.  Here is my code:

    //-----------------------------------------------------------------------------
    interrupt void IsrAdc(void)
    {
      uiAdcValue = (AdcRegs.ADCRESULT0 >> 4);

      AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;        
      AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;      
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }//IsrAdc
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    void gInitAdc(void)
    {
      EALLOW;
      PieVectTable.ADCINT = &IsrAdc;
      EDIS;
      IER |= M_INT1;
      PieCtrlRegs.PIEIER1.bit.INTx6 = 1;

      AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0;
      AdcRegs.ADCTRL1.bit.CONT_RUN = 1;
    }//gInitAdc
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    void gStartAdc(void)
    {
      AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1;
      AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;
    }//gStartAdc
    //-----------------------------------------------------------------------------

  • Clyde,

    In my case (where I was triggering the adc through an external interrupt) I was only using two adc channels so I had initialized them accordingly.

    AdcRegs.ADCTRL3.all = 0x00E0;
    //11100000
    //which is band gap ref circ power up, adc powerup
    //and core clock divider = 0 = HSPCLK

    AdcRegs.ADCTRL1.bit.CPS=1;  //divde HSPCLK by 2
    //if we don't do the above the adc clock runs too fast
    //and we get single bit errors in the data.

    AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1
    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA1 as 1st SEQ1 conv.
    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Setup ADCINA0 as 2nd SEQ1 conv.

    Not sure if the above is applicable to your situation but might help.

  • Clyde Eisenbeis said:

    The example has code that is not relevant.  Thanks for listing the code that is relevant.

    Yes, I understand the examples may have other code that is not relevant for your particular use-case.  However, the reason that example was highlighted is that it did illustrate how to configure the ADC to generate interrupts based on the end-of-conversion of Sequencer 1 which was associated with your use-case.

     

    Clyde Eisenbeis said:

    Unfortunately, it still does not work.

    I know this is semantics, but the entire thread has been concentrated on getting interrupts to work, which you next statement indicates is functioning.

     

    Clyde Eisenbeis said:

    While the interrupts are occurring, the data is always 2048 (after shifting it to the right four places) ... I am changing the voltage to AdcIna0 from 0v to 0.2v.

    Reviewing your code that you posted, I do not see where you have powered up the ADC by enabling the bandgap, reference and ADC core itself.  This is described in Section 1.6 of the TMS320x280x 2801x, 2804x Analog-to-Digital Converter(ADC) Module Reference Guide (Rev. D) and how to do this is illustrated in the same example referenced before.  It is not found in the same file however.  Please look at <INSTALL_DIR>\tidcs\c28\DSP280x\v170\DSP280x_common\source\DSP280x_Adc.c.  This defines the InitAdc() routine.

    Keep in mind, you need to wait 5 milliseconds after enabling the above circuitry before using the ADC.

    This might be a contributing reason for the inappropriate conversion results you have observed.