Hi,
with the F28335 Experimenter’s Kit I tried to sampling 16signals with the built-in ADC module in the quickest way. I programmed the ADC in simultaneous sampling mode using the ePWM1A to drive the ADC SOC signal.
To measure the timing I rise a GPIO at the start of the interrupt adc_isr.
The result is that between the center PWM of the ePWM1A and the start of the interrupt adc_isr there is 1,66uS.
1) It is not too high ? From the datasheet I think that it must be about td+tsh+tdschB0_0+ tdschB0_n1*7=100+40+200+120*7=1180nS.
2) I rise a GPIO drive from a the epwm1_isr programmed to start when the counter equal to period and I found a delay from the center PWM of the ePWM1A of 290nS, is this correct ?
3) I use another interrupt link to timer0 but when it start near the adc_isr it block the start of the adc_isr. What can I do ?
Thanks in advance for all your support.
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "IQmathLib.h"
#include <stdio.h>
_iq angolo;
_iq sinOut;
// Prototype statements for functions found within this file.
void InitEPwm1Example(void);
interrupt void epwm1_isr(void);
//void update_compare(EPWM_INFO*);
void updateCompare(void);
//interrupt void epwm1_tzint_isr(void);
interrupt void adc_isr(void);
interrupt void cpu_timer0_isr(void);
// Configure the period for each timer
#define EPWM1_TIMER_TBPRD 20000 // Period register
//#define EPWM1_MAX_CMPA 1950
#define EPWM1_MIN_CMPA 50
#define EPWM1_MAX_CMPB 1950
#define EPWM1_MIN_CMPB 50
// To keep track of which way the compare value is moving
#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
// Maximum Dead Band values
#define EPWM1_DB 100
#define PUNTIACQ 100
// Global variables used in this example:
Uint16 LoopCount;
Uint16 ConversionCount;
Uint16 Voltage1[PUNTIACQ];
Uint16 Voltage2[PUNTIACQ];
Uint16 Voltage3[PUNTIACQ];
Uint16 Voltage4[PUNTIACQ];
Uint16 Voltage5[PUNTIACQ];
Uint16 Voltage6[PUNTIACQ];
Uint16 Voltage7[PUNTIACQ];
Uint16 Voltage8[PUNTIACQ];
Uint16 Voltage9[PUNTIACQ];
Uint16 Voltage10[PUNTIACQ];
Uint16 Voltage11[PUNTIACQ];
Uint16 Voltage12[PUNTIACQ];
Uint16 Voltage13[PUNTIACQ];
Uint16 Voltage14[PUNTIACQ];
Uint16 Voltage15[PUNTIACQ];
Uint16 Voltage16[PUNTIACQ];
// These are defined by the linker (see F28335.cmd)
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsRunStart;
float y1, y2;
float m1, m2;
float x1, x2;
float b1, b2;
int32 yInt32;
int32 mInt32;
int32 xInt32;
int32 bInt32;
void main(void)
{
extern void DSP28x_usDelay(Uint32 Count);
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
InitSysCtrl();
// Default - 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
// Define ADCCLK clock frequency ( less than or equal to 25 MHz )
// Assuming InitSysCtrl() has set SYSCLKOUT to 150 MHz
EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK;
EDIS;
// Step 2. Initalize GPIO:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example
InitEPwm1Gpio();
// 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 DSP2833x_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 DSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.
InitPieVectTable();
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
InitFlash(); // The flash initialization routine should be executed from RAM.
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TINT0 = &cpu_timer0_isr;
PieVectTable.EPWM1_INT = &epwm1_isr;
PieVectTable.ADCINT = &adc_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize the Device Peripheral. This function can be
// found in DSP2833x_CpuTimers.c
InitCpuTimers(); // For this example, only initialize the Cpu Timers
// Configure CPU-Timer 0 to interrupt every 500 milliseconds:
// 150MHz CPU Freq, 50 millisecond Period (in uSeconds)
// ConfigCpuTimer(&CpuTimer0, 150, 500000);
ConfigCpuTimer(&CpuTimer0, 150, 100); // 0.1uS
// To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any
// of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2833x_CpuTimers.h), the
// below settings must also be updated.
CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0
InitAdc(); // For this example, init the ADC
// Step 5. User specific code, enable interrupts:
// Configure GPIO32 as a GPIO output pin
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO31 = 1;
GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO30 = 1;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
InitEPwm1Example();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// Enable CPU INT3 which is connected to EPWM1-3 INT:
IER |= M_INT2;
// Enable TINT0 in the PIE: Group 1 interrupt 7
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// Enable EPWM INTn in the PIE: Group 2 interrupt 1-3
PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
PieCtrlRegs.PIEIER2.bit.INTx2 = 1;
// Enable CPU INT3 which is connected to EPWM1-3 INT:
IER |= M_INT3;
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
// Enable ADCINT in PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1;
IER |= M_INT1; // Enable CPU Interrupt 1
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
angolo=0;
sinOut=0;
LoopCount = 0;
ConversionCount = 0;
// Configure ADC
// Simultaneous Sampling Dual Sequencer Mode Example
AdcRegs.ADCREFSEL.bit.REF_SEL = 0;
AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3; /* bit7-6(11): ADCBGRFDN, reference power, 00=off, 11=on */
AdcRegs.ADCTRL3.bit.ADCPWDN = 0x1; /* bit5(1): ADCPWDN, main ADC power, 0=off, 1=on */
AdcRegs.ADCTRL3.bit.ADCCLKPS = 0x0;/* bit4-1(0100): ADCCLKPS, clock prescaler, ADCLK=HSPCLK/[(2*ADCCLKPS)*(ADCTRL1[7] + 1)] */
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0x1; /* bit0(1): SMODE_SEL, 0=sequential sampling, 1=simultaneous sampling */
DSP28x_usDelay(5000); /* Wait 5ms before using the ADC */
AdcRegs.ADCMAXCONV.all = 0x0007; /* 8 double conv's (16 total) */
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; /* Setup conv from ADCINA0 and ADCINB0 */
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; /* Setup conv from ADCINA1 and ADCINB1 */
AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 0x2; /* Setup conv from ADCINA2 and ADCINB2 */
AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 0x3; /* Setup conv from ADCINA3 and ADCINB3 */
AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 0x4; /* Setup conv from ADCINA4 and ADCINB4 */
AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 0x5; /* Setup conv from ADCINA5 and ADCINB5 */
AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 0x6; /* Setup conv from ADCINA6 and ADCINB6 */
AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 0x7; /* Setup conv from ADCINA7 and ADCINB7 */
AdcRegs.ADCTRL1.bit.RESET = 0x0; /* bit14(0): RESET, 0=no action, 1=reset ADC */
AdcRegs.ADCTRL1.bit.SUSMOD = 0x00; /* bit13-12(00): emulation suspend is ignored */
AdcRegs.ADCTRL1.bit.ACQ_PS = 0x00; // 0x07; /* bit11-8(0111): ACQ_PS (Acquisition), 0100 = 5 x ADCCLK */
AdcRegs.ADCTRL1.bit.CPS = 0x0; /* bit7(0): CPS (Core clock), 0: ADCCLK=FCLK/1, 1: ADCCLK=FCLK/2 */
AdcRegs.ADCTRL1.bit.CONT_RUN = 0x0; /* bit6(0): CONT_RUN, 0=start/stop mode, 1=continuous run */
AdcRegs.ADCTRL1.bit.SEQ_OVRD = 0x0; /* bit5(0): SEQ_OVRD, 0=disabled, 1=enabled */
AdcRegs.ADCTRL1.bit.SEQ_CASC = 0x1; //0x1; /* bit4(1): SEQ_CASC, 0=dual sequencer, 1=cascaded sequencer */
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;// Enable SOCA from ePWM to start SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Enable SEQ1 interrupt (every EOS)
// Assumes ePWM1 clock is already enabled in InitSysCtrl();
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 2; //Enable event time-base counter equal to period (TBCTR = TBPRD)
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
y1 = 0;
y2 = 0;
m1 = .5;
m2 = .6;
x1 = 3.4;
x2 = 7.3;
b1 = 4.2;
b2 = 8.9;
yInt32 = 0;
mInt32 = 100;
xInt32 = 200;
bInt32 = 50;
printf(" hello world!\n");
// Step 6. IDLE loop. Just sit and loop forever (optional):
for(;;)
{
y1 = m1*x1 + b1; //160nS
yInt32 = mInt32 * xInt32 + bInt32;
}
}
interrupt void adc_isr(void)
{
GpioDataRegs.GPACLEAR.bit.GPIO31 = 1;
Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4;
Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;
Voltage3[ConversionCount] = AdcRegs.ADCRESULT2 >>4;
Voltage4[ConversionCount] = AdcRegs.ADCRESULT3 >>4;
Voltage5[ConversionCount] = AdcRegs.ADCRESULT4 >>4;
Voltage6[ConversionCount] = AdcRegs.ADCRESULT5 >>4;
Voltage7[ConversionCount] = AdcRegs.ADCRESULT6 >>4;
Voltage8[ConversionCount] = AdcRegs.ADCRESULT7 >>4;
Voltage9[ConversionCount] = AdcRegs.ADCRESULT8 >>4;
Voltage10[ConversionCount] = AdcRegs.ADCRESULT9 >>4;
Voltage11[ConversionCount] = AdcRegs.ADCRESULT10 >>4;
Voltage12[ConversionCount] = AdcRegs.ADCRESULT11 >>4;
Voltage13[ConversionCount] = AdcRegs.ADCRESULT12 >>4;
Voltage14[ConversionCount] = AdcRegs.ADCRESULT13 >>4;
Voltage15[ConversionCount] = AdcRegs.ADCRESULT14 >>4; // ADCINA7 -> ADCRESULT14
Voltage16[ConversionCount] = AdcRegs.ADCRESULT15 >>4;
if(ConversionCount == 99)
ConversionCount = 0;
else
ConversionCount++;
updateCompare();
// Reinitialize for next ADC sequence
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1
AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
return;
}
interrupt void cpu_timer0_isr(void)
{
// 0.1uS
GpioDataRegs.GPASET.bit.GPIO30 = 1;
sinOut= _IQ15sin(_IQ15(angolo*2*3.14/200));
sinOut = _IQ15mpy(sinOut ,EPWM1_TIMER_TBPRD/2);
if (angolo <=200 )
angolo++;
else
angolo=0;
GpioDataRegs.GPACLEAR.bit.GPIO30 = 1;
// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
interrupt void epwm1_isr(void)
{
GpioDataRegs.GPASET.bit.GPIO31 = 1;
// Clear INT flag for this timer
EPwm1Regs.ETCLR.bit.INT = 1;
// Acknowledge this interrupt to receive more interrupts from group 3
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
void InitEPwm1Example()
{
// Setup TBCLK
EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD; // Set timer period 801 TBCLKs
EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
EPwm1Regs.TBCTR = 0x0000; // Clear counter
// Set Compare values
EPwm1Regs.CMPA.half.CMPA = EPWM1_MIN_CMPA; // Set compare A value
EPwm1Regs.CMPB = EPWM1_MAX_CMPB; // Set Compare B value
// Setup counter mode
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
// Setup shadowing
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
// Set actions
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up count
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A, down count
EPwm1Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up count
EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR; // Clear PWM1B on event B, down count
// Interrupt where we will change the Compare Values
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_PRD;
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD =1;
}
void updateCompare(void)
{
EPwm1Regs.CMPA.half.CMPA= EPWM1_TIMER_TBPRD/2 + sinOut;
EPwm1Regs.CMPB= EPWM1_TIMER_TBPRD/2 - sinOut;
}