Triple ADC w/ DMA

μC Board: STM32F429ZI-Discovery
IDE: μVision V5.13.0.0

Enable ADC Peripheral, in Triple Mode, using DMA.

CDR ADC Priority Channel Pin
1 ADC1 1 CH13 PC3
2 ADC2 1 CH00 PA0
3 ADC3 1 CH15 PF5
4 ADC1 2 CH08 PB0
5 ADC2 2 CH10 PC0
6 ADC3 2 CH09 PF3
7 ADC1 3 CH06 PA6
8 ADC2 3 CH14 PC4
9 ADC3 3 CH03 PA3

 


TIM2 Enable

[pastacode lang=”c” manual=”%23define%20ADC_PER%204499%0A%0ARCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2%2C%20ENABLE)%3B%0A%0ATIM_BaseStruct_ST.TIM_Prescaler%20%3D%200%3B%0ATIM_BaseStruct_ST.TIM_CounterMode%20%3D%20TIM_CounterMode_Up%3B%0A%20%2F%2F%20899%20%3D%3E%20100kHz%2C%202249%20%3D%3E%2040kHz%2C%204499%20%3D%3E%2020kHz%2C%208999%20%3D%3E%2010kHz%0ATIM_BaseStruct_ST.TIM_Period%20%3D%20ADC_PER%3B%20%0ATIM_BaseStruct_ST.TIM_ClockDivision%20%3D%20TIM_CKD_DIV1%3B%0A%0ATIM_TimeBaseInit(TIM2%2C%20%26TIM_BaseStruct_ST)%3B%0ATIM_SelectOutputTrigger(TIM2%2C%20TIM_TRGOSource_Update)%3B” message=”” highlight=”” provider=”manual”/]


ADC Clock Enable

[pastacode lang=”c” manual=”%23include%20%22stm32f4xx_adc.h%22%0ARCC_APB2PeriphClockCmd%20(RCC_APB2Periph_ADC1%2C%20ENABLE)%3B%0ARCC_APB2PeriphClockCmd%20(RCC_APB2Periph_ADC2%2C%20ENABLE)%3B%0ARCC_APB2PeriphClockCmd%20(RCC_APB2Periph_ADC3%2C%20ENABLE)%3B” message=”” highlight=”” provider=”manual”/]


ADC set to Triple Mode, DMA Enable, No Prescaler

[pastacode lang=”c” manual=”ADC_CommonInitTypeDef%20ADC_CommonInitStructure%3B%0A%0AADC_CommonInitStructure.ADC_Mode%20%20%20%20%20%20%20%20%20%20%3D%20ADC_TripleMode_RegSimult%3B%0AADC_CommonInitStructure.ADC_Prescaler%20%20%20%20%20%3D%20ADC_Prescaler_Div2%3B%0AADC_CommonInitStructure.ADC_DMAAccessMode%20%3D%20ADC_DMAAccessMode_1%3B%0AADC_CommonInit%20(%26ADC_CommonInitStructure)%3B” message=”” highlight=”” provider=”manual”/]


3 conversions for each ADC, hence 9 in total.
Highest resolution of 12 bits, right data alignment and event trigger by TIM2 interrupts.

[pastacode lang=”c” manual=”ADC_InitTypeDef%20ADC_InitStructure%3B%0A%0AADC_InitStructure.ADC_ScanConvMode%20%20%20%20%20%20%20%3D%20ENABLE%3B%0AADC_InitStructure.ADC_NbrOfConversion%20%20%20%20%3D%203%3B%0AADC_InitStructure.ADC_Resolution%20%20%20%20%20%20%20%20%20%3D%20ADC_Resolution_12b%3B%0AADC_InitStructure.ADC_DataAlign%20%20%20%20%20%20%20%20%20%20%3D%20ADC_DataAlign_Right%3B%0AADC_InitStructure.ADC_ContinuousConvMode%20%3D%20DISABLE%3B%0A%0ATIM_SelectOutputTrigger%20(TIM2%2C%20TIM_TRGOSource_Update)%3B%0AADC_InitStructure.ADC_ExternalTrigConv%20%20%20%20%20%3D%20ADC_ExternalTrigConv_T2_TRGO%3B%0AADC_InitStructure.ADC_ExternalTrigConvEdge%20%3D%20ADC_ExternalTrigConvEdge_Rising%3B%0A%0AADC_Init(ADC1%2C%20%26ADC_InitStructure)%3B%0AADC_Init(ADC2%2C%20%26ADC_InitStructure)%3B%0AADC_Init(ADC3%2C%20%26ADC_InitStructure)%3B” message=”” highlight=”” provider=”manual”/]


Set each channel to the right pin, with 15 cycles for sampling the signal

