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.

TMS320F28035-EP: Configuring ADCINT1 as Internal Trigger for Continuous Conversion (No ISR Required)

Part Number: TMS320F28035-EP
Other Parts Discussed in Thread: TMS320F28035, C2000WARE

Tool/software:

Hello,

I’m trying to configure the ADC on the TMS320F28035 to achieve continuous ADC conversions using internal triggering, without involving the CPU interrupt or ISR.

My goal is:

  • Use ADCINT1 to internally retrigger SOC3 after every conversion.
  • Avoid firing an ADC interrupt (no ISR handling).
  • Collect AdcResult.ADCRESULT3 manually in a different function.

 

Below is the configuration I am using: 

    // Configure SOC3 for ADCINA3 (Current Sense IPM ADC)

    AdcRegs.ADCSOC3CTL.bit.ACQPS = 6;   // Set sample-and-hold(S/H) duration to 6 cycles

    AdcRegs.ADCSOC3CTL.bit.CHSEL = 3;   // Select channel ADCINA3

    AdcRegs.ADCINTSOCSEL1.bit.SOC3 = 1; // Trigger SOC3 from ADCINT1

    AdcRegs.INTSEL1N2.bit.INT1SEL = 3;  // EOC3 is trigger for ADCINT1

    AdcRegs.INTSEL1N2.bit.INT1E   = 0;   // Disable CPU interrupt ,only use internal trigger

    AdcRegs.INTSEL1N2.bit.INT1CONT = 1;  // Allow ADCINT1 to retrigger continuously without waiting for flag clear

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear interrupt flag

    AdcRegs.ADCSOCFRC1.bit.SOC3 = 1; // Start the continuous trigger by forcing SOC3 manually once 

This works correctly for the initial conversion on power-up (via forced SOC3), and I get a valid result. However, subsequent conversions are not happening automatically when I change the input voltage. It seems the internal trigger from ADCINT1 to SOC3 isn’t firing again.

 

I also tried the following configuration (thinking interrupt needs to be enabled to function):

AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;     // Set interrupt pulse position to EOC result latch

AdcRegs.INTSEL1N2.bit.INT1E = 1;         // Enable ADCINT1

AdcRegs.INTSEL1N2.bit.INT1CONT = 1;      // Continuous mode

But this caused an illegal ISR trap, likely because I wasn’t handling the ADCINT1 interrupt in PIE (as I don’t want to use an ISR).

