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.

MSP432P401R: Triggering an ADC14 sample using TimerA0[1] in continuous mode

Part Number: MSP432P401R

Hello,

I'm working on an application where I want to sample a signal at a given rate (22.05 kHz, but this doesn't really matter). I am also doing some processing on that signal, so I would like to contain the processing portion of my program in a timer interrupt, and the sampling in an ADC interrupt. I have configured the Timer and ADC14 peripherals as follows:

void TIMER_init(void) {

	/* enable interrupts */
	NVIC->ISER[0] |= 1 << ((TA0_0_IRQn) & 31);
	NVIC->ISER[0] |= 1 << ((TA0_N_IRQn) & 31);

	TIMER_A0->CCTL[1] |=
		TIMER_A_CCTLN_OUTMOD_7 |		//something about resetting, unsure
		CCIE;						//enable interrupts for TIMER_AO[1]
	
	/* initialize counter comparison register TEMPORARY FIX */
    TIMER_A0->CCR[1] = 1000;
    
    /* set clock source and mode */
	TIMER_A0->CTL |= 
		TIMER_A_CTL_SSEL__SMCLK |	// SMCLK as source
    		TIMER_A_CTL_ID__8 |			// clock divider (1,2,4,8)
		TIMER_A_CTL_MC__CONTINUOUS |	// continuous mode
		TIMER_A_CTL_CLR;				// clear timer count
    
    TIMER_A0->EX0 |= TAIDEX__1; //Extended clock divider (1,2,3,4,5,6,7,8)
}

void ADC14_init(void) {
	/* enable interrupts */
	NVIC->ISER[0] |= 1 << ((ADC14_IRQn) & 31);

	/* configure MIC_OUTPUT for ADC14 */
	MIC_OUT_PORT->DIR &= ~MIC_OUT_PIN;
	MIC_OUT_PORT->SEL1 |= MIC_OUT_PIN;
	MIC_OUT_PORT->SEL0 |= MIC_OUT_PIN;

	/* disable conversion to allow configuration */
	ADC14->CTL0 &= ~ADC14_CTL0_ENC;
	
	/* configure control register 0 */
	ADC14->CTL0 =
		ADC14_CTL0_SHS_1 |	// start conversion from TA0.1
		ADC14_CTL0_SHP |	// pulse mode
		ADC14_CTL0_SHT0_2 |	// 16 clock cycle sample time
		ADC14_CTL0_ON;		// turn ADC module on
		
	/* configure control register 1 */
	ADC14->CTL1 = 
		ADC14_CTL1_RES__14BIT;
	
	/* choose A10 as source */
	ADC14->MCTL[0] |= MIC_OUT_CHANNEL;
	
	/* enable interrupt when conversion on A0 is complete */
	ADC14->IER0 = ADC14_IER0_IE0;
	
	/* enable conversions */
	ADC14->CTL0 |= ADC14_CTL0_ENC;
}

and a minimal example of my interrupt service routines are here

// TIMER ISR
void TA0_N_IRQHandler(void) {
	timer_counter++;
	TIMER_A0->CCR[1] += period;
	TIMER_A0->CCTL[1] &= ~CCIFG;
}

// ADC ISR
void ADC14_IRQHandler(void) {
	if(++index >= 20000) { index = 0; }
	adc_counter++;
	audio[index] = ADC14->MEM[0]; //get sample, clear flag
}

When I run this, the Timer's ISR clearly runs (by observing the value of timer_counter in memory), but the ADC ISR seemingly runs once (the value of adc_counter increments once and then seemingly stops).

I think I'm not properly grasping how to trigger the ADC14 conversion from the timer, and how that can be tied into an ISR. I'm looking for suggestions on how to configure or implement this differently.

Thanks,

Thomas

  • Thomas,

       Please be sure to set the sequence mode to repeat-single-channel.

    Chris

  • Chris,

    Setting the sequence mode fixed my initial problem with the ADC14 not activating properly, thank you.

    Now that I've done that, I've run into a speed problem. In the ADC14_CTL0 register I chose SMCLK as my source (running at 48 MHz), but the ADC is sampling at a much slower rate than TimerA. I observed this by viewing the values of timer_counter and adc_counter in memory, where timer_counter was much larger, indicating that the timer ISR had been called many more times than the ADC14 ISR.

    How can I speed up the ADC14 to match the sampling rate?

    Thanks,
    Thomas
  • THomas,
    You are using the timer to trigger the ADC but it is based upon the output and not the isr. So in your example setting to outmode 7 which is reset on CCR1 and set on CCR 0. This means that the output will stay in the reset state until the timer counts from 0xFFFF to 0. So while you are reseting the period of CCR1 the output is not changing and not triggering the ADC.

    You might find this example helpful.
    e2e.ti.com/.../2023396

    Chris
  • Thank you so much for your help! This was the last major hurdle to the project I'm working on, that bit of example code helped me understand how timer output works.

    I achieved my desired result by putting the timer in SET/RESET mode, then updating both the CCR[0] and CCR[1] values in the timer interrupt, with CCR[0] being slightly larger than CCR[1]. This put the ADC and Timer_A interrupts perfectly in sync.

    Thanks again,
    Thomas

**Attention** This is a public forum