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@0:b0470b4e6b60, 2015-11-13 (annotated)
- Committer:
- manitou
- Date:
- Fri Nov 13 13:20:03 2015 +0000
- Revision:
- 0:b0470b4e6b60
F446RE ADC with DMA, hack
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
manitou | 0:b0470b4e6b60 | 1 | // F446RE ADC with DMA |
manitou | 0:b0470b4e6b60 | 2 | // ADC read shifted to 16 bits, our readn is only 12 bits |
manitou | 0:b0470b4e6b60 | 3 | // messy, TODO need ADC channel from pin number |
manitou | 0:b0470b4e6b60 | 4 | |
manitou | 0:b0470b4e6b60 | 5 | #include "mbed.h" |
manitou | 0:b0470b4e6b60 | 6 | |
manitou | 0:b0470b4e6b60 | 7 | #define PRREG(z) printf(#z" 0x%x\n",z) |
manitou | 0:b0470b4e6b60 | 8 | |
manitou | 0:b0470b4e6b60 | 9 | AnalogIn adc(A1); // init GPIO stuff |
manitou | 0:b0470b4e6b60 | 10 | Timer tmr; |
manitou | 0:b0470b4e6b60 | 11 | |
manitou | 0:b0470b4e6b60 | 12 | |
manitou | 0:b0470b4e6b60 | 13 | static ADC_HandleTypeDef AdcHandle; |
manitou | 0:b0470b4e6b60 | 14 | |
manitou | 0:b0470b4e6b60 | 15 | void adc_init() { |
manitou | 0:b0470b4e6b60 | 16 | // we assume AnalogIn has configureed GPIO, we need ADC channel ? |
manitou | 0:b0470b4e6b60 | 17 | __ADC1_CLK_ENABLE(); // Enable ADC clock |
manitou | 0:b0470b4e6b60 | 18 | |
manitou | 0:b0470b4e6b60 | 19 | // Configure ADC |
manitou | 0:b0470b4e6b60 | 20 | AdcHandle.Instance = (ADC_TypeDef *)ADC1; |
manitou | 0:b0470b4e6b60 | 21 | AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; |
manitou | 0:b0470b4e6b60 | 22 | AdcHandle.Init.Resolution = ADC_RESOLUTION12b; |
manitou | 0:b0470b4e6b60 | 23 | AdcHandle.Init.ScanConvMode = DISABLE; |
manitou | 0:b0470b4e6b60 | 24 | AdcHandle.Init.ContinuousConvMode = ENABLE; // DMA |
manitou | 0:b0470b4e6b60 | 25 | AdcHandle.Init.DiscontinuousConvMode = DISABLE; |
manitou | 0:b0470b4e6b60 | 26 | AdcHandle.Init.NbrOfDiscConversion = 0; |
manitou | 0:b0470b4e6b60 | 27 | AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; |
manitou | 0:b0470b4e6b60 | 28 | AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; |
manitou | 0:b0470b4e6b60 | 29 | AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT; |
manitou | 0:b0470b4e6b60 | 30 | AdcHandle.Init.NbrOfConversion = 1; |
manitou | 0:b0470b4e6b60 | 31 | AdcHandle.Init.DMAContinuousRequests = ENABLE; // DMA |
manitou | 0:b0470b4e6b60 | 32 | AdcHandle.Init.EOCSelection = DISABLE; |
manitou | 0:b0470b4e6b60 | 33 | HAL_ADC_Init(&AdcHandle); |
manitou | 0:b0470b4e6b60 | 34 | } |
manitou | 0:b0470b4e6b60 | 35 | |
manitou | 0:b0470b4e6b60 | 36 | static DMA_HandleTypeDef DMA_Handle; |
manitou | 0:b0470b4e6b60 | 37 | |
manitou | 0:b0470b4e6b60 | 38 | void dma_init() { |
manitou | 0:b0470b4e6b60 | 39 | // DMA init ADC1 is DMA2 channel0 stream 0 or 4 use DMA2_Stream0 thd |
manitou | 0:b0470b4e6b60 | 40 | |
manitou | 0:b0470b4e6b60 | 41 | __DMA2_CLK_ENABLE(); |
manitou | 0:b0470b4e6b60 | 42 | DMA_Handle.Instance = DMA2_Stream0; |
manitou | 0:b0470b4e6b60 | 43 | DMA_Handle.State = HAL_DMA_STATE_READY; |
manitou | 0:b0470b4e6b60 | 44 | HAL_DMA_DeInit(&DMA_Handle); |
manitou | 0:b0470b4e6b60 | 45 | |
manitou | 0:b0470b4e6b60 | 46 | DMA_Handle.Init.Channel = DMA_CHANNEL_0; |
manitou | 0:b0470b4e6b60 | 47 | DMA_Handle.Init.Direction = DMA_PERIPH_TO_MEMORY; |
manitou | 0:b0470b4e6b60 | 48 | DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE; |
manitou | 0:b0470b4e6b60 | 49 | DMA_Handle.Init.MemInc = DMA_MINC_ENABLE; |
manitou | 0:b0470b4e6b60 | 50 | DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; |
manitou | 0:b0470b4e6b60 | 51 | DMA_Handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; |
manitou | 0:b0470b4e6b60 | 52 | DMA_Handle.Init.Mode = DMA_NORMAL; |
manitou | 0:b0470b4e6b60 | 53 | DMA_Handle.Init.Priority = DMA_PRIORITY_HIGH; |
manitou | 0:b0470b4e6b60 | 54 | DMA_Handle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; |
manitou | 0:b0470b4e6b60 | 55 | DMA_Handle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; |
manitou | 0:b0470b4e6b60 | 56 | DMA_Handle.Init.MemBurst = DMA_MBURST_SINGLE; |
manitou | 0:b0470b4e6b60 | 57 | DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE; |
manitou | 0:b0470b4e6b60 | 58 | HAL_DMA_Init(&DMA_Handle); |
manitou | 0:b0470b4e6b60 | 59 | |
manitou | 0:b0470b4e6b60 | 60 | __HAL_LINKDMA(&AdcHandle, DMA_Handle, DMA_Handle); |
manitou | 0:b0470b4e6b60 | 61 | } |
manitou | 0:b0470b4e6b60 | 62 | |
manitou | 0:b0470b4e6b60 | 63 | void adc_readn( uint16_t * data, uint32_t nelems) { |
manitou | 0:b0470b4e6b60 | 64 | ADC_ChannelConfTypeDef sConfig; |
manitou | 0:b0470b4e6b60 | 65 | sConfig.Channel = ADC_CHANNEL_1; // A1 need to derive |
manitou | 0:b0470b4e6b60 | 66 | sConfig.Rank = 1; |
manitou | 0:b0470b4e6b60 | 67 | sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; |
manitou | 0:b0470b4e6b60 | 68 | sConfig.Offset = 0; |
manitou | 0:b0470b4e6b60 | 69 | HAL_ADC_ConfigChannel(&AdcHandle, &sConfig); |
manitou | 0:b0470b4e6b60 | 70 | |
manitou | 0:b0470b4e6b60 | 71 | HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)data, nelems); |
manitou | 0:b0470b4e6b60 | 72 | while (DMA_Handle.Instance->CR & DMA_SxCR_EN); // spin |
manitou | 0:b0470b4e6b60 | 73 | HAL_ADC_Stop(&AdcHandle); |
manitou | 0:b0470b4e6b60 | 74 | } |
manitou | 0:b0470b4e6b60 | 75 | |
manitou | 0:b0470b4e6b60 | 76 | #define SAMPLES 1000 |
manitou | 0:b0470b4e6b60 | 77 | |
manitou | 0:b0470b4e6b60 | 78 | int main() { |
manitou | 0:b0470b4e6b60 | 79 | uint16_t samples[SAMPLES]; |
manitou | 0:b0470b4e6b60 | 80 | uint32_t t1; |
manitou | 0:b0470b4e6b60 | 81 | int i; |
manitou | 0:b0470b4e6b60 | 82 | |
manitou | 0:b0470b4e6b60 | 83 | printf("\nSystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__); |
manitou | 0:b0470b4e6b60 | 84 | tmr.start(); |
manitou | 0:b0470b4e6b60 | 85 | |
manitou | 0:b0470b4e6b60 | 86 | memset(samples,0,sizeof samples); |
manitou | 0:b0470b4e6b60 | 87 | t1=tmr.read_us(); |
manitou | 0:b0470b4e6b60 | 88 | for(i=0;i<SAMPLES;i++) samples[i] = adc.read_u16(); |
manitou | 0:b0470b4e6b60 | 89 | t1=tmr.read_us() - t1; |
manitou | 0:b0470b4e6b60 | 90 | printf("loop sample time %.1f us %d elapsed %d us\n", (float)t1 / SAMPLES,samples[5],t1); |
manitou | 0:b0470b4e6b60 | 91 | |
manitou | 0:b0470b4e6b60 | 92 | adc_init(); |
manitou | 0:b0470b4e6b60 | 93 | dma_init(); |
manitou | 0:b0470b4e6b60 | 94 | memset(samples,77,sizeof samples); |
manitou | 0:b0470b4e6b60 | 95 | t1=tmr.read_us(); |
manitou | 0:b0470b4e6b60 | 96 | adc_readn(samples,SAMPLES); |
manitou | 0:b0470b4e6b60 | 97 | t1=tmr.read_us() - t1; |
manitou | 0:b0470b4e6b60 | 98 | printf("DMA sample time %.2f us %d elapsed %d us\n", (float)t1 / SAMPLES,samples[5],t1); |
manitou | 0:b0470b4e6b60 | 99 | } |