工具与软件:
您好:
我已按计时器验证 ADC 采集时间、结果有点奇怪。
在单次触发模式下、将捕获8个通道、触发器 FIFO 阈值设置为15 (8*2-1)、从 ADC 启动到进入中断的时间约为9us。
但同样、采集1个通道后、触发 FIFO 阈值设置为1 (1*2-1)、从启动 ADC 到进入中断大约需要50us。
我的问题:
1.为什么收集通道较少,但时间延长;
2.根据数据手册、采样频率是4Msps、请帮助我们确认9us 采样时间是否合理;
3、是否有措施加快采样时间。
我的程序如下、计时开始和结束于 hal_adc_trigger ()和 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); }