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.

CCS/MSP432P401R: UART interrupt stops DMA interrupt MSP432 (it seems)

Part Number: MSP432P401R

Tool/software: Code Composer Studio

Hello!,

I am working with the MSP432 to collect data from an accelerometer through the DMA and send it through serial (UART) to my PC. It has been working well so far, until I added the EUSCI interrupt so that the MSP432 could read a byte sent from my PC. Since that moment, I cant read anything from the serial port at my PC and when I debug the code I have notice that after entering the EUSCI interrupt (when a byte is sent from my PC) the DMA interrupt stops working and there is no refreashing of data to buffer_1 and buffer_2 (refer to the code).

I am attaching the code below.

#include <ti/devices/msp432p4xx/inc/msp.h>
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <ti/grlib/grlib.h>
#include <stdio.h>
#include <arm_math.h>
#include <arm_const_structs.h>

static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32];
/* DMA Control Table */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024)
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment=1024
#elif defined(__GNUC__)
__attribute__ ((aligned (1024)))
#elif defined(__CC_ARM)
__align(1024)
#endif

// ---------- Variables generales----------- //
const char digits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
#define SAMPLE_FREQUENCY    1000
#define SMCLK_FREQUENCY     48000000
static volatile uint16_t DMA_counter = 0;
static volatile uint16_t ADC_counter = 0;
static volatile uint16_t UART_counter = 0;
volatile int mode = 1;
volatile int flag = 0;
volatile int size = 0;
volatile int change_array = 0;
volatile int UART_flag = 0;
// ---------- FFT Parámetros ----------- //
#define N_MUESTRAS 1024
uint32_t fftSize = N_MUESTRAS*4;
uint32_t ifftFlag = 0;
uint32_t BitReverse = 1;
uint32_t max_freq_bin = 0;
volatile arm_status status;
// ---------- Inicialización de BUFFERS ----------- //
float hanning[N_MUESTRAS*2];
int16_t data_buffer1[N_MUESTRAS];
int16_t data_buffer2[N_MUESTRAS];
int16_t data_fft[N_MUESTRAS*8];
int16_t data_out[N_MUESTRAS*4];
int16_t buffer4096[N_MUESTRAS*4];
//------ FIR -------//
//#define N_TAPS 25
#define N_TAPS 38
int16_t filter_sum[1];
int16_t filter[1];

float coeff[N_TAPS] = { 0.0006f,    0.0005f,   -0.0002f,   -0.0016f,   -0.0037f,   -0.0065f,   -0.0092f,   -0.0110f,   -0.0110f,   -0.0082f,   -0.0015f,    0.0093f,
                        0.0243f,    0.0424f,    0.0624f,    0.0821f,    0.0995f,    0.1124f,    0.1193f,    0.1193f,    0.1124f,    0.0995f,    0.0821f,    0.0624f,
                        0.0424f,    0.0243f,    0.0093f,   -0.0015f,   -0.0082f,   -0.0110f,   -0.0110f,   -0.0092f,   -0.0065f,   -0.0037f,   -0.0016f,   -0.0002f,
                        0.0005f,    0.0006f };
//Para configurar los siguientes elementos se utilizará la libreria "driverlib".
//Las referencias a MAP de esta libreria están en: dev.ti.com/.../rom__map_8h.html
void CLOCK_Config(void)
{
// --------------------------- Configuración del CLOCK --------------------------- //
    //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1.
    MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
    MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
    MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
    //Elejimos la frecuencia de reloj general DCO en 48MHz.
    MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
    //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1.
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    //Elejimos la frecuencia de reloj MCLK en DC0=48MHz con un prescalador igual a 1.
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    //Elejimos la frecuencia de reloj HSMCLK en DC0=48MHz con un prescalador igual a 1.
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    //Elejimos la frecuencia de reloj MCLK en REFOCLOCK=36.6KHz con un prescalador igual a 1.
    MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
}

void GPIO_Config(void)
{
// --------------------------- Configuración de GPIO --------------------------- //
    //Para configurar el ADC de la Tarjeta 1 los puertos de entrada del ADC son P4.0 con canal A13.
    P4->SEL1 |= BIT0;
    P4->SEL0 |= BIT0;
    //Para configurar el ADC de la Tarjeta 2 los puertos de entrada del ADC son P6.0 con canal A15.
    P6->SEL1 |= BIT0;
    P6->SEL0 |= BIT0;
    //Para probar la frecuencia de salida de las interrupciones del ADC, se utiliza el pin P1.0 con salida digital.
    P1OUT &= ~BIT0;
    P1DIR |= BIT0;
    //Para transmitir los datos de forma serial, se elijen los pines P1.2 y P1.3 como TX Y RX respectivamente del UART.
    P1SEL0 |= BIT2 | BIT3;
}

const eUSCI_UART_Config uartConfig =
{
        //57600 bps:
        EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
        52,                                     // BRDIV = 52
        1,                                       // UCxBRF = 1
        0,                                       // UCxBRS = 0
        EUSCI_A_UART_NO_PARITY,                  // No Parity
        EUSCI_A_UART_LSB_FIRST,                  // LSB First
        EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit
        EUSCI_A_UART_MODE,                       // UART mode
        EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // Oversampling
};

