Other Parts Discussed in Thread: CONTROLSUITE
Tool/software: Code Composer Studio
Hy Guys,
i wish use DMA to collect data from ADC.
I wrote this code, can you help me to understand malfunction? Can you check the settings of adc and dma?
#include "F28x_Project.h"// Device Headerfile and Examples Include File
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#define RFFT_STAGES 11
#define RFFT_SIZE (1 << RFFT_STAGES)
#pragma DATA_SECTION(ADCin1Buff,"RFFTdata7");
int16_t ADCin1Buff[RFFT_SIZE];
void DMA_configure(void);
interrupt void local_DMACH1_ISR(void);
void ConfigureADC(void); //ADC,PWM
void ConfigureEPWM(void);
void SetupADCEpwm(Uint16 channel);
interrupt void adca1_isr(void); //ADC Isr
volatile Uint16 bufferFull;
volatile Uint16 resultsIndex;
void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xS_SysCtrl.c file.
InitSysCtrl();
// Step 2. Initialize GPIO:
// This example function is found in the F2837xS_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
InitGpio(); // Skipped for this example
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xS_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xS_DefaultIsr.c.
// This function is found in F2837xS_PieVect.c.
InitPieVectTable();
//Map ISR functions
EALLOW;
PieVectTable.ADCA1_INT = &adca1_isr; //function for ADCA interrupt 1
PieVectTable.DMA_CH1_INT = &local_DMACH1_ISR; //function for DMA interrupt 1
EDIS;
//Configure the ADC and power it up
ConfigureADC();
//Configure the ePWM
ConfigureEPWM();
//Setup the ADC for ePWM triggered conversions on channel 0
SetupADCEpwm(0);
DMA_configure();
//Enable global Interrupts and higher priority real-time debug events:
//IER |= M_INT1; //Enable group 1 interrupts
IER |= M_INT7;
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
bufferFull = 0;
EINT; // Enable Global Interrupts
//enable PIE interrupt
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
//sync ePWM
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
//start ePWM
EPwm1Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA
EPwm1Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode
while(!bufferFull);
bufferFull = 0; //clear the buffer full flag
asm(" ESTOP0");
while(1);
}
//Write ADC configurations and power up the ADC for both ADC A and ADC B
void ConfigureADC(void)
{
EALLOW;
//write configurations
AdcaRegs.ADCCTL2.bit.PRESCALE = 0b0110; //set ADCCLK divider to /4
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
//AdcSetMode(ADC_ADCA, ADC_RESOLUTION_16BIT, ADC_SIGNALMODE_DIFFERENTIAL);
//Set pulse positions to late
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
//power up the ADC
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
//delay for 1ms to allow ADC time to power up
DELAY_US(1000);
EDIS;
}
void ConfigureEPWM(void)
{
EALLOW;
// Assumes ePWM clock is already enabled
EPwm1Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC on up-count
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm1Regs.CMPA.bit.CMPA = 311;
EPwm1Regs.TBPRD = 624;
EPwm1Regs.TBCTL.bit.CTRMODE = 3; // freeze counter
EDIS;
}
void SetupADCEpwm(Uint16 channel)
{
Uint16 acqps;
//determine minimum acquisition window (in SYSCLKS) based on resolution
if((ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)){
acqps = 14; //75ns
}
else { //resolution is 16-bit
acqps = 63; //320ns
}
//Select the channels to convert and end of conversion flag
EALLOW;
AdcaRegs.ADCSOC0CTL.bit.CHSEL = channel; //SOC0 will convert pin A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA/C
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; //end of SOC0 will set INT1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
}
interrupt void adca1_isr(void)
{
ADCin1Buff[resultsIndex++] = (AdcaResultRegs.ADCRESULT0);
if(RFFT_SIZE<=resultsIndex )
{
resultsIndex = 0;
bufferFull = 1;
}
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
interrupt void local_DMACH1_ISR(void)
{
//DMA_Done = 0x0001;
EALLOW;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
//DmaRegs.CH1.CONTROL.bit.TRANSFERSTS = 1;
//DmaRegs.CH1.CONTROL.bit.RUN = 1;
bufferFull = 1;
EDIS;
// ESTOP0;
}
void DMA_configure(void)
{
DMAInitialize();
DMACH1AddrConfig((volatile Uint16 *)ADCin1Buff, &AdcaResultRegs.ADCRESULT0);
DMACH1BurstConfig(15,0,2);
DMACH1TransferConfig(((RFFT_SIZE >>4)-1),0,2);
DMACH1ModeConfig( DMA_ADCAINT1,
PERINT_ENABLE,
ONESHOT_DISABLE,
CONT_DISABLE,
SYNC_DISABLE,
SYNC_SRC,
OVRFLOW_DISABLE,
THIRTYTWO_BIT,
CHINT_END,
CHINT_ENABLE);
StartDMACH1();
}
Thank you very much.
Best regards
Paolo Marsilia