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.

ADC12 and timer interrupts

Other Parts Discussed in Thread: MSP430F5436A

Hi,

I am using msp430f5436a for a university project- I have two questions:

My application is based on TI's user experience software.

In this software the ADC is activated by Timer B, and the DMA transffers the data to flash memory When the DMA is finished- it generates an interrupt.

I added a second interrupt generated by Timer A.  The interrupt is actualy generated every 1/32 of a second,

but actual code is running only after 10 seconds, (every interrupt updated a counter, when the counter equals 320, the code is activated)

Every time the program reaches the code (after 10 seconds) the original interrupt generated by DMA does not work any more.

why is that? is there a missing configuration regarding the interrupt scheduling?

Another questions regards the frequency of the ADC12 in the user experience software:

Here is the ADC12 configurations:

 

ADC12CTL2 = ADC12RES_0;

 

ADC12CTL0 = ADC12ON + ADC12SHT02 ;

ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SSEL_2 + ADC12SHS_3;

the ADC12 is configured with SHT02 which means 16 clock cycles per sample + 13 clock cycles = 29 clock cycles.

The CONSEQ_2 is configured for repeated single channel.

the MCLK is configured for 16 Mhz, and therefor the ADC12 should be sampling in about 600khz, while it is actually sampling int about 8khz

why is that?

Thanks a lot!!

Ariel 

 

  • ariel said:

    ... I added a second interrupt generated by Timer A.  The interrupt is actualy generated every 1/32 of a second,

    but actual code is running only after 10 seconds, (every interrupt updated a counter, when the counter equals 320, the code is activated)

    Every time the program reaches the code (after 10 seconds) the original interrupt generated by DMA does not work any more.

    why is that? is there a missing configuration regarding the interrupt scheduling?...

    Your modification probably disable the original interrupt unintentionally. With the information you provided, I cannot tell what is missing or what went wrong.

    ariel said:

    ... Another questions regards the frequency of the ADC12 in the user experience software:

    Here is the ADC12 configurations:

    ADC12CTL2 = ADC12RES_0;

    ADC12CTL0 = ADC12ON + ADC12SHT02 ;

    ADC12CTL1 = ADC12SHP + ADC12CONSEQ_2 + ADC12SSEL_2 + ADC12SHS_3;

    the ADC12 is configured with SHT02 which means 16 clock cycles per sample + 13 clock cycles = 29 clock cycles.

    The CONSEQ_2 is configured for repeated single channel.

    the MCLK is configured for 16 Mhz, and therefor the ADC12 should be sampling in about 600khz, while it is actually sampling int about 8khz

    why is that? ...

    It may be able to convert about 600 k-samples per second. But if it depends on the Timer to start each sampling, then the actual sampling rate depends on how often the Timer triggers the sampling.

     

     

  • I don't know what the ISRs are doing, so any explanations as a likely as any other. Perhaps your code triggered every 10 seconds  does never exit the ISR? then no other ISR will ever be executed again.

    One thing you may not forget (even if it does not seem to apply here) is that the DMA can only be triggered if the same trigger isn't used for triggering an ISR. So if you had an ISR set up for the ADC12 interrupt, it wouldn't trigger the DMA anymore.

    ariel said:
    Another questions regards the frequency of the ADC12 in the user experience software

    The maximum clock for the ADC (after input divider) is ~5MHz, according to all datasheets I've read. Clocking it with 16MHz will lead to unpredicatable results.

  • Thanks for the help guys,

    Regarding the problem with the interrupts, when I pause the application after my program is stuck, I can see that

    the current command points to the last line in the ISR interrupt, so this might be a sign that the program doesn't exit the ISR, but I don't understand why, and why does it happen only when the main code is activated. I am adding the code for the interrupt, I hope it might help.

    Could it be that the DMA interrupt is triggered during the time that the timer interrupt is active, and therefor lost?

    Here is the code:

    #pragma vector=TIMER1_A0_VECTOR
    __interrupt void TIMER1_A0_ISR(void)
    {
     counter++;
     if (counter == 320)   //every ten seconds
     {
      counter=0;
      
        for (i=1;i<16;i++)
        {
         CurrentDoseCalc= SoundMeasureArray[i]/MaxTimeArray[i];
         SoundMeasureArray[i]=0;//-=CurrentDoseCalc*MaxTimeArray[i];
         CurrentDoseSum+=CurrentDoseCalc;
             
         
        }
        Percent=CurrentDoseSum/10;
        sprintf(PercentStr,"Dose :%d%",Percent);
        halLcdPrintLineCol(PercentStr , 3, 1, INVERT_TEXT | OVERWRITE_TEXT);    
        
      TA1CTL &= ~MC_1;
      TBCTL |= MC0;
      
     }
     TA1CTL &= ~TAIFG;
     
    }

    Regarding the second questions: I didn't change anything in the configuration of the ADC12, So I don't think I caused any problem,

    But I don't understand what determines the sampling frequency to be so low? the 5438 user guide states an ability to save about 20 seconds

    of data in 256k memory which indicates a sampling frequency of about 13k, but since the ADC12 is configured for repeat mode and the sample time for 16 clock cycles, the rate should be much higher..

    thanks again,

    Ariel

  • Maybe it's not the ISR itself that causes the problem. I've seen a program where the main code was simply running into the ISR at some point, executing it directly. And there of course the system crashed when it tried to 'leave' the ISR at its end.

    Also, it's generally a very bad idea to do complicated stuff such as sprintf inside an ISR.

    The recommended setup is:

    • init all components
    • start the timers
    • put main into sleep
    • wait for interrupt
    • set a flag or collect data inside ISR
    • wake main up inside ISR
    • exit ISR
    • let main handle the processing and output of the collected data.
    • put main into sleep mode again.

    It is possible that you*'re losing interrupts if your ISR executes too slowly. You clear TAIFG at the end of the ISR, but maybe another interrupt has been already triggered, which you skip if you clear the flag here.

    Regarding the other problem: you cannot sample data and save it to flash at the same time. While the flash is written to, no ISRs can be executed, as the CPU is not running. so the maximum sampling frequency is limited by the time the CPU is halted during flash writes.

    If you sample and write the data out using SPI, you can write about 1MB per second, which would be 500ksps. The maximum the ADC12 can do with 12 bit resolution and its maximum of 5MHz ADCclock is ~350ksps, so continuous sampling with maximum speed is possible through I2C. It would require, however, some sophisticated use of DMAs to keep the data transfer up with the sampling speed.
    Using the ADC12 in 8 bit mode woudl speed thing up further. There 500ksps are reachable. In both cases the quality would be questionable due to the ultrashort input gating.

**Attention** This is a public forum