void TIMER_Config(void)
{
    // --------------------------- Configuración del TIMER --------------------------- //
    // Se configura el Timer para que tenga la señal de reloj como SMCLK de referencia, con un escalador de 1, modo de operación UP
    // Salida tipo SET-RESET y un periodo de cuenta igual a SMLCK/Frecuencia_de_Muestreo_Deseada.
    Timer_A_PWMConfig pwmConfig = {TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY),
    TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2};
    Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
}

void ADC_Config(void)
{
    // --------------------------- Configuración del ADC --------------------------- //
    //Permite las operaciones de configuración en el ADC.
    ADC14_enableModule();
    //Inicializa el ADC con el DCO=48MHz como reloj de referencia, con un prescalador igual a 1 y escalador igual a 1.
    ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);
    //Se selecciona la salida del TIMER A0 como referencia de disparo para iniciar el muestreo, false = sin invertir la señal de entrada.
    ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);
    //Se selecciona el modo de operación de una sola muestra. Esto se debe a que el ADC iterará la adquisición de datos segun la señal externa de disparo de referencia.
    //Se escoge el espacio de memoria MEM0 para almacenar cada muestra del ADC, true = se repetirá la conversión al mismo espacio de memoria MEM0.
    ADC14_configureSingleSampleMode(ADC_MEM0, true);
    //Se configura el canal A13 del ADC que será muestreado y del cual se almacenará la información en MEM0, false = no se trabaja el ADC en modo diferencial.
    ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A15, ADC_NONDIFFERENTIAL_INPUTS);
    //Se configura la resolución del ADC en 14 bits, esto implica que cada periodo de muestreo son 16 ciclos de reloj de clock.
    ADC14_setResolution(ADC_14BIT);

}

void DMA_Config(void)
{
    // --------------------------- Configuración del DMA --------------------------- //
    //Permite las operaciones de configuración en el DMA.
    DMA_enableModule();
    //Define la estructura de control del DMA. Esta tabla se encuentra en memoria.
    DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
    //Define la estructura de control del DMA. Esta tabla se encuentra en memoria.
    DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

    MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer1, N_MUESTRAS);

    MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer2, N_MUESTRAS);

    //Configurar e inicializar interrupciones.
    MAP_DMA_assignInterrupt(DMA_INT1, 7);
    MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
    MAP_DMA_assignChannel(DMA_CH7_ADC14);
    MAP_DMA_clearInterruptFlag(7);
}

void TransmitirDatos() {

    int j=0;
    for (j=0;j < size; j++)
    {
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = digits[(data_out[j])>>12];
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = digits[0xF & ((data_out[j])>>8)];
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = digits[0xF & ((data_out[j])>>4)];
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = digits[0xF & ((data_out[j]))];
    while(!(UCA0IFG & UCTXIFG));
    UCA0TXBUF = '\n';
    UART_counter++;
    }
}

int main(void)
{
    // ---------- Funciones de configuración e inicialización del sistema ---------- //
    //Parar el reloj WDT.
    MAP_WDT_A_holdTimer();
    MAP_Interrupt_disableMaster();
    CLOCK_Config();
    GPIO_Config();
    TIMER_Config();
    ADC_Config();
    DMA_Config();

    MAP_Interrupt_enableMaster();
    MAP_DMA_enableChannel(7);
    MAP_ADC14_enableConversion();

    MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
    MAP_UART_enableModule(EUSCI_A0_BASE);
    MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_Interrupt_enableMaster();

    //Inicializar Filtro FIR de tipo Hamming Window:
    //Referencia:www.allaboutcircuits.com/.../
    int n;
    for(n = 0; n < N_MUESTRAS*2; n++)
    {
        hanning[n] = 0.5 - 0.5 * cosf((2 * PI * n) / ((N_MUESTRAS*2) - 1));
    }

    while(1)
    {
        //Duerme hasta la interrupción del DMA.
        //Medido con el Ociloscoipo: Se envía el buffer de datos cada 1000ms.
        //P1->OUT = BIT0;
        MAP_PCM_gotoLPM0();
        //P1->OUT &= ~BIT0;
        int i = 0;
        int j = 0;
        int z = 0;

        if (UART_flag == 1)
        {
            switch (mode)
            {
                case 1:
                {
                    size = N_MUESTRAS;
                    if(change_array & 1)
                    {
                        for(i = 0; i < N_MUESTRAS; i++)
                        {
                        data_out[i] = data_buffer1[i];
                        }
                        TransmitirDatos();
                    }
                    else
                    {
                        for(i = 0; i < N_MUESTRAS; i++)
                        {
                        data_out[i] =  data_buffer2[i];
                        }
                        TransmitirDatos();
                    }
                    break;
                }
                case 2:
                {
                    size = N_MUESTRAS;
                    if(change_array & 1)
                    {
                        P1->OUT = BIT0; //81ms
                        for(i=0; i < N_MUESTRAS; i++)
                        {
                            filter_sum[0] = 0;
                            for(j=0; j < N_TAPS; j++)
                            {
                                if ((i-j)<0)
                                {
                                    filter_sum[0]=data_buffer1[i];
                                }
                                else
                                {
                                    filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]);
                                    filter_sum[0] = filter_sum[0] + filter[0];
                                }
                            }
                            data_out[i] = filter_sum[0];
                        }
                        P1->OUT &= ~BIT0;
                        TransmitirDatos();
                    }
                    else
                    {
                        //P1->OUT = BIT0;
                        for(i=0; i < N_MUESTRAS; i++)
                        {
                            filter_sum[0] = 0;
                            for(j=0; j < N_TAPS; j++)
                            {
                                if ((i-j)<0)
                                {
                                    filter_sum[0]=data_buffer2[i];
                                }
                                else
                                {
                                    filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]);
                                    filter_sum[0] = filter_sum[0] + filter[0];
                                }
                            }
                            data_out[i] = filter_sum[0];
                        }
                        //P1->OUT &= ~BIT0;
                        TransmitirDatos();
                    }
                    break;
                }
                case 3:
                {
                    if(change_array & 1)
                    {
                        for(i=0; i < N_MUESTRAS; i++)
                        {
                            filter_sum[0] = 0;
                            for(j=0; j < N_TAPS; j++)
                            {
                                if ((i-j)<0)
                                {
                                    filter_sum[0]=data_buffer1[i];
                                }
                                else
                                {
                                    filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]);
                                    filter_sum[0] = filter_sum[0] + filter[0];
                                }
                            }
                        buffer4096[i] = filter_sum[0];
                        }
                    }
                    else
                    {
                        z=N_MUESTRAS;
                        flag=1;
                        for(i=0; i < N_MUESTRAS; i++)
                        {
                            filter_sum[0] = 0;
                            for(j=0; j < N_TAPS; j++)
                            {
                                if ((i-j)<0)
                                {
                                    filter_sum[0]=data_buffer2[i];
                                }
                                else
                                {
                                    filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]);
                                    filter_sum[0] = filter_sum[0] + filter[0];
                                }
                            }
                        buffer4096[z] = filter_sum[0];
                        z++;
                        }
                    }

                    if (flag==1)
                    {
                        for(i = 0; i < N_MUESTRAS*2; i++)
                        {
                            buffer4096[i] = (int16_t)(hanning[i] * buffer4096[i]);
                        }
                        for(i = (N_MUESTRAS*2); i < N_MUESTRAS*4; i++)
                        {
                            buffer4096[i] = 0;
                        }

                        arm_rfft_instance_q15 instance;
                        status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, BitReverse);
                        arm_rfft_q15(&instance, buffer4096, data_fft);

                        for(i = 0; i < (N_MUESTRAS*4); i = i+2)
                        {
                            data_out[i/2] = (int16_t)(sqrtf((data_fft[i] * data_fft[i]) + (data_fft[i+1] * data_fft[i+1])));
                        }
                        data_out[0]=15;
                        data_out[1]=15;
                        data_out[2]=15;
                        data_out[3]=15;

                        size = 205;
                        TransmitirDatos();
                        flag=0;
                    }
                break;
                }
            }
        }
    }
}