Questions:

  1. What is the correct configuration to allow ADCINT1 to continuously trigger SOC3, without requiring a CPU interrupt or ISR?
  2. Does INT1E need to be enabled for the internal trigger to work?
  3. Is INTPULSEPOS = 1 necessary in this scenario?
  4. Are there any known limitations or timing requirements I might be missing?

 Thanks in advance for your help!

  • Hi, 

    I will have to get back to you next week.

    Best Regards,

    Ben Collier

  • Hi, just following up to see if there’s any update on this. Thanks!

  • Hi,

    I apologize about the delay in getting back to you. 

    AdcRegs.INTSEL1N2.bit.INT1E = 1;         // Enable ADCINT1

    Can you try setting this to zero? 

    With the interrupt enabled, the CPU will branch to the stored location for the ISR. Since the location for the ISR is never programmed, it branches to some garbage location and the CPU encounters a fault.

    Best Regards,

    Ben Collier 

  • Hello Ben,

    I tried by setting INT1E to zero but the continuous sampling is not working. Below is my initial configuration (also shared in my above query)

    AdcRegs.ADCSOC3CTL.bit.ACQPS = 6;   // Set sample-and-hold(S/H) duration to 6 cycles

    AdcRegs.ADCSOC3CTL.bit.CHSEL = 3;   // Select channel ADCINA3

    AdcRegs.ADCINTSOCSEL1.bit.SOC3 = 1; // Trigger SOC3 from ADCINT1

    AdcRegs.INTSEL1N2.bit.INT1SEL = 3;  // EOC3 is trigger for ADCINT1

    AdcRegs.INTSEL1N2.bit.INT1E   = 0;   // Disable CPU interrupt ,only use internal trigger

    AdcRegs.INTSEL1N2.bit.INT1CONT = 1;  // Allow ADCINT1 to retrigger continuously without waiting for flag clear

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear interrupt flag

    AdcRegs.ADCSOCFRC1.bit.SOC3 = 1; // Start the continuous trigger by forcing SOC3 manually once

  • Sorry I missed that... let me check this out in more detail

  • Hello,

    Did you get a chance to look at this issue?

  • Can you try something for me? I will be able to look in more detail at the end of this week. 

    Can you try creating an ADC ISR as shown in various examples, and register the ISR as shown here: 

    But then disable the ISR in the PIE, snippet to enable shown here:

  • Ben,

    I did configure the ADC ISR and captured the ADC result inside it. I can confirm that continuous sampling is happening correctly, and I see valid ADC values when I change the input on channel 3 while the program is running.

    However, I don’t want to use the ISR, as it runs too frequently and blocks other time-critical tasks. My goal is to have the ADC perform continuous conversions in the background without relying on an ISR — just let it keep sampling, and I’ll poll the results when needed.

    I need continuous sampling because this ADC channel is used to capture feedback current from the motor for closed-loop control.

  • Hi,

    Can you set the bit to enable the ISR in the PIE to 0? 

    Thanks,

    Ben Collier

  •  Hello,

    If I disable the ADCINT1 in pie (PieCtrlRegs.PIEIER1.bit.INTx1 = 0;), it causes illegal ISR trap.

    We have already discussed this. Check the screenshot below

    To summarize everything I’ve tried so far:

    1. ADCINT disabled (AdcRegs.INTSEL1N2.bit.INT1E = 0) and not configured in the PIE –> No continuous conversion is triggered.

    2. ADCINT enabled (AdcRegs.INTSEL1N2.bit.INT1E = 1) with an ADC ISR configured –> Continuous conversion works, but I want to avoid using ISR, as it blocks other time-critical tasks.

    3. ADCINT enabled (AdcRegs.INTSEL1N2.bit.INT1E = 1) but ISR disabled in the PIE (PieCtrlRegs.PIEIER1.bit.INTx1 = 0) –> This leads to an illegal ISR trap.

    Please refer my first message to check all the register settings

    Thank you

    Mrudu

  • Hello,

    Following up on this since you mentioned you’d be able to look into it by the end of last week. This issue is blocking our project, and several other tasks are dependent on resolving it.

  • Hi,

    I apologize for taking so long to get back about this. I edited our ADC temp sensor conversion example at [C2000WARE]\device_support\f2803x\examples\c28\adc_temp_sensor_conv to do what you were asking. Now ADCSOC1 is triggered continuously by ADCINT1. Edited file is attached.

    //###########################################################################
    //
    // FILE:   Example_2803xAdc_TempSensorConv.c
    //
    // TITLE:  ADC Temperature Sensor Conversion example
    //
    //! \addtogroup f2803x_example_list
    //! <h1> ADC Temperature Sensor Conversion (adc_temp_sensor_conv)</h1>
    //!
    //! This example shows how to convert a raw ADC temperature sensor reading
    //! into deg. C and deg. K. Internal temperature is sampled continuously
    //! through ADCINA5. The coefficients required to compensate for temperature
    //! offset are read from TI OTP.
    //!
    //! \note
    //! THIS EXAMPLE USES VARIABLES STORED IN OTP DURING FACTORY TEST. THESE OTP
    //! LOCATIONS ,0x3D7E90 to 0x3D7EA4, MAY NOT BE POPULATED. ENSURE THAT THESE
    //! MEMORY LOCATIONS IN TI OTP ARE POPULATED WITH VALUES DIFFERENT FROM
    //! 0XFFFF
    //!
    //! \b Watch \b Variables \n
    //!  - temp
    //!  - degC
    //!  - degK
    //
    //###########################################################################
    // $TI Release:  $
    // $Release Date:  $
    // $Copyright:
    // Copyright (C) 2009-2024 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "DSP28x_Project.h"     // DSP28x Headerfile
    
    //
    // Defines
    //
    #define CONV_WAIT 1L //Micro-seconds to wait for ADC conversion.
                         //Longer than necessary.
    
    //
    // Globals
    //
    int16 temp; //raw temperature sensor reading
    int16 degC; //temperature in deg. C
    int16 degK; //temperature in deg. K
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Step 1. Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        // This example function is found in the DSP2803x_SysCtrl.c file.
        //
        InitSysCtrl();
    
        //
        // Step 2. Initialize GPIO:
        // Enable XCLOCKOUT to allow monitoring of oscillator 1
        //
        EALLOW;
        GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3; //enable XCLOCKOUT through GPIO mux
        SysCtrlRegs.XCLK.bit.XCLKOUTDIV = 2; //XCLOCKOUT = SYSCLK
    
        //
        // Step 3. Clear all interrupts and initialize PIE vector table:
        // Disable CPU interrupts
        //
        DINT;
    
        //
        // Initialize PIE control registers to their default state.
        // The default state is all PIE interrupts disabled and flags
        // are cleared.
        // This function is found in the DSP2803x_PieCtrl.c file.
        //
        InitPieCtrl();
    
        //
        // Disable CPU interrupts and clear all CPU interrupt flags:
        //
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        // The shell ISR routines are found in DSP2803x_DefaultIsr.c.
        // This function is found in DSP2803x_PieVect.c.
        //
        InitPieVectTable();
    
        //
        // Step 4. Initialize all the Device Peripherals:
        // Configure and Initialize  the ADC:
        //
        InitAdc();
        AdcOffsetSelfCal();
    
        EALLOW;
        
        //
        // Connect channel A5 internally to the temperature sensor
        //
        AdcRegs.ADCCTL1.bit.TEMPCONV  = 1;  
        
        AdcRegs.ADCSOC0CTL.bit.CHSEL  = 5;  //Set SOC0 channel select to ADCINA5
        AdcRegs.ADCSOC1CTL.bit.CHSEL  = 5;  //Set SOC1 channel select to ADCINA5
    
        AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 1; // Trigger SOC1 from ADCINT1
        AdcRegs.INTSEL1N2.bit.INT1CONT = 1;  // Allow ADCINT1 to retrigger continuously without waiting for flag clear
        
        //
        // Set SOC0 acquisition period to 37 ADCCLK
        //
        AdcRegs.ADCSOC0CTL.bit.ACQPS  = 36; 
        
        //
        // Set SOC1 acquisition period to 37 ADCCLK
        //
        AdcRegs.ADCSOC1CTL.bit.ACQPS  = 36; 
        
        AdcRegs.INTSEL1N2.bit.INT1SEL = 1;  //Connect ADCINT1 to EOC1
        AdcRegs.INTSEL1N2.bit.INT1E  =  1;  //Enable ADCINT1
    
        //
        // Note: two channels have been connected to the temp sensor
        // so that the first sample can be discarded to avoid the
        // ADC first sample issue.  See the device errata.
        //
    
        //
        // Set the flash OTP wait-states to minimum. This is important
        // for the performance of the temperature conversion function.
        //
        FlashRegs.FOTPWAIT.bit.OTPWAIT = 1;
    
        //
        // Main program loop - continually sample temperature
        //
        AdcRegs.ADCSOCFRC1.all = 0x03;
        for(;;)
        {
            //
            // Sample the temp sensor
            //
    
            //
            // Force start of conversion on SOC0 and SOC1
            //
    //        AdcRegs.ADCSOCFRC1.all = 0x03;
    //
    //        //
    //        // Wait for end of conversion.
    //        //
    //        while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0){}  //Wait for ADCINT1
    //        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;        //Clear ADCINT1
    
            //
            // Get temp sensor sample result from SOC1
            //
            temp = AdcResult.ADCRESULT1;
    
            //
            // Convert the raw temperature sensor measurement into temperature
            //
            degC = GetTemperatureC(temp);
            degK = GetTemperatureK(temp);
        }
    }
    
    //
    // End of File
    //
    
    

    Best Regards,

    Ben Collier

  • Ben,

    Thank you for confirming that ADC continuous conversion can work without triggering an ISR. My configuration appears to be similar to yours, but I will review it in detail and work on resolving the issue.

    Thanks again for your support.