Part Number: TMS320F28027
Hi
I have copied the adcOffsetSelfCal() and its dependent functions from the piccolo example files. I have converted the code to use the driver type HAL instead of the structs and use the code to take a ping-pong sampling of a single pin. This is called directly after the device setup, which includes ADC initialisation and calibration.
There is one problem however; at the lines at which the code waits in an empty while loop for the ADCINTFLG register's ADCINT1 and INT2 bits to be cleared to indicate that the related interrupts has been triggered. It seems that the bits in question are never cleared (i.e. execution sits in the while loop forever), at least as far as the compiled code is concerned.
In the original example these lines are coded as:
//Wait for ADCINT1 to trigger, then add ADCRESULT0-7 registers to sum
while (AdcRegs.ADCINTFLG.bit.ADCINT1 == 0){}
and:
//Wait for ADCINT2 to trigger, then add ADCRESULT8-15 registers to sum
while (AdcRegs.ADCINTFLG.bit.ADCINT2 == 0){}
In my converted code, the full function is as follows:
uint_least8_t getValueFromPingPong (void)
{ uint16_t address = 0U, i = 0U; ADC_Handle adcHandle = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj)); ADC_Obj * adc = (ADC_Obj *)adcHandle; ADC_SocNumber_e soc = ADC_SocNumber_0; for (; soc <= ADC_SocNumber_15; ++soc) { /* Select channel for all SOC. */ ADC_setSocChanNumber(adcHandle, soc, SENSE_ADC_CHANNEL); } /* Select sample window size for all SOC. */ for (soc = ADC_SocNumber_0; soc <= ADC_SocNumber_15; ++soc) { ADC_setSocSampleWindow(adcHandle, soc, ADC_SocSampleWindow_7_cycles); } /* Setup for ping-pong sampling. */ ADC_enableInt(adcHandle, ADC_IntNumber_1); ADC_enableInt(adcHandle, ADC_IntNumber_2); ADC_setIntMode(adcHandle, ADC_IntNumber_1, ADC_IntMode_ClearFlag); ADC_setIntMode(adcHandle, ADC_IntNumber_2, ADC_IntMode_ClearFlag); ADC_setIntPulseGenMode(adcHandle, ADC_IntPulseGenMode_Prior); ADC_setIntSrc(adcHandle, ADC_IntNumber_1, ADC_IntSrc_EOC6); ADC_setIntSrc(adcHandle, ADC_IntNumber_2, ADC_IntSrc_EOC14); ENABLE_PROTECTED_REGISTER_WRITE_MODE; adc->ADCINTSOCSEL1 = 0xAAAAU; /* Set ADCINT1 to start SOC8-15. */ adc->ADCINTSOCSEL2 = 0x5555U; /* Set ADCINT2 to start SOC0-7. */ DISABLE_PROTECTED_REGISTER_WRITE_MODE; DELAY_US(ADC_usDELAY); adc->ADCSOCFRC1 = 0x00FFU; /* Force start SOC0-7 to begin ping-pong sampling. */ uint32_t sum = 0U; /* Take samples. */ for (i = 0U; i < SENSE_SAMPLE_SIZE; i += 16U) { while((adc->ADCINTFLG & 0x01U) == 0U) {} // This condition is only ever true on the first iteration thru the for loop adc->ADCINTFLGCLR = 0x01U; sum += adc->ADCRESULT[0]; sum += adc->ADCRESULT[1]; sum += adc->ADCRESULT[2]; sum += adc->ADCRESULT[3]; sum += adc->ADCRESULT[4]; sum += adc->ADCRESULT[5]; sum += adc->ADCRESULT[6]; /* Wait for SOC9 conversion to start, which gives time for SOC7 * conversion result. */ while(adc->ADCSOCFLG1 & 0x200U) {} sum += adc->ADCRESULT[7]; while((adc->ADCINTFLG & 0x02U) == 0U) {} // This condition is never seems to be true adc->ADCINTFLGCLR = 0x02U; sum += adc->ADCRESULT[8]; sum += adc->ADCRESULT[9]; sum += adc->ADCRESULT[10]; sum += adc->ADCRESULT[11]; sum += adc->ADCRESULT[12]; sum += adc->ADCRESULT[13]; sum += adc->ADCRESULT[14]; /* Wait for SOC1 conversion to start, which gives time for SOC15 * conversion result. */ while(adc->ADCSOCFLG1 & 0x02U) {} sum += adc->ADCRESULT[15]; } ADC_disableInt(adcHandle, ADC_IntNumber_1); /* Stop the ping-pong sampling. */ ADC_disableInt(adcHandle, ADC_IntNumber_2); /* Average the sample data. */ uint16_t adcConvMean = (uint16_t)(sum / SENSE_SAMPLE_SIZE); return adcConvMean; }
Why does this happen and what can I do to fix it?
Realised that my adcOffsetSelfCal() function is called immediately before this and uses code that is very similar, yet it works. The main difference being that the SelfCal function uses ADC B5, with B5 connected to the VREFLO.
Thanks, T