/* Completar una interrupción para ADC14 MEM0 */
void DMA_INT1_IRQHandler(void)
{
    DMA_counter++;
    if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT)
    {
        change_array = 1;
        DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer1, N_MUESTRAS);
    }
    else
    {
        change_array = 0;
        DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer2, N_MUESTRAS);
    }
}

/* Completar una interrupción para EUSCIA0 */
void EUSCIA0_IRQHandler(void)
{
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);

    MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
    {
        //MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE));
        if (MAP_UART_receiveData(EUSCI_A0_BASE)==65)
        {
            P1->OUT = BIT0;
            UART_flag=1;
        }
        else
        {
            P1->OUT &=~BIT0;
            UART_flag=0;
        }
    }
}

I think it has to do with the order I am entering the interrupts configuration, but I am not sure.

Thanks a lot in advance.

David.

  • > MAP_Interrupt_enableSleepOnIsrExit();
    > MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);
    I recommend you remove both of these lines. They won't cause your exact symptom as described, but could cause symptoms that look similar.

    In any case, they are unnecessary and hazardous.
  • Thanks Bruce!,


    I removed those lines but the problem still remains. I know now for sure that the UART interrupt is invalidating my DMA interrupt.
    Is it because of the order of the interrupt initialization commands or is there another thing I am doing wrong?


    Thanks for the help!


    David.

  • David,

       Can you provide some more details regarding what you mean by invalidating?  Looking at your code I see some mistakes which I will comment on later, but nothing specific to your issue related to the interrupts.  My suspicion is that the UART interrupt is continuously re-entered and that the DMA interrupt is never allowed to be serviced.   The usage of the API, MAP_UART_clearInterruptFlag, within the uart isr is consistent with the example.  I do have some concerns, which I think Bruce may have been alluding to with the transmit function which also checks the interrupt flags before loading the TXBUF.  I think this would be more of an issue of overwriting the TX buffer and not related to the DMA isr.  

    Other comments:

    (1) Flash wait states of 1 can be used with revision C and D silicon up to 48Mhz.  Revision B silicon requires 2 wait states.  Do not use revision B.

    (2) Peripherals support a maximum frequency of 24Mhz (with the ADC actually supporting 25Mhz).  

    Chris

  • Hi Chris,

    Thanks for the reply!

    So, everything was working fine before I added the UART interrupt rutine to read a serial byte sent from my PC. At the begining The DMA interrupt works for a period of time and then after the UART interrupt it just stops working. Also, it shows me to a piece of code from the driverlib (picture).

    What do you mean by overwriting the TX buffer? Right now I am getting non coherent values at my PC serial port.

    This is my code so far:

    #include <ti/devices/msp432p4xx/inc/msp.h>
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    #include <ti/grlib/grlib.h>
    #include <stdio.h>
    #include <arm_math.h>
    #include <arm_const_structs.h>
    
    static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32];
    /* DMA Control Table */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=1024
    #elif defined(__GNUC__)
    __attribute__ ((aligned (1024)))
    #elif defined(__CC_ARM)
    __align(1024)
    #endif
    
    // ---------- Variables generales----------- //
    const char digits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    #define SAMPLE_FREQUENCY    1000
    #define SMCLK_FREQUENCY     48000000
    static volatile uint16_t DMA_counter = 0;
    static volatile uint16_t ADC_counter = 0;
    static volatile uint16_t UART_counter = 0;
    volatile int mode = 1;
    volatile int flag = 0;
    
    volatile int count_1 = 0;
    volatile int count_2 = 0;
    
    volatile int size = 0;
    volatile int change_array = 0;
    volatile int UART_flag = 0;
    // ---------- FFT Parámetros ----------- //
    #define N_MUESTRAS 1024
    uint32_t fftSize = N_MUESTRAS*4;
    uint32_t ifftFlag = 0;
    uint32_t BitReverse = 1;
    uint32_t max_freq_bin = 0;
    volatile arm_status status;
    // ---------- Inicialización de BUFFERS ----------- //
    float hanning[N_MUESTRAS*2];
    int16_t data_buffer1[N_MUESTRAS];
    int16_t data_buffer2[N_MUESTRAS];
    int16_t data_fft[N_MUESTRAS*8];
    int16_t data_out[N_MUESTRAS*4];
    int16_t buffer4096[N_MUESTRAS*4];
    //------ FIR -------//
    //#define N_TAPS 25
    #define N_TAPS 38
    int16_t filter_sum[1];
    int16_t filter[1];
    
    float coeff[N_TAPS] = { 0.0006f,    0.0005f,   -0.0002f,   -0.0016f,   -0.0037f,   -0.0065f,   -0.0092f,   -0.0110f,   -0.0110f,   -0.0082f,   -0.0015f,    0.0093f,
                            0.0243f,    0.0424f,    0.0624f,    0.0821f,    0.0995f,    0.1124f,    0.1193f,    0.1193f,    0.1124f,    0.0995f,    0.0821f,    0.0624f,
                            0.0424f,    0.0243f,    0.0093f,   -0.0015f,   -0.0082f,   -0.0110f,   -0.0110f,   -0.0092f,   -0.0065f,   -0.0037f,   -0.0016f,   -0.0002f,
                            0.0005f,    0.0006f };
    //Para configurar los siguientes elementos se utilizará la libreria "driverlib".
    //Las referencias a MAP de esta libreria están en: dev.ti.com/.../rom__map_8h.html
    void CLOCK_Config(void)
    {
    // --------------------------- Configuración del CLOCK --------------------------- //
        //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
        //Elejimos la frecuencia de reloj general DCO en 48MHz.
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
        //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //Elejimos la frecuencia de reloj MCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //Elejimos la frecuencia de reloj HSMCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //Elejimos la frecuencia de reloj MCLK en REFOCLOCK=36.6KHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    }
    
    void GPIO_Config(void)
    {
    // --------------------------- Configuración de GPIO --------------------------- //
        //Para configurar el ADC de la Tarjeta 1 los puertos de entrada del ADC son P4.0 con canal A13.
        P4->SEL1 |= BIT0;
        P4->SEL0 |= BIT0;
        //Para configurar el ADC de la Tarjeta 2 los puertos de entrada del ADC son P6.0 con canal A15.
        P6->SEL1 |= BIT0;
        P6->SEL0 |= BIT0;
        //Para probar la frecuencia de salida de las interrupciones del ADC, se utiliza el pin P1.0 con salida digital.
        P1OUT &= ~BIT0;
        P1DIR |= BIT0;
        //Para transmitir los datos de forma serial, se elijen los pines P1.2 y P1.3 como TX Y RX respectivamente del UART.
        P1SEL0 |= BIT2 | BIT3;
    }
    
    const eUSCI_UART_Config uartConfig =
    {
            //57600 bps:
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            52,                                     // BRDIV = 52
            1,                                       // UCxBRF = 1
            0,                                       // UCxBRS = 0
            EUSCI_A_UART_NO_PARITY,                  // No Parity
            EUSCI_A_UART_LSB_FIRST,                  // LSB First
            EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit
            EUSCI_A_UART_MODE,                       // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // Oversampling
    };
    
    void TIMER_Config(void)
    {
        // --------------------------- Configuración del TIMER --------------------------- //
        // Se configura el Timer para que tenga la señal de reloj como SMCLK de referencia, con un escalador de 1, modo de operación UP
        // Salida tipo SET-RESET y un periodo de cuenta igual a SMLCK/Frecuencia_de_Muestreo_Deseada.
        Timer_A_PWMConfig pwmConfig = {TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY),
        TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2};
        Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
    }
    
    void ADC_Config(void)
    {
        // --------------------------- Configuración del ADC --------------------------- //
        //Permite las operaciones de configuración en el ADC.
        ADC14_enableModule();
        //Inicializa el ADC con el DCO=48MHz como reloj de referencia, con un prescalador igual a 1 y escalador igual a 1.
        ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);
        //Se selecciona la salida del TIMER A0 como referencia de disparo para iniciar el muestreo, false = sin invertir la señal de entrada.
        ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);
        //Se selecciona el modo de operación de una sola muestra. Esto se debe a que el ADC iterará la adquisición de datos segun la señal externa de disparo de referencia.
        //Se escoge el espacio de memoria MEM0 para almacenar cada muestra del ADC, true = se repetirá la conversión al mismo espacio de memoria MEM0.
        ADC14_configureSingleSampleMode(ADC_MEM0, true);
        //Se configura el canal A13 del ADC que será muestreado y del cual se almacenará la información en MEM0, false = no se trabaja el ADC en modo diferencial.
        ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A15, ADC_NONDIFFERENTIAL_INPUTS);
        //Se configura la resolución del ADC en 14 bits, esto implica que cada periodo de muestreo son 16 ciclos de reloj de clock.
        ADC14_setResolution(ADC_14BIT);
    
    }
    
    void DMA_Config(void)
    {
        // --------------------------- Configuración del DMA --------------------------- //
        //Permite las operaciones de configuración en el DMA.
        DMA_enableModule();
        //Define la estructura de control del DMA. Esta tabla se encuentra en memoria.
        DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
        //Define la estructura de control del DMA. Esta tabla se encuentra en memoria.
        DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer1, N_MUESTRAS);
    
        MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer2, N_MUESTRAS);
    
        //Configurar e inicializar interrupciones.
        MAP_DMA_assignInterrupt(DMA_INT1, 7);
        MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
        MAP_DMA_assignChannel(DMA_CH7_ADC14);
        MAP_DMA_clearInterruptFlag(7);
    }
    
    void TransmitirDatos() {
    
        int j=0;
        for (j=0;j < size; j++)
        {
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[(data_out[j])>>12];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[0xF & ((data_out[j])>>8)];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[0xF & ((data_out[j])>>4)];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[0xF & ((data_out[j]))];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = '\n';
        UART_counter++;
        }
    }
    
    int main(void)
    {
        // ---------- Funciones de configuración e inicialización del sistema ---------- //
        //Parar el reloj WDT.
        MAP_WDT_A_holdTimer();
        MAP_Interrupt_disableMaster();
        CLOCK_Config();
        GPIO_Config();
        TIMER_Config();
        ADC_Config();
        DMA_Config();
        MAP_Interrupt_enableMaster();
        MAP_DMA_enableChannel(7);
        MAP_ADC14_enableConversion();
    
        MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
        MAP_UART_enableModule(EUSCI_A0_BASE);
        MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    
        //Inicializar Filtro FIR de tipo Hamming Window:
        //Referencia:www.allaboutcircuits.com/.../
        int n;
        for(n = 0; n < N_MUESTRAS*2; n++)
        {
            hanning[n] = 0.5 - 0.5 * cosf((2 * PI * n) / ((N_MUESTRAS*2) - 1));
        }
    
        while(1)
        {
            //Duerme hasta la interrupción del DMA.
            //Medido con el Ociloscoipo: Se envía el buffer de datos cada 1000ms.
            //P1->OUT = BIT0;
            MAP_PCM_gotoLPM0();
            //P1->OUT &= ~BIT0;
            int i = 0;
            int j = 0;
            int z = 0;
    
            if (UART_flag == 1)
            {
                switch (mode)
                {
                    case 1:
                    {
                        size = N_MUESTRAS;
                        if(change_array & 1)
                        {
                            for(i = 0; i < N_MUESTRAS; i++)
                            {
                            data_out[i] = data_buffer1[i];
                            }
                            count_1++;
                            TransmitirDatos();
                        }
                        else
                        {
                            for(i = 0; i < N_MUESTRAS; i++)
                            {
                            data_out[i] =  data_buffer2[i];
                            }
                            count_2++;
                            TransmitirDatos();
                        }
                        break;
                    }
                    case 2:
                    {
                        size = N_MUESTRAS;
                        if(change_array & 1)
                        {
                            P1->OUT = BIT0; //81ms
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer1[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                                data_out[i] = filter_sum[0];
                            }
                            P1->OUT &= ~BIT0;
                            TransmitirDatos();
                        }
                        else
                        {
                            //P1->OUT = BIT0;
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer2[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                                data_out[i] = filter_sum[0];
                            }
                            //P1->OUT &= ~BIT0;
                            TransmitirDatos();
                        }
                        break;
                    }
                    case 3:
                    {
                        if(change_array & 1)
                        {
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer1[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                            buffer4096[i] = filter_sum[0];
                            }
                        }
                        else
                        {
                            z=N_MUESTRAS;
                            flag=1;
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer2[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                            buffer4096[z] = filter_sum[0];
                            z++;
                            }
                        }
    
                        if (flag==1)
                        {
                            for(i = 0; i < N_MUESTRAS*2; i++)
                            {
                                buffer4096[i] = (int16_t)(hanning[i] * buffer4096[i]);
                            }
                            for(i = (N_MUESTRAS*2); i < N_MUESTRAS*4; i++)
                            {
                                buffer4096[i] = 0;
                            }
    
                            arm_rfft_instance_q15 instance;
                            status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, BitReverse);
                            arm_rfft_q15(&instance, buffer4096, data_fft);
    
                            for(i = 0; i < (N_MUESTRAS*4); i = i+2)
                            {
                                data_out[i/2] = (int16_t)(sqrtf((data_fft[i] * data_fft[i]) + (data_fft[i+1] * data_fft[i+1])));
                            }
                            data_out[0]=15;
                            data_out[1]=15;
                            data_out[2]=15;
                            data_out[3]=15;
    
                            size = 205;
                            TransmitirDatos();
                            flag=0;
                        }
                    break;
                    }
                }
            }
        }
    }
    
    /* Completar una interrupción para ADC14 MEM0 */
    void DMA_INT1_IRQHandler(void)
    {
        DMA_counter++;
        if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT)
        {
            change_array = 1;
            DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
            DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer1, N_MUESTRAS);
        }
        else
        {
            change_array = 0;
            DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
            DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer2, N_MUESTRAS);
        }
    }
    
    /* Completar una interrupción para EUSCIA0 */
    void EUSCIA0_IRQHandler(void)
    {
        uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
    
        MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);
    
        if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
        {
            //MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE));
            if (MAP_UART_receiveData(EUSCI_A0_BASE)==65)
            {
                P1->OUT = BIT0;
                UART_flag=1;
            }
            else
            {
                P1->OUT &=~BIT0;
                UART_flag=0;
            }
        }
    }

    Thanks for the help.

    David.

  • Hi Chris,

    Thanks for the reply!

    So, everything was working fine before I added the UART interrupt rutine to read a serial byte sent from my PC. At the begining The DMA interrupt works for a period of time and then after the UART interrupt it just stops working. Also, it shows me to a piece of code from the driverlib (picture).

    What do you mean by overwriting the TX buffer? Right now I am getting non coherent values at my PC serial port.

    This is my code so far:

    #include <ti/devices/msp432p4xx/inc/msp.h>
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    #include <ti/grlib/grlib.h>
    #include <stdio.h>
    #include <arm_math.h>
    #include <arm_const_structs.h>
    
    static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32];
    /* DMA Control Table */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=1024
    #elif defined(__GNUC__)
    __attribute__ ((aligned (1024)))
    #elif defined(__CC_ARM)
    __align(1024)
    #endif
    
    // ---------- Variables generales----------- //
    const char digits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    #define SAMPLE_FREQUENCY    1000
    #define SMCLK_FREQUENCY     48000000
    static volatile uint16_t DMA_counter = 0;
    static volatile uint16_t ADC_counter = 0;
    static volatile uint16_t UART_counter = 0;
    volatile int mode = 1;
    volatile int flag = 0;
    
    volatile int count_1 = 0;
    volatile int count_2 = 0;
    
    volatile int size = 0;
    volatile int change_array = 0;
    volatile int UART_flag = 0;
    // ---------- FFT Parámetros ----------- //
    #define N_MUESTRAS 1024
    uint32_t fftSize = N_MUESTRAS*4;
    uint32_t ifftFlag = 0;
    uint32_t BitReverse = 1;
    uint32_t max_freq_bin = 0;
    volatile arm_status status;
    // ---------- Inicialización de BUFFERS ----------- //
    float hanning[N_MUESTRAS*2];
    int16_t data_buffer1[N_MUESTRAS];
    int16_t data_buffer2[N_MUESTRAS];
    int16_t data_fft[N_MUESTRAS*8];
    int16_t data_out[N_MUESTRAS*4];
    int16_t buffer4096[N_MUESTRAS*4];
    //------ FIR -------//
    //#define N_TAPS 25
    #define N_TAPS 38
    int16_t filter_sum[1];
    int16_t filter[1];
    
    float coeff[N_TAPS] = { 0.0006f,    0.0005f,   -0.0002f,   -0.0016f,   -0.0037f,   -0.0065f,   -0.0092f,   -0.0110f,   -0.0110f,   -0.0082f,   -0.0015f,    0.0093f,
                            0.0243f,    0.0424f,    0.0624f,    0.0821f,    0.0995f,    0.1124f,    0.1193f,    0.1193f,    0.1124f,    0.0995f,    0.0821f,    0.0624f,
                            0.0424f,    0.0243f,    0.0093f,   -0.0015f,   -0.0082f,   -0.0110f,   -0.0110f,   -0.0092f,   -0.0065f,   -0.0037f,   -0.0016f,   -0.0002f,
                            0.0005f,    0.0006f };
    //Para configurar los siguientes elementos se utilizará la libreria "driverlib".
    //Las referencias a MAP de esta libreria están en: dev.ti.com/.../rom__map_8h.html
    void CLOCK_Config(void)
    {
    // --------------------------- Configuración del CLOCK --------------------------- //
        //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        MAP_FlashCtl_setWaitState(FLASH_BANK0, 2);
        MAP_FlashCtl_setWaitState(FLASH_BANK1, 2);
        //Elejimos la frecuencia de reloj general DCO en 48MHz.
        MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);
        //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //Elejimos la frecuencia de reloj MCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //Elejimos la frecuencia de reloj HSMCLK en DC0=48MHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
        //Elejimos la frecuencia de reloj MCLK en REFOCLOCK=36.6KHz con un prescalador igual a 1.
        MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    }
    
    void GPIO_Config(void)
    {
    // --------------------------- Configuración de GPIO --------------------------- //
        //Para configurar el ADC de la Tarjeta 1 los puertos de entrada del ADC son P4.0 con canal A13.
        P4->SEL1 |= BIT0;
        P4->SEL0 |= BIT0;
        //Para configurar el ADC de la Tarjeta 2 los puertos de entrada del ADC son P6.0 con canal A15.
        P6->SEL1 |= BIT0;
        P6->SEL0 |= BIT0;
        //Para probar la frecuencia de salida de las interrupciones del ADC, se utiliza el pin P1.0 con salida digital.
        P1OUT &= ~BIT0;
        P1DIR |= BIT0;
        //Para transmitir los datos de forma serial, se elijen los pines P1.2 y P1.3 como TX Y RX respectivamente del UART.
        P1SEL0 |= BIT2 | BIT3;
    }
    
    const eUSCI_UART_Config uartConfig =
    {
            //57600 bps:
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            52,                                     // BRDIV = 52
            1,                                       // UCxBRF = 1
            0,                                       // UCxBRS = 0
            EUSCI_A_UART_NO_PARITY,                  // No Parity
            EUSCI_A_UART_LSB_FIRST,                  // LSB First
            EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit
            EUSCI_A_UART_MODE,                       // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // Oversampling
    };
    
    void TIMER_Config(void)
    {
        // --------------------------- Configuración del TIMER --------------------------- //
        // Se configura el Timer para que tenga la señal de reloj como SMCLK de referencia, con un escalador de 1, modo de operación UP
        // Salida tipo SET-RESET y un periodo de cuenta igual a SMLCK/Frecuencia_de_Muestreo_Deseada.
        Timer_A_PWMConfig pwmConfig = {TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY),
        TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2};
        Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
    }
    
    void ADC_Config(void)
    {
        // --------------------------- Configuración del ADC --------------------------- //
        //Permite las operaciones de configuración en el ADC.
        ADC14_enableModule();
        //Inicializa el ADC con el DCO=48MHz como reloj de referencia, con un prescalador igual a 1 y escalador igual a 1.
        ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);
        //Se selecciona la salida del TIMER A0 como referencia de disparo para iniciar el muestreo, false = sin invertir la señal de entrada.
        ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);
        //Se selecciona el modo de operación de una sola muestra. Esto se debe a que el ADC iterará la adquisición de datos segun la señal externa de disparo de referencia.
        //Se escoge el espacio de memoria MEM0 para almacenar cada muestra del ADC, true = se repetirá la conversión al mismo espacio de memoria MEM0.
        ADC14_configureSingleSampleMode(ADC_MEM0, true);
        //Se configura el canal A13 del ADC que será muestreado y del cual se almacenará la información en MEM0, false = no se trabaja el ADC en modo diferencial.
        ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A15, ADC_NONDIFFERENTIAL_INPUTS);
        //Se configura la resolución del ADC en 14 bits, esto implica que cada periodo de muestreo son 16 ciclos de reloj de clock.
        ADC14_setResolution(ADC_14BIT);
    
    }
    
    void DMA_Config(void)
    {
        // --------------------------- Configuración del DMA --------------------------- //
        //Permite las operaciones de configuración en el DMA.
        DMA_enableModule();
        //Define la estructura de control del DMA. Esta tabla se encuentra en memoria.
        DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable);
        //Define la estructura de control del DMA. Esta tabla se encuentra en memoria.
        DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
    
        MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer1, N_MUESTRAS);
    
        MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
        MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer2, N_MUESTRAS);
    
        //Configurar e inicializar interrupciones.
        MAP_DMA_assignInterrupt(DMA_INT1, 7);
        MAP_Interrupt_enableInterrupt(INT_DMA_INT1);
        MAP_DMA_assignChannel(DMA_CH7_ADC14);
        MAP_DMA_clearInterruptFlag(7);
    }
    
    void TransmitirDatos() {
    
        int j=0;
        for (j=0;j < size; j++)
        {
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[(data_out[j])>>12];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[0xF & ((data_out[j])>>8)];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[0xF & ((data_out[j])>>4)];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = digits[0xF & ((data_out[j]))];
        while(!(UCA0IFG & UCTXIFG));
        UCA0TXBUF = '\n';
        UART_counter++;
        }
    }
    
    int main(void)
    {
        // ---------- Funciones de configuración e inicialización del sistema ---------- //
        //Parar el reloj WDT.
        MAP_WDT_A_holdTimer();
        MAP_Interrupt_disableMaster();
        CLOCK_Config();
        GPIO_Config();
        TIMER_Config();
        ADC_Config();
        DMA_Config();
        MAP_Interrupt_enableMaster();
        MAP_DMA_enableChannel(7);
        MAP_ADC14_enableConversion();
    
        MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
        MAP_UART_enableModule(EUSCI_A0_BASE);
        MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    
        //Inicializar Filtro FIR de tipo Hamming Window:
        //Referencia:www.allaboutcircuits.com/.../
        int n;
        for(n = 0; n < N_MUESTRAS*2; n++)
        {
            hanning[n] = 0.5 - 0.5 * cosf((2 * PI * n) / ((N_MUESTRAS*2) - 1));
        }
    
        while(1)
        {
            //Duerme hasta la interrupción del DMA.
            //Medido con el Ociloscoipo: Se envía el buffer de datos cada 1000ms.
            //P1->OUT = BIT0;
            MAP_PCM_gotoLPM0();
            //P1->OUT &= ~BIT0;
            int i = 0;
            int j = 0;
            int z = 0;
    
            if (UART_flag == 1)
            {
                switch (mode)
                {
                    case 1:
                    {
                        size = N_MUESTRAS;
                        if(change_array & 1)
                        {
                            for(i = 0; i < N_MUESTRAS; i++)
                            {
                            data_out[i] = data_buffer1[i];
                            }
                            count_1++;
                            TransmitirDatos();
                        }
                        else
                        {
                            for(i = 0; i < N_MUESTRAS; i++)
                            {
                            data_out[i] =  data_buffer2[i];
                            }
                            count_2++;
                            TransmitirDatos();
                        }
                        break;
                    }
                    case 2:
                    {
                        size = N_MUESTRAS;
                        if(change_array & 1)
                        {
                            P1->OUT = BIT0; //81ms
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer1[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                                data_out[i] = filter_sum[0];
                            }
                            P1->OUT &= ~BIT0;
                            TransmitirDatos();
                        }
                        else
                        {
                            //P1->OUT = BIT0;
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer2[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                                data_out[i] = filter_sum[0];
                            }
                            //P1->OUT &= ~BIT0;
                            TransmitirDatos();
                        }
                        break;
                    }
                    case 3:
                    {
                        if(change_array & 1)
                        {
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer1[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                            buffer4096[i] = filter_sum[0];
                            }
                        }
                        else
                        {
                            z=N_MUESTRAS;
                            flag=1;
                            for(i=0; i < N_MUESTRAS; i++)
                            {
                                filter_sum[0] = 0;
                                for(j=0; j < N_TAPS; j++)
                                {
                                    if ((i-j)<0)
                                    {
                                        filter_sum[0]=data_buffer2[i];
                                    }
                                    else
                                    {
                                        filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]);
                                        filter_sum[0] = filter_sum[0] + filter[0];
                                    }
                                }
                            buffer4096[z] = filter_sum[0];
                            z++;
                            }
                        }
    
                        if (flag==1)
                        {
                            for(i = 0; i < N_MUESTRAS*2; i++)
                            {
                                buffer4096[i] = (int16_t)(hanning[i] * buffer4096[i]);
                            }
                            for(i = (N_MUESTRAS*2); i < N_MUESTRAS*4; i++)
                            {
                                buffer4096[i] = 0;
                            }
    
                            arm_rfft_instance_q15 instance;
                            status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, BitReverse);
                            arm_rfft_q15(&instance, buffer4096, data_fft);
    
                            for(i = 0; i < (N_MUESTRAS*4); i = i+2)
                            {
                                data_out[i/2] = (int16_t)(sqrtf((data_fft[i] * data_fft[i]) + (data_fft[i+1] * data_fft[i+1])));
                            }
                            data_out[0]=15;
                            data_out[1]=15;
                            data_out[2]=15;
                            data_out[3]=15;
    
                            size = 205;
                            TransmitirDatos();
                            flag=0;
                        }
                    break;
                    }
                }
            }
        }
    }
    
    /* Completar una interrupción para ADC14 MEM0 */
    void DMA_INT1_IRQHandler(void)
    {
        DMA_counter++;
        if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT)
        {
            change_array = 1;
            DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
            DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer1, N_MUESTRAS);
        }
        else
        {
            change_array = 0;
            DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
            DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer2, N_MUESTRAS);
        }
    }
    
    /* Completar una interrupción para EUSCIA0 */
    void EUSCIA0_IRQHandler(void)
    {
        uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
    
        MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);
    
        if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
        {
            //MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE));
            if (MAP_UART_receiveData(EUSCI_A0_BASE)==65)
            {
                P1->OUT = BIT0;
                UART_flag=1;
            }
            else
            {
                P1->OUT &=~BIT0;
                UART_flag=0;
            }
        }
    }

    Thanks for the help.

    David.

  • adc14_14b_manualTrigger.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    /******************************************************************************
    *
    * Copyright (C) 2012 - 2017 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.
    *
    * MSP432 SimpleLink C:\ti\simplelink_msp432p4_sdk_1_50_00_12
    *
    *****************************************************************************/
    /*******************************************************************************
    * MSP432 ADC14 - Single Channel Continuous Sample w/ Timer_A Trigger
    *
    * Description: In this ADC14 code example, a single input channel is sampled
    * using the standard reference specified in the reference definition and
    * configuration variable. The ADC is setup to continuously sample/convert
    * from A10. The sample-and hold time and the source of the sample trigger is
    * provided by Timer_A0. Capture Compare Register 0 (CCR0) defines the sample
    * period while CCR1 defines the sample-hold time. The CCR0 value is 23 and
    * CCR1 is set to 19, resulting in a sample period of 1us.
    * The ADC is setup to perform repeated single-channel measurements of channel
    * A10.
    * The DMA moves the results from the ADC to the resultsBuffer and
    * destination pointer is maintained in the DMA ISR.
    *
    * Timer_A0 is started once the GPIO interrupt for P1.4 is serviced. Upon
    * completion the array resultsBuffer is transmitted via UART.
    *
    * MSP-EXP432P401
    * ------------------
    * /|\| |
    * | | |<--- P5.6 (Veref+)
    * | | |<--- P5.7 (Veref-)
    * | | |
    * --|RST P4.2 |<--- A11 (Analog Input)
    * | P4.3 |<--- A10 (Analog Input)
    * | |
    * | P1.4 |<--- GPIO trigger to Start conversions
    * | |
    * | P1.0 |---> Debug port to show GPIO ISR
    * | P1.2 |<--- UART Rx
    * | P1.3 |---> UART Tx
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Consider the flow of your code.  The LPM0 is intended to keep the CPU from proceeding until the DMA interrupt.  Now that you have added another interrupt for the UART, this will also allow the CPU to proceed.  You may have a potential issue where the main loop is being executed while the DMA is still writing to the data.  Can you simply remove the UART ISR and within the DMA isr check if the UART received any data?  Do you really want the data transmitted continuously or do you want a burst (2Kb) of data every time a specific uart value is received.

    Not sure is the attached is helpful, but in this example instead of a UART rx a port isr is used to burst out data.

    Chris

**Attention** This is a public forum