I have an interesting problem using the ADC peripheral of the C2000 - F28027PTA, I'm using the controlCARD and Docking Station USB EMU. It's my understanding that the DSP2802x Example Code is already written for use on this MCU of the C2000 family, so there shouldn't be any clock or additional register setting changes to use the examples. With that in mind I took the example "Example_2802xAdcSoc" and modified it to use simultaneous sampling on channel pairs A0/B0 and A1/B1. It works just about as expected, results are stored like the ADC Reference guide describes with A0 results in ADCRESULT0, B0 in ADCRESULT1, and so on. The problem I am having is that channel B0 doesn't seem to actually be converting anything. I'm using CCSv4.1.2, so I set a breakpoint in the ADCINT1 ISR, run the program in the CCS debugger with nothing connected to any of the channels and check the values read in ADCRESULT0, ADCRESULT1, ADCRESULT2, and ADCRESULT3.
My Results;
I don't understand why ADCRESULT1 (what should be ADC Channel B0's data) always reads something in the range of 8-20 regardless of if it is grounded or connected to 3.3V (or anything else for that matter). I've included the main of my project below, any help would be appreciated. Is channel B0 possibly fried? Thanks in advance.
#include "DSP28x_Project.h" // Device Headerfile and DSP2802x Examples Include File
// Prototype statements for functions found within this file.
interrupt void adc_isr(void);
void Adc_Config(void);
// Global variables used in this example:
Uint16 LoopCount;
Uint16 ConversionCount;
Uint16 ChannelA0[10];
Uint16 ChannelB0[10];
Uint16 ChannelA1[10];
Uint16 ChannelB1[10];
main()
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
InitSysCtrl();
// Step 2. 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.
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.
InitPieVectTable();
// 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 register
PieVectTable.ADCINT1 = &adc_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 3. Initialize all the Device ADC Peripheral:
InitAdc();
// Step 4. User specific code, enable interrupts:
// Enable ADCINT1 in PIE
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
// Set global variables to keep track of conversions and LoopControl while waiting for ADC Interrupts
LoopCount = 0;
ConversionCount = 0;
// Configure ADC
EALLOW; // This is needed to write to EALLOW protected registers
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // ADCINT1 trips after AdcResults latch
AdcRegs.INTSEL1N2.bit.INT1E = 1; // Enabled ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; // Disable ADCINT1 Continuous mode
AdcRegs.INTSEL1N2.bit.INT1SEL = 3; // setup EOC1 to trigger ADCINT1 to fire
AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1; // Set SOC0/SOC1 to trigger simultaneous sampling
AdcRegs.ADCSAMPLEMODE.bit.SIMULEN2 = 1; // Set SOC2/SOC3 to trigger simultaneous sampling,
AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // Set SOC0 channel select to ADCINA0/ADCINB0
AdcRegs.ADCSOC2CTL.bit.CHSEL = 1; // Set SOC0 channel select to ADCINA0/ADCINB0
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // Set SOC0 start trigger on EPWM1A, due to round-robin SOC0/SOC1 converts first then SOC2/SOC3
AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5; // Set SOC0 start trigger on EPWM1A, due to round-robin SOC0/SOC1 converts first then SOC2/SOC3
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; // Set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; // Set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCSOC2CTL.bit.ACQPS = 6; // Set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCSOC3CTL.bit.ACQPS = 6; // Set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
EDIS; // This is needed to disable write to EALLOW protected registers
// Assumes ePWM1 clock is already enabled in InitSysCtrl();
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC from CPMA on upcount
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm1Regs.CMPA.half.CMPA = 0x0080; // Set compare A value
EPwm1Regs.TBPRD = 0xFFFF; // Set period for ePWM1
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // count up and start
// Wait for ADC interrupt
for(;;)
{
LoopCount++;
}
}
interrupt void adc_isr(void)
{
ChannelA0[ConversionCount] = AdcResult.ADCRESULT0;
ChannelB0[ConversionCount] = AdcResult.ADCRESULT1;
ChannelA1[ConversionCount] = AdcResult.ADCRESULT2;
ChannelB1[ConversionCount] = AdcResult.ADCRESULT3;
if(ConversionCount == 9)
{
ConversionCount = 0;
}
else ConversionCount++;
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
return;
}