Other Parts Discussed in Thread: TMS320F28377S, TMS320F28377D
Hello,
I am new in C2000 programming. I will start a question that is big, but threre's no way to axplain my problem, so I sorry for the English and the size of the post,
I'm studing LAUNCHXL-F28377S using the Workshop avaiable in
.
In Lab 6, there's a exercise to learn how configurate the ADC trigered by ePWM2.
Although the workshop is to the TMS320F28377D, I made the necessary modifications to be compatible with my TMS320F28377S. This includes changing the headers and pins. As stated in the Student Guide:
The objective of this lab is to become familiar with the programming and operation of the on-chip analog-to-digital converter. The MCU will be setup to sample a single ADC input channel at a prescribed sampling rate and store the conversion result in a circular memory buffer.
In this lab, we will be using the ADC for data acquisition. Therefore, one of the ePWMs (ePWM2) will be configured to automatically trigger the SOCA signal at the desired sampling rate (ePWM period match CTR = PRD). The ADC end-of-conversion interrupt will be used to prompt the CPU to copy the results of the ADC conversion into a results buffer in memory. This buffer pointer will be managed in a circular fashion, such that new conversion results will continuously overwrite older conversion results in the buffer.
My main code is as follow, that is equal to the solution. There's nothing in the main loop and the processor just waits for the ePWM2 to triger the ADC converter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /**********************************************************************
* File: Main_6.c -- File for Lab 6
* Devices: TMS320F28x7x
* Author: Technical Training Organization (TTO), Texas Instruments
**********************************************************************/
#include "F28x_Project.h" // Device Headerfile and Examples Include File
#include "LabS.h" // Main include file
//--- Global Variables
Uint16 DEBUG_TOGGLE = 1; // Used for realtime mode investigation test
Uint16 SINE_ENABLE = 0; // Used for DAC waveform generation
Uint16 AdcBuf[ADC_BUF_LEN]; // ADC buffer allocation
Uint16 DacOffset; // DAC offset
Uint16 DacOutput; // DAC output
/**********************************************************************
* Function: main()
*
* Description: Main function for C28x workshop labs
**********************************************************************/
void main(void)
{
//--- CPU Initialization
InitSysCtrl(); // Initialize the CPU (FILE: SysCtrl.c)
InitGpio(); // Initialize the shared GPIO pins (FILE: Gpio.c)
InitXbar(); // Initialize the input, output & ePWM X-Bar (FILE: Xbar.c)
InitPieCtrl(); // Initialize and enable the PIE (FILE: PieCtrl.c)
InitWatchdog(); // Initialize the Watchdog Timer (FILE: WatchDog.c)
//--- Peripheral Initialization
InitAdca(); // Initialize the ADC-A (FILE: Adc.c)
InitDacb(); // Initialize the DAC-B (File: Dac.c)
InitEPwm(); // Initialize the EPwm (FILE: EPwm.c)
//--- Enable global interrupts
asm(" CLRC INTM, DBGM"); // Enable global interrupts and realtime debug
//--- Main Loop
while(1) // endless loop - wait for an interrupt
{
asm(" NOP");
}
} //end of main()
/*** end of file *****************************************************/ |
The InitEPwm() is as follow, again equal to the solution. It enabled the generation of signal SOC0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | /**********************************************************************
* File: EPwm_6.c -- Solution File
* Devices: TMS320F28x7x
* Author: Technical Training Organization (TTO), Texas Instruments
**********************************************************************/
#include "LabS.h" // Main include file
/**********************************************************************
* Function: InitEPwm()
*
* Description: Initializes the Enhanced PWM modules on the F28x7x
**********************************************************************/
void InitEPwm(void)
{
asm(" EALLOW"); // Enable EALLOW protected register access
// Configure the prescaler to the ePWM modules. Max ePWM input clock is 100 MHz.
ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 1; // EPWMCLK divider from PLLSYSCLK. 0=/1, 1=/2
// Must disable the clock to the ePWM modules if you want all ePWM modules synchronized.
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
asm(" EDIS"); // Disable EALLOW protected register access
//---------------------------------------------------------------------
//--- Configure ePWM2 to trigger ADC SOCA at a 50 kHz rate
//---------------------------------------------------------------------
asm(" EALLOW"); // Enable EALLOW protected register access
DevCfgRegs.SOFTPRES2.bit.EPWM2 = 1; // ePWM2 is reset
DevCfgRegs.SOFTPRES2.bit.EPWM2 = 0; // ePWM2 is released from reset
asm(" EDIS"); // Disable EALLOW protected register access
EPwm2Regs.TBCTL.bit.CTRMODE = 0x3; // Disable the timer
EPwm2Regs.TBCTL.all = 0xC033; // Configure timer control register
// bit 15-14 11: FREE/SOFT, 11 = ignore emulation suspend
// bit 13 0: PHSDIR, 0 = count down after sync event
// bit 12-10 000: CLKDIV, 000 => TBCLK = HSPCLK/1
// bit 9-7 000: HSPCLKDIV, 000 => HSPCLK = EPWMCLK/1
// bit 6 0: SWFSYNC, 0 = no software sync produced
// bit 5-4 11: SYNCOSEL, 11 = sync-out disabled
// bit 3 0: PRDLD, 0 = reload PRD on counter=0
// bit 2 0: PHSEN, 0 = phase control disabled
// bit 1-0 11: CTRMODE, 11 = timer stopped (disabled)
EPwm2Regs.TBCTR = 0x0000; // Clear timer counter
EPwm2Regs.TBPRD = ADC_SAMPLE_PERIOD; // Set timer period
EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; // Set timer phase
EPwm2Regs.ETPS.all = 0x0100; // Configure SOCA
// bit 15-14 00: EPWMxSOCB, read-only
// bit 13-12 00: SOCBPRD, don't care
// bit 11-10 00: EPWMxSOCA, read-only
// bit 9-8 01: SOCAPRD, 01 = generate SOCA on first event
// bit 7-4 0000: reserved
// bit 3-2 00: INTCNT, don't care
// bit 1-0 00: INTPRD, don't care
EPwm2Regs.ETSEL.all = 0x0A00; // Enable SOCA to ADC
// bit 15 0: SOCBEN, 0 = disable SOCB
// bit 14-12 000: SOCBSEL, don't care
// bit 11 1: SOCAEN, 1 = enable SOCA
// bit 10-8 010: SOCASEL, 010 = SOCA on PRD event
// bit 7-4 0000: reserved
// bit 3 0: INTEN, 0 = disable interrupt
// bit 2-0 000: INTSEL, don't care
EPwm2Regs.TBCTL.bit.CTRMODE = 0x0; // Enable the timer in count up mode
//---------------------------------------------------------------------
//--- Enable the clocks to the ePWM module.
//--- Note: this should be done after all ePWM modules are configured
//--- to ensure synchronization between the ePWM modules.
//---------------------------------------------------------------------
asm(" EALLOW"); // Enable EALLOW protected register access
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; // TBCLK to ePWM modules enabled
asm(" EDIS"); // Disable EALLOW protected register access
} // end InitEPwm()
//--- end of file ----------------------------------------------------- |
The InitAdca() is as follow. It setup the ADCINA0 to start after SOC0 and enable the interrupts.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | void InitAdca(void)
{
asm(" EALLOW"); // Enable EALLOW protected register access
//--- Reset the ADC. This is good programming practice.
DevCfgRegs.SOFTPRES13.bit.ADC_A = 1; // ADC is reset
DevCfgRegs.SOFTPRES13.bit.ADC_A = 0; // ADC is released from reset
//--- Configure the ADC base registers
AdcaRegs.ADCCTL1.all = 0x0004; // Main ADC configuration
// bit 15-14 00: reserved
// bit 13 0: ADCBSY, ADC busy, read-only
// bit 12 0: reserved
// bit 11-8 0's: ADCBSYCHN, ADC busy channel, read-only
// bit 7 0: ADCPWDNZ, ADC power down, 0=powered down, 1=powered up
// bit 6-3 0000: reserved
// bit 2 1: INTPULSEPOS, INT pulse generation, 0=start of conversion, 1=end of conversion
// bit 1-0 00: reserved
AdcaRegs.ADCCTL2.all = 0x0006; // ADC clock configuration
// bit 15-8 0's: reserved
// bit 7 0: SIGNALMODE, configured by AdcSetMode() below to get calibration correct
// bit 6 0: RESOLUTION, configured by AdcSetMode() below to get calibration correct
// bit 5-4 00: reserved
// bit 3-0 0110: PRESCALE, ADC clock prescaler. 0110=CPUCLK/4
AdcaRegs.ADCBURSTCTL.all = 0x0000;
// bit 15 0: BURSTEN, 0=burst mode disabled, 1=burst mode enabled
// bit 14-12 000: reserved
// bit 11-8 0000: BURSTSIZE, 0=1 SOC converted (don't care)
// bit 7-6 00: reserved
// bit 5-0 000000: BURSTTRIGSEL, 00=software only (don't care)
//--- Call AdcSetMode() to configure the resolution and signal mode.
// This also performs the correct ADC calibration for the configured mode.
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
//--- SOC0 configuration
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0x7; // Trigger SOC0 is triggered by the ePWM2 SOCA
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // Convert channel SOC0 converts input ADCINA0 in single-sample mode
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 0x13; // Acquisition window SOC0 has a 20 SYSCLK cycle acquisition window
AdcaRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // ADC interrupt triggers No ADCINT will trigger SOC0. TRIGSEL field determines SOC0 trigger.
AdcaRegs.ADCSOCPRICTL.bit.SOCPRIORITY = 0; // SOC priority mode
//--- ADCA1 interrupt configuration
AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1; // Interrupt pulses
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // ADC interrupt enable
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // EOC triggers the interrupt
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
InitPieVectTable();
//--- Enable the ADC interrupt
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable ADCA1 interrupt in PIE group 1
IER |= 1; // Enable INT1 in IER to enable PIE group
//---------------------------------------------------------------------------
// EnableInterrupts:
//---------------------------------------------------------------------------
// This function enables the PIE module and CPU __interrupts
EnableInterrupts();
//--- Finish up
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // Power up the ADC
DELAY_US(1000); // Wait 1 ms after power-up before using the ADC
asm(" EDIS"); // Disable EALLOW protected register access
} // end InitAdc()
//--- end of file ----------------------------------------------------- |
The ADC end-of-conversion interrupt function, that will be used to prompt the CPU to copy the results of the ADC conversion into a results buffer in memory is as follow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | interrupt void ADCA1_ISR(void) // PIE1.1 @ 0x000D40 ADC-A interrupt #1
{
static Uint16 *AdcBufPtr = AdcBuf; // Pointer to buffer
static Uint16 iQuadratureTable = 0; // Quadrature table index
static volatile Uint16 GPIO19_count = 0; // Counter for pin toggle
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Must acknowledge the PIE group
//--- Manage the ADC registers
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag
//--- Read the ADC result
*AdcBufPtr++ = AdcaResultRegs.ADCRESULT0; // Read the result
//--- Brute-force the circular buffer
if( AdcBufPtr == (AdcBuf + ADC_BUF_LEN) )
{
AdcBufPtr = AdcBuf; // Rewind the pointer to beginning
}
//--- Example: Toggle GPIO18 so we can read it with the ADC ***/
if(DEBUG_TOGGLE == 1)
{
GpioDataRegs.GPATOGGLE.bit.GPIO18 = 1; // Toggle the pin
}
//--- Example: Toggle GPIO19 at a 0.5 sec rate (connected to the LED on the ControlCARD).
// (1/50000 sec/sample)*(1 samples/int)*(x interrupts/toggle) = (0.5 sec/toggle)
// ==> x = 25000
if(GPIO19_count++ > 25000) // Toggle slowly to see the LED blink
{
GpioDataRegs.GPATOGGLE.bit.GPIO19 = 1; // Toggle the pin
GPIO19_count = 0; // Reset the counter
}
//--- Write to DAC-B to create input to ADC-A0
if(SINE_ENABLE == 1)
{
DacOutput = DacOffset + ((QuadratureTable[iQuadratureTable++] ^ 0x8000) >> 5);
}
else
{
DacOutput = DacOffset;
}
if(iQuadratureTable > (SINE_PTS - 1)) // Wrap the index
{
iQuadratureTable = 0;
}
DacbRegs.DACVALS.all = DacOutput;
} |
Now let's get to the problem:
When I monitor the AdcaResultRegs.ADCRESULT0 register, the values do not change, regardless of connecting ADCAIN0 input to GND or 3V3.
The ADCA interrupt call is working because when I put a breakpoint, the program stops, so I'm assuming SOC and ADC end-of-conversion (ADCA INT) is working for.
I have attached a zip file with the entire project.Lab6.zip
Again, sorry for the English and the size of the post, but this Labs workshop is driving me crazy.
I apreciate any help.