Jace, thank you for this threat to talk about DMA and ADC.
Mi problem begin once I use : " MAP_ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM1,true);" to obtain analog values constantly and store them in ADC_MEM0 and ADCMEM1, i have modified the DMA configuration to increase the source direction "ADC_MEM0" 32 bits, but my destination address does not get filled, their values remain in 0, I need to use ping pong mode for DMA and repeat mode for ADC14, I have found examples of DMA and ADC with a SequenceMode in "not repeat mode". In your example I see that you use one DMA channel for one ADC source, in that case I will be able to use only 4 ADC sources because there are only 4 DMA_INTx_IRQHandler(if i am wrong, please, tell me). I beleave that is possible to use only one DMA channel to get information from multiple ADC sources, but I tried to do it but does no work.
#include "msp.h" #include <driverlib.h> #include <grlib.h> #include <stdio.h> #include <string.h> #include <arm_math.h> #include "arm_const_structs.h" #define TEST_LENGTH_SAMPLES 512 #define SAMPLE_LENGTH 512 /* ------------------------------------------------------------------ * Global variables for FFT Bin Example * ------------------------------------------------------------------- */ volatile long BUF_32; volatile short m=0; /* Graphic library context */ #define SMCLK_FREQUENCY 48000000 #define SAMPLE_FREQUENCY 600000 /* DMA Control Table */ #ifdef ewarm #pragma data_alignment=256 #else #pragma DATA_ALIGN(controlTable, 256) #endif uint8_t controlTable[256]; /* Processing buffers*/ float hann[SAMPLE_LENGTH]; int32_t data_array1[SAMPLE_LENGTH]; int32_t data_array2[SAMPLE_LENGTH]; int32_t data_array3[SAMPLE_LENGTH]; int32_t data_array4[SAMPLE_LENGTH]; int16_t salida[SAMPLE_LENGTH]; volatile int switch_data = 0; uint32_t color = 0; volatile uint16_t * res[2]; /* Timer_A PWM Configuration Parameter */ 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 }; void main(void) { /* Halting WDT and disabling master interrupts */ MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); /* Initializes Clock System */ MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); /*---------------------------------------------------------------------------------------------------------*/ // Configuracion de los puertos UART P1SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function __enable_interrupt(); NVIC->ISER[0] = 1 << ((EUSCIA0_IRQn) & 31); // Enable eUSCIA0 interrupt in NVIC module // Configuracion de UART UCA0CTLW0 |= UCSWRST; UCA0CTLW0 |= UCSSEL__SMCLK; // Pone eUSCI en reseteo UCA0BR0 = 26; // 48000000/16/9600 UCA0MCTLW = 0x1000 | 0x0020 | UCOS16; UCA0BR1 = 0; UCA0CTLW0 &= ~UCSWRST; // Inicializa eUSCI UCA0IE |= UCRXIE; // habilita la interrupcion USCI_A0 RX /*---------------------------------------------------------------------------------------------------------*/ /* Configuring Timer_A to have a period of approximately 500ms and * an initial duty cycle of 10% of that (3200 ticks) */ Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig); /*--------------------------------------------------------------------------------------------------*/ /* Initializing ADC (MCLK/1/1) */ ADC14_enableModule(); ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); /* Configuring GPIOs (4.3 A10)*/ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5 | GPIO_PIN4 ,GPIO_TERTIARY_MODULE_FUNCTION); /* Configuring ADC Memory */ // ADC14_enableSampleTimer (ADC_AUTOMATIC_ITERATION); ADC14_configureSingleSampleMode(ADC_MEM0, true); // ADC14_configureMultiSequenceMode (ADC_MEM0, ADC_MEM1,true); ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS,ADC_INPUT_A0, false); ADC14_configureConversionMemory(ADC_MEM1, ADC_VREFPOS_AVCC_VREFNEG_VSS,ADC_INPUT_A1, false); ADC14_setResolution (ADC_12BIT); /* Set ADC result format to signed binary */ // ADC14_setResultFormat(ADC_SIGNED_BINARY); /*--------------------------------------------------------------------------------------------------*/ /* Configuring DMA module */ DMA_enableModule(); DMA_setControlBase(controlTable); DMA_disableChannelAttribute(DMA_CH7_ADC14 , UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); /* Setting Control Indexes. In this case we will set the source of the * DMA transfer to ADC14 Memory 0 * and the destination to the * destination data array. */ MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14 , UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_2); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14 , UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array1, SAMPLE_LENGTH); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14 , UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_2); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14 , UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array2, SAMPLE_LENGTH); /* Assigning/Enabling Interrupts */ MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_assignChannel(DMA_CH7_ADC14); MAP_DMA_clearInterruptFlag(7); MAP_Interrupt_enableMaster(); /* Now that the DMA is primed and setup, enabling the channels. The ADC14 * hardware should take over and transfer/receive all bytes */ MAP_DMA_enableChannel(7); MAP_ADC14_enableConversion(); while(1) { MAP_PCM_gotoLPM0(); int i = 0; int j = 0; /* Store data on "salida[]" */ if (switch_data & 1) { for (i=0; i<512; i++) { salida[i] = (int16_t)(data_array1[i]); } } else { for (i=0; i<512; i++) { salida[i] = (int16_t)(data_array2[i]); } } /*--------------------------------------------------------------------------------------------------------------------------*/ /* Enviando datos a traves de UART */ for (j = 25; j <= 512-2; j+=2) { BUF_32= salida[j+1]; BUF_32= (BUF_32<<12)|salida[j]; while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF = (BUF_32 & 0x000000FF); while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF = (BUF_32 & 0x0000FF00)>>8; while(!(UCA0IFG&UCTXIFG)); UCA0TXBUF = (BUF_32 & 0x00FF0000)>>16; } /*--------------------------------------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------------------------------------------*/ } } /* Completion interrupt for ADC14 MEM0 */ void DMA_INT1_IRQHandler(void) { /* Switch between primary and alternate bufferes with DMA's PingPong mode */ if (DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14 , UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_2); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14 , UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array1, SAMPLE_LENGTH); switch_data = 1; } else { DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14 , UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_2); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14 , UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array2, SAMPLE_LENGTH); switch_data = 0; } } void EUSCIA0_IRQHandler(void) { if (UCA0IFG & UCRXIFG) { } }
If I change "UDMA_ARB_x" to "1" it still does not work, i got the same problem, destination array does not get filled. How can I use one channel to transfer information from multiple ADC sources??
Thank you!!!!