I am trying to modify the MSP430FR57xx_adc10_10.c example (which samples 3 inputs in a sequence and transfers to an array using DMA).
The main change I want to make, is to trigger the sampling using timerB0 (to generate a fixed sampling time) instead of using ADC10SC (software triggering)
I want to get the amplitude of two AC signals, so the idea is that the DMA interrupt routine is called 180 times (which is a bit more that one period of the signal) during which it will search for max and min values of the signal. After the 180'th measurement it falls out of sleep mode and the main program continues.
The problem is that the ADC seems to hang each time after the first series of 180 measurements, so the MCU stays in sleep mode the second time that it goes through the infinite wile loop.
When I break the program after it hangs, the debugger tells me it is at the __no_operation() line. TimerB0 is still running (value changes if I continue/stop). The ADC's Busy bit stays ON and the ADC10MCTL0 has counted to zero.
The ADC is no longer sampling (value in ADC10MEM0 doesn't change any more).
Does anybody have any idea why it stops calling the DMA interrupt routine after the first series of 180?
The code is below:
Thanks,
Bart
#include <msp430.h>
/*
* main.c
*/
unsigned short ADC_Result[2]; // 8-bit ADC conversion result array
unsigned char pos=0;
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
// Configure ADC pins
P1SEL0 |= BIT0 + BIT1;
P1SEL1 |= BIT0 + BIT1;
// Configure ADC10
ADC10CTL0 = ADC10SHT_2 + ADC10MSC + ADC10ON;// 16ADCclks(dont go lower!!), MultipleSampleConversion, ADC ON
ADC10CTL1 = ADC10SHP + ADC10CONSEQ_1 + ADC10SHS_3; // sampling timer, channel sequence, using timerB0 as trigger
ADC10CTL2 |= ADC10RES; // 10-bit resolution
ADC10MCTL0 = ADC10INCH_1; // A0,A1(EoS), AVCC reference
// ADC conversion trigger signal - TimerA0.0 (32ms ON-period)
TB0CCR0 = 2048-1; // PWM Period
TB0CCR1 = 1024-1; // TB0.1 ADC trigger
TB0CCTL1 = OUTMOD_4; // TB0CCR0 toggle
// TB0CTL = TBSSEL_2 + MC_1 + TBCLR; // MCLK source (8MHz)
// Configure DMA0 (ADC10IFG trigger)
DMACTL0 = DMA0TSEL__ADC10IFG; // ADC10IFG trigger
__data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC10MEM0);
// Source single address
__data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &ADC_Result[0]);
// Destination array address
DMA0SZ = 0x02; // 3 conversions
DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN + DMAIE;
// Rpt, inc dest, byte access,
// enable int after seq of convs
while(1)
{
pos=0;
TB0CTL = TBSSEL_2 + MC_1 + TBCLR; // start timer from 0
ADC10CTL0 &= ~ADC10ENC;
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active
ADC10CTL0 |= ADC10ENC;// + ADC10SC; // Sampling and conversion start
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit
// __delay_cycles(2); // needed or ADC hangs
__no_operation(); // BREAKPOINT; check ADC_Result
__no_operation(); // BREAKPOINT; check ADC_Result
}
}
#pragma vector=DMA_VECTOR
__interrupt void DMA0_ISR (void)
{
switch(__even_in_range(DMAIV,16))
{
case 0: break; // No interrupt
case 2:
// sequence of conversions complete
// __bic_SR_register_on_exit(CPUOFF); // exit LPM
ADC10CTL0 &= ~ADC10ENC;
ADC10CTL0 |= ADC10ENC;
if (pos>180) {
__bic_SR_register_on_exit(CPUOFF); // exit LPM
}
break; // DMA0IFG
case 4: break; // DMA1IFG
case 6: break; // DMA2IFG
case 8: break; // Reserved
case 10: break; // Reserved
case 12: break; // Reserved
case 14: break; // Reserved
case 16: break; // Reserved
default: break;
}
pos++;
}