TI中文支持网
TI专业的中文技术问题搜集分享网站

基于tm4c1294+ADC+DMA的代码分享

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 oversamplingROM_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 referenceROM_ADCPhaseDelaySet(ADC0_BASE, ADC_PHASE_0);//enable ADC and ADC DMAROM_ADCSequenceEnable(ADC0_BASE, 1);ROM_ADCSequenceDMAEnable(ADC0_BASE, 1);//configure the uDMAROM_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 oversamplingROM_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 DMAROM_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 VCOuint32_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 peripheralsROM_IntMasterDisable();//enable peripheralsinitPeripherals();//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 ADCROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_5);//clears screen and reset the cursorUARTprintf("\033[2J\033[H");//enable udma error interruptROM_IntEnable(INT_UDMAERR);//enable udmaROM_uDMAEnable();ROM_uDMAControlBaseSet(dmaControlTable);//configs ADCconfig_ADC0DMA();config_ADC1DMA();//now that every periph is safely configured, we can enable interruptsROM_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 DMAADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS1);//checks udma primary control structure current modeui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_PRI_SELECT);//if udma primary control structure is done transfering data, re-enable itif(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 modeui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_ADC1 | UDMA_ALT_SELECT);//if udma secondary control structure is done transfering data, re-enable itif(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 speedROM_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 DMAADCIntClearEx(ADC1_BASE, ADC_INT_DMA_SS1);//checks udma primary control structure current modeui32Mode = ROM_uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC11 | UDMA_PRI_SELECT);//if udma primary control structure is done transfering data, re-enable itif(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 modeui32Mode = ROM_uDMAChannelModeGet(UDMA_SEC_CHANNEL_ADC11 | UDMA_ALT_SELECT);//if udma secondary control structure is done transfering data, re-enable itif(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 speedROM_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++;}
}

xyz549040622:

工程打包如下所示,代码来自于github:

adc-dma-pingpong-tm4c1294-master.zip

Susan Yang:

谢谢分享!

赞(0)
未经允许不得转载:TI中文支持网 » 基于tm4c1294+ADC+DMA的代码分享
分享到: 更多 (0)