Hi Folks,
I am attempting to calibrate the ADC OFFTRIM value on an F28027. I have an older project that uses the struct support files, the example DevInit() and example AdcOffsetSelfCal(), that appears to work as intended.
I have recreated the DevInit() and AdcOffsetSelfCal() in my main() initialization section of my new project, this time using the driver support files. The code is as below.
Currently my issue is as follows. When attempting the ping-pong sampling initially the first conversion SOC is forced, by writing 0x00FF to the ADCSOCFRC1 register, subsequent conversion SOCs should then be triggered by the ADCINT1 & 2 that occur at the end of the conversion. However, the flags for these ADCINTs never seem to be raised, meaning that after the first set of (forced) conversions the program gets stuck waiting for the flags to be raised (ln#:165)...
I have checked all the values set in the registers and the appear correct and matching to the values in my older, working, project. So I have a feeling I must be missing something silly somewhere, but i cant for the life of me see what it might be.
Note that I have also started this project from scratch instead of altering an example project as I did for my previous projects, so there may possibly be some issue there, but I couldn't think of anything in this regard that would affect the ADCs in this way.
the code is below, I'd appreciate if anyone could let me know if they can spot anything incorrect or if you suffer see a similar problem with this code. Many thanks.
#include "DSP28x_Project.h" #include <clk.h> #include <flash.h> #include <gpio.h> #include <pie.h> #include <pll.h> #include <pie.h> #include <wdog.h> #include <adc.h> #include <DPlib.h> #define ADC_usDELAY 1000L #define ADC_ADCCTL1_VREFLOCONV_BIT 1 #define ADC_OFFTRIM_CAL_SAMPLE_SIZE 256 /* NB: Sample size must be multiples of 2^x where is an integer >= 4). */ extern uint16_t RamfuncsLoadEnd; volatile struct EPWM_REGS *ePWM[] = /* This is declared extern by DPLib.h.*/ { &EPwm1Regs, /* Intentional: (ePWM[0] not used). */ &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, #if (!DSP2802x_DEVICE_H) &EPwm5Regs, &EPwm6Regs, #if (DSP2803x_DEVICE_H || DSP2804x_DEVICE_H) &EPwm7Regs, #if (DSP2804x_DEVICE_H) &EPwm8Regs #endif #endif #endif }; extern void ADC_SOC_CNF(int ChSel[], int Trigsel[], int ACQPS[], int IntChSel, int mode); extern void PWM_1ch_CNF(int16 n, Uint16 period, int16 mode, int16 phase); // This function configures the A channel of a ePWM with the settings specified by the arguments. // uint16_t pwm Target ePWM module, 1,2,...16. e.g. if n=2, then target is ePWM2. // uint16_t f_pwm PWM frequency in kHz. // bool_t master Master mode selector. // uint16_t phase Phase angle from upstream master in degrees, applicable only if master=false, i.e. slave. void confgiure_dpl_pwm (uint16_t pwm, double f_pwm, bool_t master, uint16_t phase) { /* frequency parameter is in kHz, phase parameter is in degrees. */ uint16_t t_pwm = (uint16_t)((1/f_pwm) * 1000.0) + 0.5; t_pwm = ((t_pwm/CPU_RATE) * 1000.0) + 0.5; uint16_t t_phi = ((t_pwm/360.0) * phase) + 0.5; PWM_1ch_CNF(pwm, t_pwm, (master?1:0), t_phi); } void MemCopy(uint16_t * SourceAddr, uint16_t * SourceEndAddr, uint16_t * DestAddr) { while(SourceAddr < SourceEndAddr) { *DestAddr++ = *SourceAddr++; } return; } void main(void) { /* Initialize all the system handles needed for this application. */ CPU_Handle cpu = CPU_init((void *)NULL, sizeof(CPU_Obj)); WDOG_Handle wdog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj)); WDOG_disable(wdog); /* Disable the watchdog. */ CPU_disableGlobalInts(cpu); /* DINT (INTM = 1). */ CPU_disableInts(cpu); /* Clear CPU IER register. */ CPU_clearIntFlags(cpu); /* Clear CPU IFR register. */ #ifdef FLASH FLASH_Handle flash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj)); #endif CLK_Handle clk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj)); PLL_Handle pll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj)); PIE_Handle pie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj)); GPIO_Handle gpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj)); ADC_Handle adc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj)); /*=========================== DEVICE INITIALISATION ===========================*/ CLK_enableAdcClock(clk); /* Clock to ADC needs to be enabled for Device_cal(). */ (*Device_cal)(); /* Calibrate the internal oscillators and ADC. */ CLK_disableAdcClock(clk); CLK_enableOsc1(clk); /* Enable internal oscillator 1. */ CLK_setOscSrc(clk, CLK_OscSrc_Internal); /* Select the internal oscillator 1 as the clock source. */ CLK_disableClkIn(clk); /* Disable the external clock input. */ CLK_disableCrystalOsc(clk); /* Disable the crystal oscillator. */ CLK_disableOsc2(clk); /* Disable the internal oscillator 2. */ PLL_setup(pll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2); /* Setup the PLL for x12 /2 which will yield 60Mhz = 10Mhz * 12 / 2. */ PIE_disable(pie); /* Clear the PIE CTRL enable bit. */ PIE_disableAllInts(pie); /* Clear all PIE IER registers to all 0. */ PIE_clearAllFlags(pie); /* Clear all PIE IFR registers to 0. */ PIE_setDefaultIntVectorTable(pie); /* Initializes the vector table with illegal ISR handlers. */ PIE_enable(pie); /* Set the PIE CTRL enable bit. */ CLK_setLowSpdPreScaler(clk, CLK_LowSpdPreScaler_SysClkOut_by_2);/* Setup the low-speed clock for SYSCLKOUT/(LOSPCP * 2) which will yield 15Mhz = 60Mhz / 4. */ CLK_setClkOutPreScaler(clk, CLK_ClkOutPreScaler_SysClkOut_by_2);/* Setup the clock external output for /2, yielding 60MHz = 60MHz / 2. */ CLK_enableI2cClock(clk); /* Enable clock to I2C. */ CLK_enableGpioInputClock(clk); /* Enable clock to GPIO inputs. */ CLK_disableCompClock(clk, CLK_CompNumber_1);/* Disable clock to comparator 1. */ CLK_disableCompClock(clk, CLK_CompNumber_2);/* Disable clock to comparator 2. */ CLK_disableSciaClock(clk); /* Disable clock to SCI-A. */ CLK_disableSpiaClock(clk); /* Disable clock to SPI-A. */ CLK_disableEcap1Clock(clk); /* Disable clock to eCAP1. */ #ifdef FLASH MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); /* Copy time critical code and Flash setup code to RAM. */ FLASH_setup(flash); /* Call the flash wrapper init function. */ #endif /*=============================== CONFIGURE ADC ===============================*/ GPIO_Obj * gpioObj = (GPIO_Obj *)gpio; ENABLE_PROTECTED_REGISTER_WRITE_MODE; gpioObj->AIOMUX1 = 0x22202220; /* Disables AIOIN lines, ADC & CMP only used. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; CLK_enableAdcClock(clk); /* Enable clock to ADC. */ ADC_enableBandGap(adc); /* Power up ADC and references. */ ADC_enableRefBuffers(adc); ADC_powerUp(adc); ADC_enable(adc); ADC_setVoltRefSrc(adc, ADC_VoltageRefSrc_Int); DELAY_US(ADC_usDELAY); /* Wait for power up to complete. */ uint16_t adcConvMean; ADC_Obj * adcObj = (ADC_Obj *)adc; ADC_SocNumber_e soc = ADC_SocNumber_0; ENABLE_PROTECTED_REGISTER_WRITE_MODE; /* Setup for OFFTRIM calibration. */ adcObj->ADCCTL1 |= (1 << ADC_ADCCTL1_VREFLOCONV_BIT); /* Connect B5 to VREFLO instead of the ADCINB5 pin. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; for (; soc <= ADC_SocNumber_15; ++soc) /* Select channel B5 for all SOC. */ ADC_setSocChanNumber(adc, (ADC_SocNumber_e)soc, ADC_SocChanNumber_B5); ENABLE_PROTECTED_REGISTER_WRITE_MODE; adcObj->ADCOFFTRIM = 80; /* Apply artificial offset (+80) to account for a negative offset that may reside in the ADC core. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; for (soc = ADC_SocNumber_0; soc <= ADC_SocNumber_15; ++soc) ADC_setSocSampleWindow(adc, soc, ADC_SocSampleWindow_7_cycles); ADC_enableInt(adc, ADC_IntNumber_1); /* Setup for ping-pong sampling. */ ADC_enableInt(adc, ADC_IntNumber_2); ADC_setIntMode(adc, ADC_IntNumber_1, ADC_IntMode_ClearFlag); ADC_setIntMode(adc, ADC_IntNumber_2, ADC_IntMode_ClearFlag); ADC_setIntPulseGenMode(adc, ADC_IntPulseGenMode_Prior); ADC_setIntSrc(adc, ADC_IntNumber_1, ADC_IntSrc_EOC6); ADC_setIntSrc(adc, ADC_IntNumber_2, ADC_IntSrc_EOC14); ENABLE_PROTECTED_REGISTER_WRITE_MODE; adcObj->ADCINTSOCSEL1 = 0xAAAA; /* Set ADCINT1 to start SOC8-15. */ adcObj->ADCINTSOCSEL2 = 0x5555; /* Set ADCINT2 to start SOC0-7. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; DELAY_US(ADC_usDELAY); ENABLE_PROTECTED_REGISTER_WRITE_MODE; adcObj->ADCSOCFRC1 = 0x00FF; /* Force start SOC0-7 to begin ping-pong sampling. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; uint16_t i = 0; uint32_t sum = 0; /* Take samples. */ for (; i < ADC_OFFTRIM_CAL_SAMPLE_SIZE; i += 16) { ADC_ResultNumber_e result = ADC_ResultNumber_0; while (!ADC_getIntStatus(adc, ADC_IntNumber_1)) {} // GETS STUCK HERE ON SECOND ITERATION ADC_clearIntFlag(adc, ADC_IntNumber_1); for (; result <= ADC_ResultNumber_7; ++result) sum += ADC_readResult(adc, result); while (!ADC_getIntStatus(adc, ADC_IntNumber_2)) {} ADC_clearIntFlag(adc, ADC_IntNumber_2); for (result = ADC_ResultNumber_8; result <= ADC_ResultNumber_15; ++result) sum += ADC_readResult(adc, result); } ADC_disableInt(adc, ADC_IntNumber_1); /* Stop the ping-pong sampling. */ ADC_disableInt(adc, ADC_IntNumber_2); adcConvMean = sum / ADC_OFFTRIM_CAL_SAMPLE_SIZE; /* Average the sample data. */ ENABLE_PROTECTED_REGISTER_WRITE_MODE; adcObj->ADCOFFTRIM = 80 - adcConvMean; /* Set offtrim register with new value (i.e remove artical offset (+80) and create a two's compliment of the offset error). */ adcObj->ADCCTL1 &= ~(1 << ADC_ADCCTL1_VREFLOCONV_BIT); /* Connect B5 to back to the ADCINB5 pin. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; int chsel[16] = {0, 0x1, 0x9, 0x2, 0}; /* A0 Unused (SOC0 Errata), A1, B1, A2, all others unused */ int trigsel[16] = {5, 5, 5, 5, 0}; int acqps[16] = {0, 6, 6, 6, 0}; ADC_SOC_CNF(chsel, trigsel, acqps, 16, 0); for (;;) {} /* Super loop. */ }