Tool/software:
Hello:
I verified the ADC acquisition time by timer, and the result was a little strange.
In one-shot mode, 8 channels are captured, the trigger FIFO threshold is set to 15 (8*2-1), and the time from adc startup to interrupt entry is about 9us.
However, similarly, with the acquisition of 1 channel, the trigger FIFO threshold is set to 1 (1*2-1), and the time from starting adc to entering the interrupt takes about 50us.
My question:
1. Why the collection channel is less, but the time is extended;
2. According to the data manual, the sampling frequency is 4MSPS, please help us to confirm whether the sampling time of 9us is reasonable;
3. Whether there are measures to speed up the sampling time.
My program is as follows,the timing starts and ends at hal_adc_trigger() and App_adcGetData():
uint16_t adc_original_buff[APP_ADC_NUM_CH];
int32_t adc_buff[APP_ADC_NUM_CH];
float curr_result[3];
static HwiP_Object gAdcHwiObject;
HwiP_Params hwiPrms;
volatile uint32_t adc_start_ns = 0;
volatile uint32_t adc_interval_ns = 0;
void App_adcGetData(void)
{
uint32_t voltageLvl;
uint32_t id;
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
uint32_t i = 0;
uint32_t fifoData = 0;
uint32_t fifoWordCnt;
if(is_float_zero(gUserParams_float.adc_gain) == MT_TRUE)
{
gUserParams_float.adc_gain = 0.15f;
}
/* Get FIFO data */
fifoWordCnt = ADCGetFIFOWordCount(baseAddr, ADC_FIFO_NUM_0);
for (i = 0U; i < fifoWordCnt; i++)
{
fifoData = ADCGetFIFOData(baseAddr, ADC_FIFO_NUM_0);
id = ((fifoData & ADC_FIFODATA_ADCCHNLID_MASK) >>
ADC_FIFODATA_ADCCHNLID_SHIFT);
fifoData = ((fifoData & ADC_FIFODATA_ADCDATA_MASK) >>
ADC_FIFODATA_ADCDATA_SHIFT);
adc_original_buff[id] = (uint16_t)fifoData;
if((id > 2) && (id < 6))
{
voltageLvl = fifoData * (uint32_t) (V_ADC_REF * 1000);
voltageLvl /= (uint32_t) ADC_GET_RANGE(CONFIG_ADC0_NUM_BITS);
if(Old_m_state == MC_STATE_CALIBRATION)
{
//1650 = 3.3V * 1000 / 2
adc_buff[id] = voltageLvl - 1650;
}
else
{
adc_buff[id] = voltageLvl - 1650 - hal_hwParams_u32_t.PhaseCurrOffset[id - 3];
}
curr_result[id - 3] = (adc_buff[id] * 1.0f / 1000.0f) / gUserParams_float.adc_gain;
}
else
{
adc_buff[id] = fifoData;
}
}
adc_interval_ns = clock_cal_interval(adc_start_ns, clock_get_ns());
}
void App_adcISR(void *handle)
{
uint32_t status;
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
/* Get interrupt status and clear */
status = ADCGetIntrStatus(baseAddr);
ADCClearIntrStatus(baseAddr, status);
App_adcGetData();
/* Set EOI to generate next interrupt if any */
ADCWriteEOI(baseAddr);
}
void App_adcConfig(uint32_t baseAddr)
{
adcStepConfig_t adcConfig;
uint32_t chCnt, adcStep;
/* Enable interrupts */
ADCEnableIntr(baseAddr, ADC_INTR_SRC_FIFO0_THRESHOLD);
/*
* Configure all ADC Steps
*/
/* Initialize ADC configuration params */
adcConfig.mode = ADC_OPERATION_MODE_SINGLE_SHOT;
adcConfig.openDelay = 0x0U;
adcConfig.sampleDelay = 0U;
adcConfig.rangeCheckEnable = 0U;
adcConfig.averaging = ADC_AVERAGING_NONE;
adcConfig.fifoNum = ADC_FIFO_NUM_0;
/* Configure all required steps - Step 1 to N mapped to Channel 1 to N */
for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
{
adcConfig.channel = ADC_CHANNEL_1 + chCnt;
adcStep = ADC_STEP_1 + chCnt; /* Step -> Channel one to one mapped */
ADCSetStepParams(baseAddr, adcStep, &adcConfig);
}
ADCStepIdTagEnable(baseAddr, TRUE);
ADCSetCPUFIFOThresholdLevel(baseAddr, ADC_FIFO_NUM_0, APP_ADC_NUM_CH * 2);
/* Step enable */
for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
{
adcStep = ADC_STEP_1 + chCnt; /* Step -> Channel one to one mapped */
ADCStepEnable(baseAddr, adcStep, TRUE);
}
}
static void App_adcInit(uint32_t baseAddr)
{
/* Clear All interrupt status */
ADCClearIntrStatus(baseAddr, ADC_INTR_STATUS_ALL);
/* Register & enable interrupt */
HwiP_Params_init(&hwiPrms);
hwiPrms.intNum = CONFIG_ADC0_INTR;
hwiPrms.callback = &App_adcISR;
hwiPrms.priority = 1U;
HwiP_construct(&gAdcHwiObject, &hwiPrms);
/* Power up AFE */
ADCPowerUp(baseAddr, TRUE);
/* Wait for 4us at least */
ClockP_usleep(5U);
/* Do the internal calibration */
ADCInit(baseAddr, FALSE, 0U, 0U);
}
static void App_adcStart(uint32_t baseAddr)
{
adcSequencerStatus_t status;
/* Check if FSM is idle */
ADCGetSequencerStatus(baseAddr, &status);
while ((ADC_ADCSTAT_FSM_BUSY_IDLE != status.fsmBusy) &&
ADC_ADCSTAT_STEP_ID_IDLE != status.stepId)
{
ADCGetSequencerStatus(baseAddr, &status);
}
/* Start ADC conversion */
ADCStart(baseAddr, TRUE);
}
int32_t hal_adc_init(void)
{
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
App_adcInit(baseAddr);
App_adcConfig(baseAddr);
/* Set EOI to generate next interrupt if any */
ADCWriteEOI(baseAddr);
App_adcStart(baseAddr);
return MT_OK;
}
void hal_adc_trigger(void)
{
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
uint32_t chCnt, adcStep;
/* Step enable */
for(chCnt = 0U; chCnt < APP_ADC_NUM_CH; chCnt++)
{
adcStep = ADC_STEP_1 + chCnt; /* Step -> Channel one to one mapped */
ADCStepEnable(baseAddr, adcStep, TRUE);
}
adc_start_ns = clock_get_ns();
App_adcStart(baseAddr);
}