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.

MSPM0G3507: IRQHandler for ADC0

Part Number: MSPM0G3507

Tool/software:

Im back to this ADC code in the new MSPM0G3507 But im not sure if I need

#include "ti/devices/msp/m0p/mspm0g350x.h"
#include "ti/driverlib/dl_adc12.h"
#include "ti/driverlib/dl_common.h" // For DL_Common_delayCycles function
#include "ti_msp_dl_config.h"
#include "IndexMacros.h"
#include "stdio.h"
uint16_t threshold = 1;//16384 / 2; // VCC/2 or 1.15V
int i=0;
int j=0;

int main (void)
{

  ADC0->ULLMEM.GPRCM.CLKCFG = 0xA9000000; // ULPCLK
  ADC0->ULLMEM.CLKFREQ = 7;               // 40-48 MHz
  ADC0->ULLMEM.CTL0 = 0x03010000;         // divide by 8
  ADC0->ULLMEM.CTL1 = 0x00000000;         // mode
  ADC0->ULLMEM.CTL2 = 0x00000000;         // MEMRES
  ADC0->ULLMEM.MEMCTL[0] = 3;             // channel 3 PA24 ADC1pin
  ADC0->ULLMEM.SCOMP0 = 0;                // 8 sample clocks
  ADC0->ULLMEM.CPU_INT.IMASK = 0;         // no interrupt

   ADC0->ULLMEM.CTL0 |= 0x00000001;             //  enable conversions
   ADC0->ULLMEM.CTL1 |= 0x00000100;             //  start ADC
   uint32_t volatile delay=ADC0->ULLMEM.STATUS; //  time to let ADC start

NVIC->IP[1] = 1<<4; // ADC0 is IRQ 4
NVIC->ISER[0] = 1<<4; 
NVIC->IP [1] = (NVIC->IP [1] & (~0xFF000000)) | (2<<6) ;  
__enable_irq();

  while(1)
  {
    //ADC0->CTL0 |= ADC0_CTL0_ENC | ADC0_CTL0_SC;
    printf("NoData\n");
    DL_Common_delayCycles(40000000); // 1/2 sec
    j++;
  }
         
}
void ADC0_IRQHandler(void) 
{
    uint16_t adcRaw = ADC0->ULLMEM.MEMRES[0];
    while((ADC0->ULLMEM.STATUS&0x01)==0x01)
    {
      if(adcRaw>0)
      {
      i=i+1;
      printf("ADC = %d \n", i);
      }
    }

}
a Handler Please TI need input

  • > ADC0->ULLMEM.CPU_INT.IMASK = 0; // no interrupt

    With IMASK=0 the ADC won't generate any interrupts, so in that sense the ADC0_IRQHandler is unneeded.

    However, I don't see anything in main() which checks for completion, and I do see some setup for the NVIC, suggesting that you intended to get completion interrupts. If you enable one or more IMASK conditions then  the ADC0_IRQHandler is needed.

    How did you envision that this program would operate?

  • I see ok good thing I asked, Im basing the code from my MSP432 code Im semi new graduate and its my 5th MC I work on the register level so forgive me if I sound bad. In the 432 we used the handler for ADC so how can I go about that? Here attached is my old code 

    #include "msp.h"
    uint16_t threshold = 16384 / 2; // VCC/2 or 1.15V
    void main(void)
    {
        WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD; // stop watchdog timer
        // Enable ADC Pins
        P5->SEL0 |= BIT0;
        P5->SEL1 |= BIT0;
    
        // Enable on-board LED
        P2->DIR |= BIT2;     // Bit Set P2.2
        P2->OUT &= ~(BIT2);  // Bit Clear P2.2
        P2->SEL0 &= ~(BIT2); // Bit Clear SEL0 for P2.2
        P2->SEL1 &= ~(BIT2); // Bit Clear SEL1 for P2.2
        // Set-Up for ADC
        ADC14->CTL0 |= ADC14_CTL0_SHP | ADC14_CTL0_CONSEQ_0 | ADC14_CTL0_ON; //
        ADC14->MCTL[0] = ADC14_MCTLN_INCH_5;                                 // set ADC channel as A5 = P5.0
        ADC14->CTL1 |= ADC14_CTL1_RES__14BIT;                                // set resolution as a 14 bits resolution
        ADC14->IER0 |= ADC14_IER0_IE0;                                       // interrupt for mem 0
    
        // enable NVIC for ADC14
        NVIC->ISER[0] |= 1 << ((ADC14_IRQn)&31); // enable nvic
    
        // enable global interrupts
        __enable_irq();
    
        while (1)
        {
            __delay_cycles(1000000);                       // delay
            ADC14->CTL0 |= ADC14_CTL0_ENC | ADC14_CTL0_SC; // start conversion and enable conversion
        }
    }
    void ADC14_IRQHandler(void)
    {
        uint16_t adcRaw = ADC14->MEM[0]; // read adc data
    
        if (adcRaw > threshold) // Vcc/2 -> 3.04/2
        {
            P2->OUT = BIT2; // turn on BLUE led
        }
        else
        {
            P2->OUT &= ~(BIT2); // turn off LED
        }
    }
    

  • Hi,

    Agree with Bruce's point. It seems that you do not need the ADC interrupt routine in your code, since you are not enable ADC interrupt with IMASK = 0;

    Best regards,

    Cash Hao

  • i have updated the code but i think somethings wrong with the NVIC, I did do a separate code and yes you both were correct i was able to get ADC to work with no interrupts but now Im trying with the handler

    #include "ti/devices/msp/m0p/mspm0g350x.h"
    #include "ti/driverlib/dl_adc12.h"
    #include "ti/driverlib/dl_common.h" // For DL_Common_delayCycles function
    #include "ti_msp_dl_config.h"
    #include "IndexMacros.h"
    #include "stdio.h"
    
    int counter=1;
    int main (void)
    {
    
      ADC0->ULLMEM.GPRCM.RSTCTL = 0xB1000003; // reset ADC0 pins
      ADC0->ULLMEM.GPRCM.PWREN = 0x26000001;  // activate ADC0 pins
      DL_Common_delayCycles(40000000); // 1/2 sec delay
    
      ADC0->ULLMEM.GPRCM.CLKCFG = 0xA9000000; // ULPCLK
      ADC0->ULLMEM.CLKFREQ = 7;               // 40-48 MHz
      ADC0->ULLMEM.CTL0 = 0x03010000;         // divide by 8
      ADC0->ULLMEM.CTL1 = 0x00000000;         // mode
      ADC0->ULLMEM.CTL2 = 0x00000000;         // MEMRES
      ADC0->ULLMEM.MEMCTL[0] = 3;             // channel 3 PA24 ADC0pin
      ADC0->ULLMEM.SCOMP0 = 0;                // 8 sample clocks
    
      ADC0->ULLMEM.CPU_INT.IMASK |= (1<<0);  // arm PA24 1<<24  
    
    
    
    NVIC->IP [1] = (NVIC->IP [1] & (~0x000000FF))|(2<<6); // ADC0 is IRQ 4
    NVIC->ISER[0] = 1<<4; 
    
    __enable_irq();
    
      while(1)
      {
      ADC0->ULLMEM.CTL0 |= 0x00000001;             //  enable conversions
      ADC0->ULLMEM.CTL1 |= 0x00000100;             //  start ADC
      }
             
    }
    void ADC0_IRQHandler(void) 
    {
        uint16_t adcRaw = ADC0->ULLMEM.MEMRES[0];
    
          if(adcRaw>1000)
          {
            printf("%d\n", counter);
            counter++;
            DL_Common_delayCycles(40000000); // 1/2 sec delay
          }
    }
    

  • Hi,

    I would suggest to call API NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN); instead of directly operates on the NVIC->ISER[0] instead.

    Best regards,

    Cash Hao

  • no need heres my interrupt code that works fine

    #include "ti/devices/msp/m0p/mspm0g350x.h"
    #include "ti/driverlib/dl_common.h" // For DL_Common_delayCycles function
    #include "IndexMacros.h"
    #include "stdio.h"
    int x=0;
    int main(void)
    {
        GPIOA->GPRCM.RSTCTL = 0xB1000003;
        GPIOA->GPRCM.PWREN = 0x26000001;
        DL_Common_delayCycles(24);
    
        //LED
        IOMUX->SECCFG.PINCM[18] = 0x81; // PA8
        GPIOA->DOE31_0 |= (1 << 8);                   // set doe register to enable peripheral (1 means using mode 1 or GPIO)
    
        //SWITCH PA18
        IOMUX->SECCFG.PINCM[39] = 0x00050081;         // PA18 PULLDOWN : 0x0005 means pulldown
    
      // INTERRUPT
      GPIOA->POLARITY31_16 = 0x00000010; // rising
      GPIOA->CPU_INT.ICLR = 1<<18;  // clear bit 18
      GPIOA->CPU_INT.IMASK = 1<<18; // arm PA18 (1<<18)
      
      NVIC->IP[0] = (NVIC->IP[0]&(~0x0000FF00))|2<<6;  // set priority (bits 15,14) IRQ 0
      NVIC->ISER[0] = 1 << 1;            // Group0 interrupt
    
       __enable_irq();
    
        while (1)
        {     
          GPIOA->DOUT31_0 |= (1 << 8); // LED ON
          printf("%d\n",x);
            x++;
            DL_Common_delayCycles(40000000); // 1/2 sec
        }
    }
    void GROUP1_IRQHandler(void)
    { 
    if (GPIOA->CPU_INT.IIDX==19) // 
    {
        GPIOA->DOUT31_0 &= ~(1 << 8); // LED OFF
        printf("paused\n");
        DL_Common_delayCycles(40000000); // 1/2 sec
        GPIOA->CPU_INT.ICLR = (1<<18); // clear bit 18
    
    }
      
    }

  • Hi,

    So, your issue has been solved or not?

    Best regards,

    Cash Hao

  • So at this point I checked and checked and so far my set up is correct according to T.I TRM and according to a lecture slide but somethings not right 

    #include "ti/devices/msp/m0p/mspm0g350x.h"
    #include "ti/driverlib/dl_adc12.h"
    #include "ti/driverlib/dl_common.h" // For DL_Common_delayCycles function
    #include "ti_msp_dl_config.h"
    #include "IndexMacros.h"
    #include "stdio.h"
    
    int counter=0;
    int main (void)
    {
     
      ADC0->ULLMEM.GPRCM.RSTCTL = 0xB1000003; // reset ADC0 pins
      ADC0->ULLMEM.GPRCM.PWREN = 0x26000001;  // activate ADC0 pins
      DL_Common_delayCycles(40000000); // 1/2 sec delay
    
      ADC0->ULLMEM.GPRCM.CLKCFG = 0xA9000000; // ULPCLK
      ADC0->ULLMEM.CLKFREQ = 7;               // 40-48 MHz
      ADC0->ULLMEM.CTL0 = 0x03010000;         // divide by 8
      ADC0->ULLMEM.CTL1 = 0x00000000;         // mode
      ADC0->ULLMEM.CTL2 = 0x00000000;         // MEMRES
      ADC0->ULLMEM.MEMCTL[0] = 3;             // channel 3 PA24 ADC0pin
      ADC0->ULLMEM.SCOMP0 = 0;                // 8 sample clocks
      ADC0->ULLMEM.CPU_INT.ICLR = 1<<24;             // clear bit 24
      ADC0->ULLMEM.CPU_INT.IMASK = (1 << 24); // Enable MEM0 interrupt  
    
      NVIC->IP[1] = (NVIC->IP[1]&(~0x0000FF00))|(2<<7);  // set priority (bits 15,14) IRQ 4
      NVIC->ISER[0] = 1 << 4;            // ADC0 interrupt
    
      __enable_irq();
    
      while(1)
      {
      ADC0->ULLMEM.CTL0 |= 0x00000001;             //  enable conversions
      ADC0->ULLMEM.CTL1 |= 0x00000100;             //  start ADC
    
      }
        
    }
    void ADC0_IRQHandler(void) 
    {
      printf("ADC Interrupt Triggered!\n");
      ADC0->ULLMEM.CPU_INT.ICLR = (1 << 24);  //clear flag
    }
    

  • Hi,

    The code seems alright to me. But I would recommend you to run an ADC demo code in SDK first to check if the hardware is good in this case. And I would also suggest to use driver library instead of directly operates on the registers. 

    Best regards,

    Cash Hao

  • What is it that isn't right? Can you describe your symptom?

    ----------------

    >  ADC0->ULLMEM.CPU_INT.IMASK = (1 << 24); // Enable MEM0 interrupt

    Based on TRM (SLAU846B) Fig 12-12 this enables MEMRES16, which you're not using. Try instead:

    >  ADC0->ULLMEM.CPU_INT.IMASK = ADC12_CPU_INT_IMASK_MEMRESIFG0_MASK; // Enable MEM0 interrupt.

    ----------------

    More generally: I suggest you use the (CMSIS) names for these settings, so people who want to help aren't sent scrambling through the TRM.

    ----------------

    Even more generally: The strategy of setting SC repeatedly as fast as possible is somewhat unusual. I haven't found anything in the TRM (nor the Errata) which prohibits (re-)starting the ADC while it's busy, but I'm not sure what effect that has. I've seen ADCs which don't perform well in this case. I suggest you wait (maybe in _WFI()) for the ADC to finish.

  • __WFI(): definitely not needed BUT you were 100% i needed 

     ADC0->ULLMEM.CPU_INT.IMASK = (1 << 8); // Enable MEM0 interrupt  
    Thank you soooo much for the heads up on the TRM I was not informed there are two versions and yours helped me a ton!