[pastacode lang=”c” manual=”ADC_RegularChannelConfig%20(ADC1%2C%20ADC_Channel_13%2C%201%2C%20ADC_SampleTime_15Cycles)%3B%0AADC_RegularChannelConfig%20(ADC1%2C%20ADC_Channel_8%2C%20%202%2C%20ADC_SampleTime_15Cycles)%3B%0AADC_RegularChannelConfig%20(ADC1%2C%20ADC_Channel_6%2C%20%203%2C%20ADC_SampleTime_15Cycles)%3B%0A%0AADC_RegularChannelConfig%20(ADC2%2C%20ADC_Channel_0%2C%20%201%2C%20ADC_SampleTime_15Cycles)%3B%0AADC_RegularChannelConfig%20(ADC2%2C%20ADC_Channel_10%2C%202%2C%20ADC_SampleTime_15Cycles)%3B%0AADC_RegularChannelConfig%20(ADC2%2C%20ADC_Channel_14%2C%203%2C%20ADC_SampleTime_15Cycles)%3B%0A%0AADC_RegularChannelConfig%20(ADC3%2C%20ADC_Channel_15%2C%201%2C%20ADC_SampleTime_15Cycles)%3B%0AADC_RegularChannelConfig%20(ADC3%2C%20ADC_Channel_9%2C%20%202%2C%20ADC_SampleTime_15Cycles)%3B%0AADC_RegularChannelConfig%20(ADC3%2C%20ADC_Channel_3%2C%20%203%2C%20ADC_SampleTime_15Cycles)%3B” message=”” highlight=”” provider=”manual”/]


DMA Clock Enable.

Setup DMA data transport, base address, matrix size, half word data transfer and circular mode.

Enable Stream4 of DMA2.

[pastacode lang=”c” manual=”%23include%20%22stm32f4xx_dma.h%22%0ARCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2%2C%20ENABLE)%3B%0A%0ADMA_InitTypeDef%20DMA_InitStructure%3B%0A%0ADMA_InitStructure.DMA_DIR%20%20%20%20%20%3D%20DMA_DIR_PeripheralToMemory%3B%0ADMA_InitStructure.DMA_Channel%20%3D%20DMA_Channel_0%3B%0A%0ADMA_InitStructure.DMA_PeripheralBaseAddr%20%3D%20(uint32_t)%26ADC-%3ECDR%3B%0ADMA_InitStructure.DMA_PeripheralInc%20%20%20%20%20%20%3D%20DMA_PeripheralInc_Disable%3B%0ADMA_InitStructure.DMA_Memory0BaseAddr%20%20%20%20%3D%20(uint32_t)(%26adc%5B0%5D)%3B%0ADMA_InitStructure.DMA_MemoryInc%20%20%20%20%20%20%20%20%20%20%3D%20DMA_MemoryInc_Enable%3B%0A%0ADMA_InitStructure.DMA_BufferSize%20%3D%209%3B%0A%0ADMA_InitStructure.DMA_PeripheralDataSize%20%3D%20DMA_PeripheralDataSize_HalfWord%3B%0ADMA_InitStructure.DMA_MemoryDataSize%20%20%20%20%20%3D%20DMA_MemoryDataSize_HalfWord%3B%0A%0ADMA_InitStructure.DMA_Mode%20%3D%20DMA_Mode_Circular%3B%0A%0ADMA_Init(DMA2_Stream4%2C%20%26DMA_InitStructure)” message=”” highlight=”” provider=”manual”/]


Setup and enable interrupt event of DMA

[pastacode lang=”c” manual=”NVIC_InitTypeDef%20ADCNVICConfig%3B%0AADCNVICConfig.NVIC_IRQChannel%20%3D%20DMA2_Stream4_IRQn%3B%0AADCNVICConfig.NVIC_IRQChannelPreemptionPriority%20%3D%200%3B%0AADCNVICConfig.NVIC_IRQChannelSubPriority%20%3D%201%3B%0AADCNVICConfig.NVIC_IRQChannelCmd%20%3D%20ENABLE%3B%0ANVIC_Init(%26ADCNVICConfig)%3B%0A%0AADC_DMACmd(ADC1%2C%20ENABLE)%3B%0AADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE)%3B%0ADMA_ITConfig(DMA2_Stream4%2C%20DMA_IT_TC%2C%20ENABLE)%3B%0A%0ADMA_Cmd(DMA2_Stream4%2C%20ENABLE)%3B%20″ message=”” highlight=”” provider=”manual”/]


Setup ADC1 as Master and ADC2 and ADC3 as Slaves, enable DMA and all ADCs.

[pastacode lang=”c” manual=”ADC_DMACmd(ADC1%2C%20ENABLE)%3B%0AADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE)%3B%0A%0AADC_Cmd(ADC1%2C%20ENABLE)%3B%0AADC_Cmd(ADC2%2C%20ENABLE)%3B%0AADC_Cmd(ADC3%2C%20ENABLE)%3B” message=”” highlight=”” provider=”manual”/]


The full code can be found in GitHUB

Published By
admin

1 Comment

aatif shaikh

#define ADC_PER 4499
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_BaseStruct_ST.TIM_Prescaler = 0;
TIM_BaseStruct_ST.TIM_CounterMode = TIM_CounterMode_Up;
// 899 => 100kHz, 2249 => 40kHz, 4499 => 20kHz, 8999 => 10kHz
TIM_BaseStruct_ST.TIM_Period = ADC_PER;
TIM_BaseStruct_ST.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &TIM_BaseStruct_ST);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

If I’m not mistaken you used this “Timer2” to trigger the “ADC start conversion”. I’ve ported your code for STM32F205xx(HSI-16Mhz) with slight modification. In my case, I’m using 4 channels on two different ADC. the issue I’m getting is that it is not calling it on its own (Timer trigger), I’ve to personally call the ADC_SoftwareStartConv(ADC1); to trigger the conversion.

Leave a Reply to aatif shaikh Cancel Reply

Your email address will not be published. Required fields are marked *