Part Number: TM4C129EKCPDT
Tool/software: TI C/C++ Compiler
I can read two voltage from ADC 9 and ADC 11, but I can't use udma to save the two ADC value to array.
I don't know how to config udma with two adc channel.
I try use udma repeatedly ,but failed.
can you help me .I want to read ADC9 and ADC11 voltage use udma. that I can get the two voltage value from array.
thank you ! if you can ,can you give me some demo adbut use two adc with udma.
my code ( udna part is error,and I cannot confirm adc part is correct ):
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "driverlib/adc.h"
#include "rom_map.h"
#include "hw_adc.h"
#include "driverlib/gpio.h"
#include <string.h>
#include "stdio.h"
#include "drv_adc.h"
#include <rtthread.h>
#include "hw_memmap.h"
#include "hw_ints.h"
#include "tiva_timer.h"
#include "interrupt.h"
#include "rom.h"
#include "plc_config.h"
uint32_t g_ui32SysClock;
//*****************************************************************************
//
// The control table used by the uDMA controller. This table must be aligned
// to a 1024 byte boundary.
//
//*****************************************************************************
#if defined(ewarm)
#pragma data_alignment=1024
uint8_t pui8ControlTable[1024];
#elif defined(ccs)
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];
#else
uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
#endif
//*****************************************************************************
//
// The size of the memory transfer source and destination buffers (in words).
//
//*****************************************************************************
#define MEM_BUFFER_SIZE 1024
//*****************************************************************************
//
// The source and destination buffers used for memory transfers.
//
//*****************************************************************************
static uint32_t g_ui32SrcBuf[MEM_BUFFER_SIZE];
static uint32_t g_ui32DstBuf[MEM_BUFFER_SIZE];
//*****************************************************************************
//
// The count of uDMA errors. This value is incremented by the uDMA error
// handler.
//
//*****************************************************************************
static volatile uint32_t g_ui32uDMAErrCount = 0;
//*****************************************************************************
//
// The count of memory uDMA transfer blocks. This value is incremented by the
// uDMA interrupt handler whenever a memory block transfer is completed.
//
//*****************************************************************************
static volatile uint32_t g_ui32MemXferCount = 0;
//*****************************************************************************
//
// The count of times the uDMA interrupt occurred but the uDMA transfer was not
// complete. This should remain 0.
//
//*****************************************************************************
static volatile uint32_t g_ui32BadISR = 0;
#define ADC_BUFF_SIZE 64
extern char HardVer[5];
uint32_t adc_value;
float R=0;
float TEMP=0;
uint16_t g_temp;
uint16_t g_vol;
uint16_t g_ele;
//*****************************************************************************
//
// Initializes the uDMA software channel to perform a memory to memory uDMA
// transfer.
//
//*****************************************************************************
void
InitADC0Transfer(void)
{
uint_fast16_t ui16Idx;
//
// Fill the source memory buffer with a simple incrementing pattern.
//
for(ui16Idx = 0; ui16Idx < MEM_BUFFER_SIZE; ui16Idx++)
{
g_ui32SrcBuf[ui16Idx] = ui16Idx;
}
//
// Enable interrupts from the uDMA software channel.
//
IntEnable(INT_UDMA);
//
// Put the attributes in a known state for the uDMA software channel.
// These should already be disabled by default.
//
uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
(UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK));
//
// Configure the control parameters for the SW channel. The SW channel
// will be used to transfer between two memory buffers, 32 bits at a time.
// Therefore the data size is 32 bits, and the address increment is 32 bits
// for both source and destination. The arbitration size will be set to 8,
// which causes the uDMA controller to rearbitrate after 8 items are
// transferred. This keeps this channel from hogging the uDMA controller
// once the transfer is started, and allows other channels cycles if they
// are higher priority.
//
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 |
UDMA_ARB_8);
//
// Set up the transfer parameters for the software channel. This will
// configure the transfer buffers and the transfer size. Auto mode must be
// used for software transfers.
//
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
UDMA_MODE_AUTO, g_ui32SrcBuf, g_ui32DstBuf,
MEM_BUFFER_SIZE);
//
// Now the software channel is primed to start a transfer. The channel
// must be enabled. For software based transfers, a request must be
// issued. After this, the uDMA memory transfer begins.
//
uDMAChannelEnable(UDMA_CHANNEL_ADC0);
uDMAChannelRequest(UDMA_CHANNEL_ADC0);
}
//*****************************************************************************
//
// The interrupt handler for uDMA errors. This interrupt will occur if the
// uDMA encounters a bus error while trying to perform a transfer. This
// handler just increments a counter if an error occurs.
//
//*****************************************************************************
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
//
// Check for uDMA error bit
//
ui32Status = uDMAErrorStatusGet();
//
// If there is a uDMA error, then clear the error and increment
// the error counter.
//
if(ui32Status)
{
uDMAErrorStatusClear();
g_ui32uDMAErrCount++;
}
}
//*****************************************************************************
//
// The interrupt handler for uDMA interrupts from the memory channel. This
// interrupt will increment a counter, and then restart another memory
// transfer.
//
//*****************************************************************************
void
uDMAIntHandler(void)
{
uint32_t ui32Mode;
//
// Check for the primary control structure to indicate complete.
//
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0);
if(ui32Mode == UDMA_MODE_STOP)
{
//
// Increment the count of completed transfers.
//
g_ui32MemXferCount++;
//
// Configure it for another transfer.
//
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0, UDMA_MODE_AUTO,
g_ui32SrcBuf, g_ui32DstBuf,
MEM_BUFFER_SIZE);
//
// Initiate another transfer.
//
uDMAChannelEnable(UDMA_CHANNEL_ADC0);
uDMAChannelRequest(UDMA_CHANNEL_ADC0);
}
//
// If the channel is not stopped, then something is wrong.
//
else
{
g_ui32BadISR++;
}
}
void ADC_Init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//ADC GPIO-B VER
GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);//ADC PIN
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH10 | ADC_CTL_IE |ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE, 1);
ADCIntClear(ADC0_BASE, 1);
ADCIntEnable(ADC0_BASE, 1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5);
ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH8 | ADC_CTL_IE |ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE, 3);
ADCIntClear(ADC0_BASE, 3);
ADCIntEnable(ADC0_BASE, 3);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//ADC GPIO-E
GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_5);//
ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH11 | ADC_CTL_IE |ADC_CTL_END);
ADCSequenceEnable(ADC0_BASE, 2);
ADCIntClear(ADC0_BASE, 2);
ADCIntEnable(ADC0_BASE, 2);
IntEnable(INT_ADC0SS0);
return;
}
void DMA_init(void)
{
//
// Enable the uDMA controller at the system level. Enable it to continue
// to run while the processor is in sleep.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
//
// Enable the uDMA controller error interrupt. This interrupt will occur
// if there is a bus error during a transfer.
//
IntEnable(INT_UDMAERR);
// Enable the uDMA
uDMAEnable();
//
// Point at the control table to use for channel control structures.
//
uDMAControlBaseSet(pui8ControlTable);
//
// Initialize the uDMA memory to memory transfers.
//
InitADC0Transfer();
}
void AI_thread(void* parameter)
{
int i,value;
float V,I,RV;
float ch_read;
uint32_t p_ADC_buff[100];
ADC_Init();
// DMA_init();
while(1)
{
// read first voltage value use ADC
for(i=0;i<100;i++)
{
ADCProcessorTrigger(ADC0_BASE,3);
while(!ADCIntStatus(ADC0_BASE, 3, false))
{
}
ADCIntClear(ADC0_BASE, 3);
ADCSequenceDataGet(ADC0_BASE, 3, &p_ADC_buff[i]);
}
for(i=0, value=0; i<100; i++)
{
value += p_ADC_buff[i];
}
value = value /100;
ch_read = value*3.3/4096.0;
V = ch_read *100.0*1000.0/12.0; // V is right value
///////////////////////////////////////// read second voltage value use ADC
for(i=0;i<100;i++)
{
ADCProcessorTrigger(ADC0_BASE,2);
while(!ADCIntStatus(ADC0_BASE, 2, false))
{
}
ADCIntClear(ADC0_BASE, 2);
ADCSequenceDataGet(ADC0_BASE, 2, &p_ADC_buff[i]);
}
for(i=0, value=0; i<100; i++)
{
value += p_ADC_buff[i];
}
value = value /100;
ch_read = value*3.3/4096.0;
RV = ch_read/(100.0/10.0)/12.0; // RV is right value of voltage
rt_thread_delay(20);
}
}
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "driverlib/adc.h"
#include "rom_map.h"
#include "hw_adc.h"
#include "driverlib/gpio.h"
#include <string.h>
#include "stdio.h"
#include "drv_adc.h"
#include <rtthread.h>
#include "hw_memmap.h"
#include "hw_ints.h"
#include "tiva_timer.h"
#include "interrupt.h"
#include "rom.h"
#include "plc_config.h"
uint32_t g_ui32SysClock;
//*****************************************************************************
//
// The control table used by the uDMA controller. This table must be aligned
// to a 1024 byte boundary.
//
//*****************************************************************************
#if defined(ewarm)
#pragma data_alignment=1024
uint8_t pui8ControlTable[1024];
#elif defined(ccs)
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];
#else
uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));
#endif
//*****************************************************************************
//
// The size of the memory transfer source and destination buffers (in words).
//
//*****************************************************************************
#define MEM_BUFFER_SIZE 1024
//*****************************************************************************
//
// The source and destination buffers used for memory transfers.
//
//*****************************************************************************
static uint32_t g_ui32SrcBuf[MEM_BUFFER_SIZE];
static uint32_t g_ui32DstBuf[MEM_BUFFER_SIZE];
//*****************************************************************************
//
// The count of uDMA errors. This value is incremented by the uDMA error
// handler.
//
//*****************************************************************************
static volatile uint32_t g_ui32uDMAErrCount = 0;
//*****************************************************************************
//
// The count of memory uDMA transfer blocks. This value is incremented by the
// uDMA interrupt handler whenever a memory block transfer is completed.
//
//*****************************************************************************
static volatile uint32_t g_ui32MemXferCount = 0;
//*****************************************************************************
//
// The count of times the uDMA interrupt occurred but the uDMA transfer was not
// complete. This should remain 0.
//
//*****************************************************************************
static volatile uint32_t g_ui32BadISR = 0;
#define ADC_BUFF_SIZE 64
extern char HardVer[5];
uint32_t adc_value;
float R=0;
float TEMP=0;
uint16_t g_temp;
uint16_t g_vol;
uint16_t g_ele;
//*****************************************************************************
//
// Initializes the uDMA software channel to perform a memory to memory uDMA
// transfer.
//
//*****************************************************************************
void
InitADC0Transfer(void)
{
uint_fast16_t ui16Idx;
//
// Fill the source memory buffer with a simple incrementing pattern.
//
for(ui16Idx = 0; ui16Idx < MEM_BUFFER_SIZE; ui16Idx++)
{
g_ui32SrcBuf[ui16Idx] = ui16Idx;
}
//
// Enable interrupts from the uDMA software channel.
//
IntEnable(INT_UDMA);
//
// Put the attributes in a known state for the uDMA software channel.
// These should already be disabled by default.
//
uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
(UDMA_ATTR_HIGH_PRIORITY |
UDMA_ATTR_REQMASK));
//
// Configure the control parameters for the SW channel. The SW channel
// will be used to transfer between two memory buffers, 32 bits at a time.
// Therefore the data size is 32 bits, and the address increment is 32 bits
// for both source and destination. The arbitration size will be set to 8,
// which causes the uDMA controller to rearbitrate after 8 items are
// transferred. This keeps this channel from hogging the uDMA controller
// once the transfer is started, and allows other channels cycles if they
// are higher priority.
//
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 |
UDMA_ARB_8);
//
// Set up the transfer parameters for the software channel. This will
// configure the transfer buffers and the transfer size. Auto mode must be
// used for software transfers.
//
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
UDMA_MODE_AUTO, g_ui32SrcBuf, g_ui32DstBuf,
MEM_BUFFER_SIZE);
//
// Now the software channel is primed to start a transfer. The channel
// must be enabled. For software based transfers, a request must be
// issued. After this, the uDMA memory transfer begins.
//
uDMAChannelEnable(UDMA_CHANNEL_ADC0);
uDMAChannelRequest(UDMA_CHANNEL_ADC0);
}
//*****************************************************************************
//
// The interrupt handler for uDMA errors. This interrupt will occur if the
// uDMA encounters a bus error while trying to perform a transfer. This
// handler just increments a counter if an error occurs.
//
//*****************************************************************************
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
//
// Check for uDMA error bit
//
ui32Status = uDMAErrorStatusGet();
//
// If there is a uDMA error, then clear the error and increment
// the error counter.
//
if(ui32Status)
{
uDMAErrorStatusClear();
g_ui32uDMAErrCount++;
}
}
//*****************************************************************************
//
// The interrupt handler for uDMA interrupts from the memory channel. This
// interrupt will increment a counter, and then restart another memory
// transfer.
//
//*****************************************************************************
void
uDMAIntHandler(void)
{
uint32_t ui32Mode;
//
// Check for the primary control structure to indicate complete.
//
ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0);
if(ui32Mode == UDMA_MODE_STOP)
{
//
// Increment the count of completed transfers.
//
g_ui32MemXferCount++;
//
// Configure it for another transfer.
//
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0, UDMA_MODE_AUTO,
g_ui32SrcBuf, g_ui32DstBuf,
MEM_BUFFER_SIZE);
//
// Initiate another transfer.
//
uDMAChannelEnable(UDMA_CHANNEL_ADC0);
uDMAChannelRequest(UDMA_CHANNEL_ADC0);
}
//
// If the channel is not stopped, then something is wrong.
//
else
{
g_ui32BadISR++;
}
}
void ADC_Init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //?a??ADC0
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//?a??ADC GPIO-B VER
GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_4);//????ADC ��y??PIN
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);//D����D����??��?????D����D��?����?���䣤�����?��??��??0
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH10 | ADC_CTL_IE |ADC_CTL_END); //2��?�������̨�10 VER
ADCSequenceEnable(ADC0_BASE, 1);//��1?��2��?��D����D��1?��
ADCIntClear(ADC0_BASE, 1); //??3y?D??����??
ADCIntEnable(ADC0_BASE, 1);//ADC?D??��1?��
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);//?a??ADC GPIO-E ��??1��?����
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5);//????ADC ��y??PIN
ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);//D����D����??��?????D����D��?����?���䣤�����?��??��??0
ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH8 | ADC_CTL_IE |ADC_CTL_END); //2��?�������̨�8 ��??1��?����
ADCSequenceEnable(ADC0_BASE, 3);//��1?��2��?��D����D��1?��
ADCIntClear(ADC0_BASE, 3); //??3y?D??����??
ADCIntEnable(ADC0_BASE, 3);//ADC?D??��1?��
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//?a??ADC GPIO-E ��??1��?����
GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_5);//????ADC ��y??PIN
ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_PROCESSOR, 0);//D����D����??��?????D����D��?����?���䣤�����?��??��??0
ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH11 | ADC_CTL_IE |ADC_CTL_END); //2��?�������̨�8 ��??1��?����
ADCSequenceEnable(ADC0_BASE, 2);//��1?��2��?��D����D��1?��
ADCIntClear(ADC0_BASE, 2); //??3y?D??����??
ADCIntEnable(ADC0_BASE, 2);//ADC?D??��1?��
IntEnable(INT_ADC0SS0);//��1?��ADC2��?��D����D?D??
return;
}
void DMA_init(void)
{
//
// Enable the uDMA controller at the system level. Enable it to continue
// to run while the processor is in sleep.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
//
// Enable the uDMA controller error interrupt. This interrupt will occur
// if there is a bus error during a transfer.
//
IntEnable(INT_UDMAERR);
// Enable the uDMA
uDMAEnable();
//
// Point at the control table to use for channel control structures.
//
uDMAControlBaseSet(pui8ControlTable);
//
// Initialize the uDMA memory to memory transfers.
//
InitADC0Transfer();
}
void AI_thread(void* parameter)
{
int i,value;
float V,I,RV;
float ch_read;
uint32_t p_ADC_buff[100];
ADC_Init();
// DMA_init();
while(1)
{
// read first voltage value use ADC
for(i=0;i<100;i++)
{
ADCProcessorTrigger(ADC0_BASE,3);
while(!ADCIntStatus(ADC0_BASE, 3, false))
{
}
ADCIntClear(ADC0_BASE, 3);
ADCSequenceDataGet(ADC0_BASE, 3, &p_ADC_buff[i]);
}
for(i=0, value=0; i<100; i++)
{
value += p_ADC_buff[i];
}
value = value /100;
ch_read = value*3.3/4096.0;
V = ch_read *100.0*1000.0/12.0; // V is right value
///////////////////////////////////////// read second voltage value use ADC
for(i=0;i<100;i++)
{
ADCProcessorTrigger(ADC0_BASE,2);
while(!ADCIntStatus(ADC0_BASE, 2, false))
{
}
ADCIntClear(ADC0_BASE, 2);
ADCSequenceDataGet(ADC0_BASE, 2, &p_ADC_buff[i]);
}
for(i=0, value=0; i<100; i++)
{
value += p_ADC_buff[i];
}
value = value /100;
ch_read = value*3.3/4096.0;
RV = ch_read/(100.0/10.0)/12.0; // RV is right value of voltage
rt_thread_delay(20);
}
}