cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f4 adc multiple channels with dma

d4ng3r09
Associate II
Posted on January 14, 2015 at 17:40

Hi, I am trying to use 4 adc channels with adc 1 and dma 1 stream 0.I don't know why but it seems that the dma isn't doing its job.

Any suggestions?

#include ''stm32f4xx_gpio.h''
#include ''stm32f4xx_dma.h''
#include ''stm32f4xx_adc.h''
#include ''stm32f4xx_rcc.h''
#include ''stm32f4xx.h''
#include ''misc.h''
#include ''stm32f4xx_tim.h''
#include ''stm32f4xx_exti.h''
#include ''stm32f4xx_syscfg.h''
#define BUFSIZE 1
volatile uint16_t ADCConvertedValues[4 * BUFSIZE];
int NumbConv = 0;
float Sens1 = 0, Sens2 = 0, Sens3 = 0, Sens4 = 0;
void ADC_GPIO_Configuration(void) // CONFIGURE THE PINS USED FOR THE ADC CHANNELL
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2
| GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void ADC12_DMA_Configuration(void) //CONFIG THE DMA
{
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA1 clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
DMA_DeInit(DMA1_Stream0);
/* DMA configuration */
/* DMA1 Channel1 Init Test */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR; // The register of a singular ADC
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) & ADCConvertedValues[0]; //begin adress of the buffer
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 4; //size of the buffer
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //HALFOWord=16 bits the adc is configured in 12 bits mode so we need 16 bits to fit them in
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //same
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream0, &DMA_InitStructure); // ADC1
}
/**************************************************************************************/
void ADC_Configuration(void) {
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_GPIO_Configuration();
ADC12_DMA_Configuration();
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; // Not Multi Mode
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // Freerun
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; // Not using
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_56Cycles); // PA0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_56Cycles); // PA1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_56Cycles); //PA2
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_56Cycles); //PA3
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Stream0, ENABLE);
// ADC_StartConversion(ADC1);
}
void DMA1_Channel0_IRQHandler(void) // X Hz
{
if (DMA_GetITStatus(DMA1_Stream0, DMA_IT_TCIF0)) {
if (NumbConv < 21) {
NumbConv++;
Sens1 = ADCConvertedValues[0] + Sens1;
Sens2 = ADCConvertedValues[1] + Sens2;
Sens3 = ADCConvertedValues[2] + Sens3;
Sens4 = ADCConvertedValues[3] + Sens4;
}
if (NumbConv == 21) {
Sens1 = Sens1 / 20;
Sens2 = Sens2 / 20;
Sens3 = Sens3 / 20;
Sens4 = Sens4 / 20;
}
DMA_ClearITPendingBit(DMA1_Stream0, DMA_IT_TCIF0);
}
}
void NVIC_Configuration(void) {
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void) {
NVIC_Configuration();
ADC_Configuration();
DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
ADC_SoftwareStartConv(ADC1);
while (1) { 
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{
}
}
#endif
//******************************************************************************

#discovery #dma #adc #nvic #stm32f4
4 REPLIES 4
Posted on January 14, 2015 at 17:56

DMA2

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on January 14, 2015 at 18:00

0690X00000603JAQAY.jpg
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
d4ng3r09
Associate II
Posted on January 14, 2015 at 20:55

I update the code as follows . The DMA seems to work now ONLY one time :I concluded that because the values never change when i debug the program.

Any ideas?

#include ''stm32f4xx_gpio.h''
#include ''stm32f4xx_dma.h''
#include ''stm32f4xx_adc.h''
#include ''stm32f4xx_rcc.h''
#include ''stm32f4xx.h''
#include ''misc.h''
#include ''stm32f4xx_tim.h''
#include ''stm32f4xx_exti.h''
#include ''stm32f4xx_syscfg.h''
#define BUFSIZE 1
volatile uint16_t ADCConvertedValues[4 * BUFSIZE];
int NumbConv = 0;
float Sens1 = 0, Sens2 = 0, Sens3 = 0, Sens4 = 0;
void ADC_GPIO_Configuration(void) // CONFIGURE THE PINS USED FOR THE ADC CHANNELL
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2
| GPIO_Pin_3;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void ADC12_DMA_Configuration(void) //CONFIG THE DMA
{
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA1 clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_DeInit(DMA2_Stream0);
/* DMA configuration */
/* DMA1 Channel1 Init Test */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR; // The register of a singular ADC
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) & ADCConvertedValues[0]; //begin adress of the buffer
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 4; //size of the buffer
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //HALFOWord=16 bits the adc is configured in 12 bits mode so we need 16 bits to fit them in
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //same
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure); // ADC1
}
/**************************************************************************************/
void ADC_Configuration(void) {
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_GPIO_Configuration();
ADC12_DMA_Configuration();
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; // Not Multi Mode
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // Freerun
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles); // PA0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_3Cycles); // PA1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_3Cycles); //PA2
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_3Cycles); //PA3
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
DMA_Cmd(DMA2_Stream0, ENABLE);
// ADC_StartConversion(ADC1);
}
void DMA2_Stream0_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0)) {
if (NumbConv < 21) {
NumbConv++;
Sens1 = ADCConvertedValues[0] + Sens1;
Sens2 = ADCConvertedValues[1] + Sens2;
Sens3 = ADCConvertedValues[2] + Sens3;
Sens4 = ADCConvertedValues[3] + Sens4;
}
if (NumbConv == 21) {
Sens1 = Sens1 / 20;
Sens2 = Sens2 / 20;
Sens3 = Sens3 / 20;
Sens4 = Sens4 / 20;
}
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
}
}
void NVIC_Configuration(void) {
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void) {
NVIC_Configuration();
ADC_Configuration();
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
ADC_SoftwareStartConv(ADC1);
while (1) {//NumbConv=0;
//Sens1=0;Sens2=0;Sens3=0;Sens4=0;
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{
}
}
#endif
//******************************************************************************

Posted on January 14, 2015 at 21:56

Looks to be interrupting far too frequently (every 60 ADC cycles), I don't have time to rack up the code at the moment.

Why would you not get all 20 samples and THEN interrupt? Have two buffers, so the DMA isn't overwriting the buffer you're working on. Not sure what debugger you're using, or how frequently it updates the memory view, but the most practical method to determine it's working is to have the interrupt toggle a GPIO/LED, and then measure the period on a scope.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..