Other Parts Discussed in Thread: TM4C1294NCZAD
Tool/software: Code Composer Studio
Hey Bob, I was working on a project involving sampling external analog signal. I saw your post above in which you provided with a example file. So, I tried to run the code with small modification as I am working on DK-TM4C129X. My project files are attached below.
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_adc.h"
#include "inc/hw_types.h"
#include "inc/hw_udma.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "driverlib/udma.h"
#include "driverlib/timer.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/systick.h"
#include "utils/uartstdio.h"
#define ADC_SAMPLE_BUF_SIZE 64
enum BUFFERSTATUS
{ EMPTY,
FILLING,
FULL
};
#pragma DATA_ALIGN(ucControlTable, 1024)
uint8_t ucControlTable[1024];
static uint16_t ADC_Out1[ADC_SAMPLE_BUF_SIZE];
static uint16_t ADC_Out2[ADC_SAMPLE_BUF_SIZE];
static enum BUFFERSTATUS BufferStatus[2];
void ConfigureUART(void);
void init_ADC(void);
void init_TIMER(void);
void init_DMA(void);
static uint32_t g_ui32DMAErrCount = 0u;
static uint32_t g_ui32SysTickCount;
void uDMAErrorHandler(void)
{
uint32_t ui32Status;
ui32Status = MAP_uDMAErrorStatusGet();
if(ui32Status)
{
MAP_uDMAErrorStatusClear();
g_ui32DMAErrCount++;
}
}
// Not used in this example, but used to debug to make sure timer interrupts happen
void Timer0AIntHandler(void)
{
//
// Clear the timer interrupt flag.
//
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}
void SysTickIntHandler(void)
{
// Update our system tick counter.
g_ui32SysTickCount++;
}
void ADCseq0Handler()
{
ADCIntClear(ADC0_BASE, 0);
if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT) == UDMA_MODE_STOP)
&& (BufferStatus[0] == FILLING))
{
BufferStatus[0] = FULL;
BufferStatus[1] = FILLING;
}
else if ((uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT) == UDMA_MODE_STOP)
&& (BufferStatus[1] == FILLING))
{
BufferStatus[0] = FILLING;
BufferStatus[1] = FULL;
}
}
int main(void)
{
uint32_t i, average1, average2, samples_taken;
// Set the system clock to run at 80MHz from the PLL.
//SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
SysCtlDelay(20u);
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //Enable the clock to TIMER0
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //Enable the clock to ADC module
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); //Enable the clock to uDMA
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Enables the clock to PORT E
MAP_SysCtlDelay(30u);
MAP_SysTickPeriodSet(SysCtlClockGet() / 100000u); //Sets the period of the SysTic counter to 10us
MAP_SysTickIntEnable();
MAP_SysTickEnable();
BufferStatus[0] = FILLING;
BufferStatus[1] = EMPTY;
samples_taken = 0u;
ConfigureUART();
UARTprintf("Timer->ADC->uDMA demo!\n");
UARTprintf("\tAverage1\tAverage2\tTotal Samples\n");
init_DMA();
init_ADC();
init_TIMER();
MAP_IntMasterEnable();
MAP_TimerEnable(TIMER0_BASE, TIMER_A); // Start everything
while(1)
{
if(BufferStatus[0u] == FULL)
{
// Do something with data in ADC_OUT1
average1 = 0u;
for(i =0u; i < ADC_SAMPLE_BUF_SIZE; i++)
{
average1 += ADC_Out1[i];
ADC_Out1[i] = 0u;
}
BufferStatus[0u] = EMPTY;
// Enable for another uDMA block transfer
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_Out1, ADC_SAMPLE_BUF_SIZE);
uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT); // Enables DMA channel so it can perform transfers
samples_taken += ADC_SAMPLE_BUF_SIZE;
average1 = (average1 + (ADC_SAMPLE_BUF_SIZE / 2u)) / ADC_SAMPLE_BUF_SIZE;
}
if(BufferStatus[1u] == FULL)
{
// Do something with data in ADC_OUT2
average2 = 0u;
for(i =0u; i < ADC_SAMPLE_BUF_SIZE; i++)
{
average2 += ADC_Out2[i];
ADC_Out2[i] = 0u;
}
BufferStatus[1u] = EMPTY;
// Enable for another uDMA block transfer
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_Out2, ADC_SAMPLE_BUF_SIZE);
uDMAChannelEnable(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);
samples_taken += ADC_SAMPLE_BUF_SIZE;
average2 = (average2 + (ADC_SAMPLE_BUF_SIZE / 2u)) / ADC_SAMPLE_BUF_SIZE;
UARTprintf("\t%d\t\t%d\t\t%d\r", average1,average2,samples_taken);
}
}
}
void init_TIMER()
{
MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC);
// Set sample frequency to 16KHz (every 62.5uS)
MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, MAP_SysCtlClockGet()/16000 -1); //TODO: Timer Load Value is set here
MAP_TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
MAP_TimerControlStall(TIMER0_BASE, TIMER_A, true); //Assist in debug by stalling timer at breakpoints
}
void init_ADC()
{
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
SysCtlDelay(80u);
// Use ADC0 sequence 0 to sample channel 0 once for each timer period
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_HALF, 1);
SysCtlDelay(10); // Time for the clock configuration to set
IntDisable(INT_ADC0SS0);
ADCIntDisable(ADC0_BASE, 0u);
ADCSequenceDisable(ADC0_BASE,0u);
// With sequence disabled, it is now safe to load the new configuration parameters
ADCSequenceConfigure(ADC0_BASE, 0u, ADC_TRIGGER_TIMER, 0u);
ADCSequenceStepConfigure(ADC0_BASE,0u,0u,ADC_CTL_CH0| ADC_CTL_END | ADC_CTL_IE);
ADCSequenceEnable(ADC0_BASE,0u); //Once configuration is set, re-enable the sequencer
ADCIntClear(ADC0_BASE,0u);
ADCSequenceDMAEnable(ADC0_BASE,0);
IntEnable(INT_ADC0SS0);
}
void init_DMA()
{
uDMAEnable(); // Enables uDMA
uDMAControlBaseSet(ucControlTable);
uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0, UDMA_ATTR_USEBURST);
// Only allow burst transfers
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_Out1, ADC_SAMPLE_BUF_SIZE);
uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_Out2, ADC_SAMPLE_BUF_SIZE);
uDMAChannelEnable(UDMA_CHANNEL_ADC0); // Enables DMA channel so it can perform transfers
}
//*****************************************************************************
//
// Configure the UART and its pins. This must be called before UARTprintf().
//
//*****************************************************************************
void
ConfigureUART(void)
{
//
// Enable the GPIO Peripheral used by the UART.
//
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Enable UART0
//
MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
//
// Configure GPIO Pins for UART mode.
//
MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Use the internal 16MHz oscillator as the UART clock source.
//
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, 16000000);
}
//*****************************************************************************
//
// Startup code for use with TI's Code Composer Studio.
//
// Copyright (c) 2011-2014 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
//*****************************************************************************
#include <stdint.h>
//*****************************************************************************
//
// Forward declaration of the default fault handlers.
//
//*****************************************************************************
void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);
//*****************************************************************************
//
// External declaration for the reset handler that is to be called when the
// processor is started
//
//*****************************************************************************
extern void _c_int00(void);
//*****************************************************************************
//
// Linker variable that marks the top of the stack.
//
//*****************************************************************************
extern uint32_t __STACK_TOP;
//*****************************************************************************
//
// External declarations for the interrupt handlers used by the application.
//
//*****************************************************************************
extern void uDMAErrorHandler(void);
extern void Timer0AIntHandler(void);
extern void SysTickIntHandler(void);
extern void ADCseq0Handler();
//*****************************************************************************
//
// The vector table. Note that the proper constructs must be placed on this to
// ensure that it ends up at physical address 0x0000.0000 or at the start of
// the program if located at a start address other than 0.
//
//*****************************************************************************
#pragma DATA_SECTION(g_pfnVectors, ".intvecs")
void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((uint32_t)&__STACK_TOP),
// The initial stack pointer
ResetISR, // The reset handler
NmiSR, // The NMI handler
FaultISR, // The hard fault handler
IntDefaultHandler, // The MPU fault handler
IntDefaultHandler, // The bus fault handler
IntDefaultHandler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
IntDefaultHandler, // SVCall handler
IntDefaultHandler, // Debug monitor handler
0, // Reserved
IntDefaultHandler, // The PendSV handler
SysTickIntHandler, // The SysTick handler
IntDefaultHandler, // GPIO Port A
IntDefaultHandler, // GPIO Port B
IntDefaultHandler, // GPIO Port C
IntDefaultHandler, // GPIO Port D
IntDefaultHandler, // GPIO Port E
IntDefaultHandler, // UART0 Rx and Tx
IntDefaultHandler, // UART1 Rx and Tx
IntDefaultHandler, // SSI0 Rx and Tx
IntDefaultHandler, // I2C0 Master and Slave
IntDefaultHandler, // PWM Fault
IntDefaultHandler, // PWM Generator 0
IntDefaultHandler, // PWM Generator 1
IntDefaultHandler, // PWM Generator 2
IntDefaultHandler, // Quadrature Encoder 0
ADCseq0Handler, // ADC Sequence 0
IntDefaultHandler, // ADC Sequence 1
IntDefaultHandler, // ADC Sequence 2
IntDefaultHandler, // ADC Sequence 3
IntDefaultHandler, // Watchdog timer
Timer0AIntHandler, // Timer 0 subtimer A
IntDefaultHandler, // Timer 0 subtimer B
IntDefaultHandler, // Timer 1 subtimer A
IntDefaultHandler, // Timer 1 subtimer B
IntDefaultHandler, // Timer 2 subtimer A
IntDefaultHandler, // Timer 2 subtimer B
IntDefaultHandler, // Analog Comparator 0
IntDefaultHandler, // Analog Comparator 1
IntDefaultHandler, // Analog Comparator 2
IntDefaultHandler, // System Control (PLL, OSC, BO)
IntDefaultHandler, // FLASH Control
IntDefaultHandler, // GPIO Port F
IntDefaultHandler, // GPIO Port G
IntDefaultHandler, // GPIO Port H
IntDefaultHandler, // UART2 Rx and Tx
IntDefaultHandler, // SSI1 Rx and Tx
IntDefaultHandler, // Timer 3 subtimer A
IntDefaultHandler, // Timer 3 subtimer B
IntDefaultHandler, // I2C1 Master and Slave
IntDefaultHandler, // CAN0
IntDefaultHandler, // CAN1
IntDefaultHandler, // Ethernet
IntDefaultHandler, // Hibernate
IntDefaultHandler, // USB0
IntDefaultHandler, // PWM Generator 3
IntDefaultHandler, // uDMA Software Transfer
uDMAErrorHandler, // uDMA Error
IntDefaultHandler, // ADC1 Sequence 0
IntDefaultHandler, // ADC1 Sequence 1
IntDefaultHandler, // ADC1 Sequence 2
IntDefaultHandler, // ADC1 Sequence 3
IntDefaultHandler, // External Bus Interface 0
IntDefaultHandler, // GPIO Port J
IntDefaultHandler, // GPIO Port K
IntDefaultHandler, // GPIO Port L
IntDefaultHandler, // SSI2 Rx and Tx
IntDefaultHandler, // SSI3 Rx and Tx
IntDefaultHandler, // UART3 Rx and Tx
IntDefaultHandler, // UART4 Rx and Tx
IntDefaultHandler, // UART5 Rx and Tx
IntDefaultHandler, // UART6 Rx and Tx
IntDefaultHandler, // UART7 Rx and Tx
IntDefaultHandler, // I2C2 Master and Slave
IntDefaultHandler, // I2C3 Master and Slave
IntDefaultHandler, // Timer 4 subtimer A
IntDefaultHandler, // Timer 4 subtimer B
IntDefaultHandler, // Timer 5 subtimer A
IntDefaultHandler, // Timer 5 subtimer B
IntDefaultHandler, // FPU
0, // Reserved
0, // Reserved
IntDefaultHandler, // I2C4 Master and Slave
IntDefaultHandler, // I2C5 Master and Slave
IntDefaultHandler, // GPIO Port M
IntDefaultHandler, // GPIO Port N
0, // Reserved
IntDefaultHandler, // Tamper
IntDefaultHandler, // GPIO Port P (Summary or P0)
IntDefaultHandler, // GPIO Port P1
IntDefaultHandler, // GPIO Port P2
IntDefaultHandler, // GPIO Port P3
IntDefaultHandler, // GPIO Port P4
IntDefaultHandler, // GPIO Port P5
IntDefaultHandler, // GPIO Port P6
IntDefaultHandler, // GPIO Port P7
IntDefaultHandler, // GPIO Port Q (Summary or Q0)
IntDefaultHandler, // GPIO Port Q1
IntDefaultHandler, // GPIO Port Q2
IntDefaultHandler, // GPIO Port Q3
IntDefaultHandler, // GPIO Port Q4
IntDefaultHandler, // GPIO Port Q5
IntDefaultHandler, // GPIO Port Q6
IntDefaultHandler, // GPIO Port Q7
IntDefaultHandler, // GPIO Port R
IntDefaultHandler, // GPIO Port S
IntDefaultHandler, // SHA/MD5 0
IntDefaultHandler, // AES 0
IntDefaultHandler, // DES3DES 0
IntDefaultHandler, // LCD Controller 0
IntDefaultHandler, // Timer 6 subtimer A
IntDefaultHandler, // Timer 6 subtimer B
IntDefaultHandler, // Timer 7 subtimer A
IntDefaultHandler, // Timer 7 subtimer B
IntDefaultHandler, // I2C6 Master and Slave
IntDefaultHandler, // I2C7 Master and Slave
IntDefaultHandler, // HIM Scan Matrix Keyboard 0
IntDefaultHandler, // One Wire 0
IntDefaultHandler, // HIM PS/2 0
IntDefaultHandler, // HIM LED Sequencer 0
IntDefaultHandler, // HIM Consumer IR 0
IntDefaultHandler, // I2C8 Master and Slave
IntDefaultHandler, // I2C9 Master and Slave
IntDefaultHandler, // GPIO Port T
IntDefaultHandler, // Fan 1
0, // Reserved
};
//*****************************************************************************
//
// This is the code that gets called when the processor first starts execution
// following a reset event. Only the absolutely necessary set is performed,
// after which the application supplied entry() routine is called. Any fancy
// actions (such as making decisions based on the reset cause register, and
// resetting the bits in that register) are left solely in the hands of the
// application.
//
//*****************************************************************************
void
ResetISR(void)
{
//
// Jump to the CCS C initialization routine. This will enable the
// floating-point unit as well, so that does not need to be done here.
//
__asm(" .global _c_int00\n"
" b.w _c_int00");
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI. This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
static void
NmiSR(void)
{
//
// Enter an infinite loop.
//
while(1)
{
}
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
FaultISR(void)
{
//
// Enter an infinite loop.
//
while(1)
{
}
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
IntDefaultHandler(void)
{
//
// Go into an infinite loop.
//
while(1)
{
}
}
I gave analog signal input as a square wave of 1kHz and 1Vpp at PE2 from a function generator and connected ground of function generator pin to board's ground. When I ran this code in CCSv6, the buffers ADC_Out1 and ADC_Out2 were filled, and when I plotted them using CCS graph window, how do I verify if the values are correct or not? Like I should get a square wave or part of it in graph, but it was nothing like that. My ADC_Out1 was plotted like this.
And ADC_Out2 was like this:
Can you please help me to figure out whats wrong or how can I get something similar to sqaure wave as an output in array, because my project involves calculation of FFT after getting that array.
And one more question, can I just change the buffer size to like 128,256 or high to get large buffer size or do I also have to change some uDMA part of the code also?
Regards,
Harshul Agarwal