F446RE ADC with DMA hack (need pin to ADC channel) 1000 samples, for loop adc.read_u16() rate is 2.2us/sample for DMA block read, rate is 0.34us/sample
F446RE ADC with DMA for 1000 samples. (a hack for now, need to get ADC channel from pin name, for asynch operation would need callback)
For 1000 samples with loop adc.read_u16(), sample rate is 2.2us/sample
For DMA, 0.34us/sample.
This matches expected rate: ADC clock at 45MHz, ADC configured for 3CYCLES/sample, cycles = 12+3, rate = 15/45 =0.33us/sample
main.cpp
- Committer:
- manitou
- Date:
- 2015-11-13
- Revision:
- 0:b0470b4e6b60
File content as of revision 0:b0470b4e6b60:
// F446RE ADC with DMA // ADC read shifted to 16 bits, our readn is only 12 bits // messy, TODO need ADC channel from pin number #include "mbed.h" #define PRREG(z) printf(#z" 0x%x\n",z) AnalogIn adc(A1); // init GPIO stuff Timer tmr; static ADC_HandleTypeDef AdcHandle; void adc_init() { // we assume AnalogIn has configureed GPIO, we need ADC channel ? __ADC1_CLK_ENABLE(); // Enable ADC clock // Configure ADC AdcHandle.Instance = (ADC_TypeDef *)ADC1; AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; AdcHandle.Init.Resolution = ADC_RESOLUTION12b; AdcHandle.Init.ScanConvMode = DISABLE; AdcHandle.Init.ContinuousConvMode = ENABLE; // DMA AdcHandle.Init.DiscontinuousConvMode = DISABLE; AdcHandle.Init.NbrOfDiscConversion = 0; AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT; AdcHandle.Init.NbrOfConversion = 1; AdcHandle.Init.DMAContinuousRequests = ENABLE; // DMA AdcHandle.Init.EOCSelection = DISABLE; HAL_ADC_Init(&AdcHandle); } static DMA_HandleTypeDef DMA_Handle; void dma_init() { // DMA init ADC1 is DMA2 channel0 stream 0 or 4 use DMA2_Stream0 thd __DMA2_CLK_ENABLE(); DMA_Handle.Instance = DMA2_Stream0; DMA_Handle.State = HAL_DMA_STATE_READY; HAL_DMA_DeInit(&DMA_Handle); DMA_Handle.Init.Channel = DMA_CHANNEL_0; DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY; DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE; DMA_Handle.Init.MemInc = DMA_MINC_ENABLE; DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; DMA_Handle.Init.Mode = DMA_NORMAL; DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH; DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE; DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE; HAL_DMA_Init(&DMA_Handle); __HAL_LINKDMA(&AdcHandle, DMA_Handle, DMA_Handle); } void adc_readn( uint16_t * data, uint32_t nelems) { ADC_ChannelConfTypeDef sConfig; sConfig.Channel = ADC_CHANNEL_1; // A1 need to derive sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; sConfig.Offset = 0; HAL_ADC_ConfigChannel(&AdcHandle, &sConfig); HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)data, nelems); while (DMA_Handle.Instance->CR & DMA_SxCR_EN); // spin HAL_ADC_Stop(&AdcHandle); } #define SAMPLES 1000 int main() { uint16_t samples[SAMPLES]; uint32_t t1; int i; printf("\nSystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__); tmr.start(); memset(samples,0,sizeof samples); t1=tmr.read_us(); for(i=0;i<SAMPLES;i++) samples[i] = adc.read_u16(); t1=tmr.read_us() - t1; printf("loop sample time %.1f us %d elapsed %d us\n", (float)t1 / SAMPLES,samples[5],t1); adc_init(); dma_init(); memset(samples,77,sizeof samples); t1=tmr.read_us(); adc_readn(samples,SAMPLES); t1=tmr.read_us() - t1; printf("DMA sample time %.2f us %d elapsed %d us\n", (float)t1 / SAMPLES,samples[5],t1); }