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.
Configures the ADC in the Tiva 1294 with DMA ping-pong mode, dual interleaved with phase shift
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_adc.h" #include "inc/hw_timer.h" #include "inc/hw_gpio.h" #include "inc/hw_udma.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" #include "driverlib/interrupt.h" #include "driverlib/gpio.h" #include "driverlib/adc.h" #include "driverlib/pwm.h" #include "driverlib/fpu.h" #include "driverlib/uart.h" #include "driverlib/timer.h" #include "driverlib/udma.h" #include "utils/uartstdio.h" #pragma DATA_ALIGN(dmaControlTable, 1024) uint8_t dmaControlTable[1024]; #define ADC_BUFFER_SIZE 2 static uint16_t g_adcBuf[ADC_BUFFER_SIZE]; static uint32_t g_uDMAErrCount; bool g_flagAdc0; bool g_flagAdc1; void initPeripherals(void) { ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)); ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD)); ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOK); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOK); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOK)); ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC0); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0)); ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_ADC1); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_ADC1); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1)); ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_UART2); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_UART2); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_UART2)); ROM_SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA); ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA)); } void config_UART2(uint32_t baudrate, uint32_t cpuClock) { ROM_GPIOPinConfigure(GPIO_PD4_U2RX); ROM_GPIOPinConfigure(GPIO_PD5_U2TX); ROM_GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5); ROM_UARTClockSourceSet(UART2_BASE, UART_CLOCK_SYSTEM); UARTStdioConfig(2, baudrate, cpuClock); } void config_ADC0DMA(void) { ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1); ROM_ADCReferenceSet(ADC0_BASE, ADC_REF_INT); ROM_ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_ALWAYS, 0); ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH16); ROM_ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH17 | ADC_CTL_IE | ADC_CTL_END); //(320MHz PLL/2) / 5 = 32MHz = 2MSPS (there's an issue with the documentation, the PLL is divided by 2, hence 320MHz/2) ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 10); //enable oversampling ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); //set the phase delay, so the two ADCs can sample the same signal alternately, the value is experimental //and you should check with an logic analyser or oscilloscope to see if they're separated by ~180� //this case is 0 for being the reference ROM_ADCPhaseDelaySet(ADC0_BASE, ADC_PHASE_0); //enable ADC and ADC DMA ROM_ADCSequenceEnable(ADC0_BASE, 1); ROM_ADCSequenceDMAEnable(ADC0_BASE, 1); //configure the uDMA ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC1, UDMA_ATTR_ALL); ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC1, UDMA_ATTR_USEBURST); ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC1); //enable the interrupts (for this case is ADCIntEnableEx instead of ADCIntEnable) ROM_ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS1); ROM_IntEnable(INT_ADC0SS1); } void config_ADC1DMA(void) { ROM_GPIOPinTypeADC(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1); ROM_ADCReferenceSet(ADC1_BASE, ADC_REF_INT); ROM_ADCSequenceConfigure(ADC1_BASE, 1, ADC_TRIGGER_ALWAYS, 0); ROM_ADCSequenceStepConfigure(ADC1_BASE, 1, 0, ADC_CTL_CH16); ROM_ADCSequenceStepConfigure(ADC1_BASE, 1, 1, ADC_CTL_CH17 | ADC_CTL_IE | ADC_CTL_END); //(320MHz PLL/2) / 5 = 32MHz = 2MSPS (there's an issue with the documentation, the PLL is divided by 2, hence 320MHz/2) ADCClockConfigSet(ADC1_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 10); //enable oversampling ROM_ADCHardwareOversampleConfigure(ADC1_BASE, 64); //set the phase delay, so the two ADCs can sample the same signal alternately, the value is experimental //and you should check with an logic analyser or oscilloscope to see if they're separated by ~180� ROM_ADCPhaseDelaySet(ADC1_BASE, ADC_PHASE_270); //enable ADC and DMA ROM_ADCSequenceEnable(ADC1_BASE, 1); ROM_ADCSequenceDMAEnable(ADC1_BASE, 1); //assign channel 25 to ADC1 (since the channel defaults to SSI1TX) ROM_uDMAChannelAssign(UDMA_CH25_ADC1_1); //configures the uDMA (secondary peripheral assignments) ROM_uDMAChannelAttributeDisable(UDMA_SEC_CHANNEL_ADC11, UDMA_ATTR_ALL); ROM_uDMAChannelAttributeEnable(UDMA_SEC_CHANNEL_ADC11, UDMA_ATTR_USEBURST); ROM_uDMAChannelControlSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); ROM_uDMAChannelControlSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC1_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC1_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); ROM_uDMAChannelEnable(UDMA_SEC_CHANNEL_ADC11); //enable the interrupts (for this case is ADCIntEnableEx instead of ADCIntEnable) ROM_ADCIntEnableEx(ADC1_BASE, ADC_INT_DMA_SS1); ROM_IntEnable(INT_ADC1SS1); } int main(void) { //config CPU to run at 120MHz with 320MHz VCO uint32_t g_cpuFrequency = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320), 120000000); ROM_FPUEnable(); ROM_FPULazyStackingEnable(); //disable interrupts to safely configure peripherals ROM_IntMasterDisable(); //enable peripherals initPeripherals(); //configs UART 2 (Launchpad jumpers must be in CAN position, otherwhise you'll need to rewrite this function to UART0) config_UART2(921600, g_cpuFrequency); //set PA output pins to change state after every interrupt from the ADC ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_5); //clears screen and reset the cursor UARTprintf("\033[2J\033[H"); //enable udma error interrupt ROM_IntEnable(INT_UDMAERR); //enable udma ROM_uDMAEnable(); ROM_uDMAControlBaseSet(dmaControlTable); //configs ADC config_ADC0DMA(); config_ADC1DMA(); //now that every periph is safely configured, we can enable interrupts ROM_IntMasterEnable(); for(;;) { UARTprintf("ADC Reading: %u %u Error Count: %u\n", g_adcBuf[0], g_adcBuf[1], g_uDMAErrCount); ROM_SysCtlDelay((g_cpuFrequency/3)*0.1); } } void ADC0SS1IntHandler(void) { uint32_t ui32Mode; //clear ADC interrupt caused by DMA ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS1); //checks udma primary control structure current mode ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT); //if udma primary control structure is done transfering data, re-enable it if(ui32Mode == UDMA_MODE_STOP) ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); //checks udma secondary control structure current mode ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT); //if udma secondary control structure is done transfering data, re-enable it if(ui32Mode == UDMA_MODE_STOP) ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); //toggle pin PA5 to analyse it with an oscilloscope or logic analyser the ADC current speed ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_4, g_flagAdc0 ? GPIO_PIN_4 : 0x00); g_flagAdc0 = !g_flagAdc0; } void ADC1SS1IntHandler(void) { uint32_t ui32Mode; //clear ADC interrupt caused by DMA ADCIntClearEx(ADC1_BASE, ADC_INT_DMA_SS1); //checks udma primary control structure current mode ui32Mode = ROM_uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT); //if udma primary control structure is done transfering data, re-enable it if(ui32Mode == UDMA_MODE_STOP) ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC1_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); //checks udma secondary control structure current mode ui32Mode = ROM_uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT); //if udma secondary control structure is done transfering data, re-enable it if(ui32Mode == UDMA_MODE_STOP) ROM_uDMAChannelTransferSet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC1_BASE + ADC_O_SSFIFO1), g_adcBuf, ADC_BUFFER_SIZE); //toggle pin PA5 to analyse it with an oscilloscope or logic analyser the ADC current speed ROM_GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_5, g_flagAdc1 ? GPIO_PIN_5 : 0x00); g_flagAdc1 = !g_flagAdc1; } void uDMAErrorHandler(void) { uint32_t ui32Status; ui32Status = ROM_uDMAErrorStatusGet(); if(ui32Status) { ROM_uDMAErrorStatusClear(); g_uDMAErrCount++; } }