cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 issues with ADC1 6 channel DMA transfer

lkaino
Associate II
Posted on August 06, 2016 at 17:38

Hello,

I have used ADC1 in 4 channel mode successfully in my project with DMA1 transferring the values in circular mode. Now I needed to add 2 more channels, but for some reason as a result reason the channel values are jumping all over the place now. I'm using pins PA4-PA7 (ADC1 channels 4-7) + PB0-PB1 (channels 8-9). The channels 8-9 are the ones I now added. Below is the initialization code that I'm using. Let me know if I need to open the preprocessor macros more to make it more understandable. It doesn't matter what conversion ranks or conversion speeds I use, the result is almost the same. Normally the channel input are at VDD/2 and this seems to result in correct conversion on all the channels. If I pull any pin to VDD or VSS, that channel starts jumping between the desired value and VDD/2. In addition the other channels start to do the same jumping. If I reduce the number of conversion back to 4, the first 4 channels are working correctly. Any help is appreciated.


#define SWITCH_ADC_INSTANCE ADC1

#define SWITCH_ADC_CLK_ENABLE() __HAL_RCC_ADC1_CLK_ENABLE()

#define SWITCH_ADC_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE()

#define SWITCH_ADC_DMA_CHANNEL_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE()

#define SWITCH_ADC_FIRST_CHANNEL_NUMBER 4

#define SWITCH_ADC_CHANNEL_1 ADC_CHANNEL_4

#define SWITCH_ADC_CHANNEL_2 ADC_CHANNEL_5

#define SWITCH_ADC_CHANNEL_3 ADC_CHANNEL_6

#define SWITCH_ADC_CHANNEL_4 ADC_CHANNEL_7

#define SWITCH_ADC_CHANNEL_5 ADC_CHANNEL_8

#define SWITCH_ADC_CHANNEL_6 ADC_CHANNEL_9

#define SWITCH_ADC_CHANNEL_1_GPIO_PIN GPIO_PIN_4

#define SWITCH_ADC_CHANNEL_2_GPIO_PIN GPIO_PIN_5

#define SWITCH_ADC_CHANNEL_3_GPIO_PIN GPIO_PIN_6

#define SWITCH_ADC_CHANNEL_4_GPIO_PIN GPIO_PIN_7

#define SWITCH_ADC_CHANNEL_5_GPIO_PIN GPIO_PIN_0

#define SWITCH_ADC_CHANNEL_6_GPIO_PIN GPIO_PIN_1

#define SWITCH_ADC_GPIO GPIOA

#define SWITCH_ADC_GPIO2 GPIOB

#define ADC_SAMPLING_TIME ADC_SAMPLETIME_239CYCLES_5


static ADC_ChannelConfTypeDef gADCChannels[SWITCH_NUM_OF_CHANNELS] =

{

[SWITCH_CHANNEL_1] =

{

.Channel = SWITCH_ADC_CHANNEL_1,

.Rank = 1,

.SamplingTime = ADC_SAMPLING_TIME

},

[SWITCH_CHANNEL_2] =

{

.Channel = SWITCH_ADC_CHANNEL_2,

.Rank = 2,

.SamplingTime = ADC_SAMPLING_TIME

},

[SWITCH_CHANNEL_3] =

{

.Channel = SWITCH_ADC_CHANNEL_3,

.Rank = 3,

.SamplingTime = ADC_SAMPLING_TIME

},

[SWITCH_CHANNEL_4] =

{

.Channel = SWITCH_ADC_CHANNEL_4,

.Rank = 4,

.SamplingTime = ADC_SAMPLING_TIME

},

[SWITCH_CHANNEL_5] =

{

.Channel = SWITCH_ADC_CHANNEL_5,

.Rank = 5,

.SamplingTime = ADC_SAMPLING_TIME

},

[SWITCH_CHANNEL_6] =

{

.Channel = SWITCH_ADC_CHANNEL_6,

.Rank = 6,

.SamplingTime = ADC_SAMPLING_TIME

}

};


// DMA stores ADC conversions here

static u16 gChannelRawValue[10];



/////////////////////////////////// INIT CODE:


// De-init of ADC is required, otherwise init would fail

ADCHandle.Instance = SWITCH_ADC_INSTANCE;

HALRet = HAL_ADC_DeInit(&ADCHandle);

if (HALRet != HAL_OK)

{

printf(''[SWITCH] Failed to de-init ADC (%d, %d, %d).\r\n'', HALRet, ADCHandle.ErrorCode, ADCHandle.State);

retVal = SWITCH_ERROR;

}


ADCHandle.Init.ScanConvMode = ADC_SCAN_ENABLE;

ADCHandle.Init.ContinuousConvMode = ENABLE;

ADCHandle.Init.DiscontinuousConvMode = DISABLE;

ADCHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START;

ADCHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;

ADCHandle.Init.NbrOfConversion = SWITCH_NUM_OF_CHANNELS;

HALRet = HAL_ADC_Init(&ADCHandle);

if (HALRet != HAL_OK)

{

printf(''[SWITCH] Failed to init ADC (%d, %d, %d).\r\n'', HALRet, ADCHandle.ErrorCode, ADCHandle.State);

retVal = SWITCH_ERROR;

}


switchChannel_e channel;

for (channel = 0; channel < 
SWITCH_NUM_OF_CHANNELS
; channel++)

{

HALRet
= 
HAL_ADC_ConfigChannel
(&ADCHandle, &gADCChannels[channel]);

if (HALRet != HAL_OK)

{

printf(''[SWITCH] Failed to init ADC channel %d (%d).\r\n'', channel, HALRet);

retVal
= 
SWITCH_ERROR
;

}

}


HALRet
= 
HAL_ADCEx_Calibration_Start
(&ADCHandle);

if (HALRet != HAL_OK)

{

printf(''[SWITCH] Failed to calibrate ADC (%d).\r\n'', HALRet);

retVal
= 
SWITCH_ERROR
;

}


HALRet
= 
HAL_ADC_Start_DMA
(&ADCHandle, (uint32_t *)&gChannelRawValue[0], ARRAYLEN(gChannelRawValue));

if (HALRet != HAL_OK)

{

printf(''[SWITCH] Failed to start ADC in DMA mode (%d).\r\n'', HALRet);

retVal
= 
SWITCH_ERROR
;

}


///////////////////////////////// MSP INIT CODE

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)

{

if(hadc->Instance == SWITCH_ADC_INSTANCE)

{

GPIO_InitTypeDef GPIO_InitStruct;

HAL_StatusTypeDef HALRet;


SWITCH_ADC_CLK_ENABLE();

SWITCH_ADC_GPIO_CLK_ENABLE();

SWITCH_ADC_DMA_CHANNEL_CLK_ENABLE();


GPIO_InitStruct.Pin = SWITCH_ADC_CHANNEL_1_GPIO_PIN |

SWITCH_ADC_CHANNEL_2_GPIO_PIN |

SWITCH_ADC_CHANNEL_3_GPIO_PIN |

SWITCH_ADC_CHANNEL_4_GPIO_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;

HAL_GPIO_Init(SWITCH_ADC_GPIO, &GPIO_InitStruct);


GPIO_InitStruct.Pin = SWITCH_ADC_CHANNEL_5_GPIO_PIN |

SWITCH_ADC_CHANNEL_6_GPIO_PIN;

HAL_GPIO_Init(SWITCH_ADC_GPIO2, &GPIO_InitStruct);


gDMAHandle.Instance = SWITCH_TIMER_DMA_INSTANCE;

gDMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;

gDMAHandle.Init.PeriphInc = DMA_PINC_DISABLE;

gDMAHandle.Init.MemInc = DMA_MINC_ENABLE;

gDMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

gDMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

gDMAHandle.Init.Mode = DMA_CIRCULAR;

gDMAHandle.Init.Priority = DMA_PRIORITY_LOW;


HALRet = HAL_DMA_Init(&gDMAHandle);

if (HALRet != HAL_OK)

{

printf(''[SWITCH] Failed to init DMA (%d).\r\n'', HALRet);

gInitStatus = SWITCH_ERROR;

}


__HAL_LINKDMA(hadc, DMA_Handle, gDMAHandle);

}

}

1 REPLY 1
lkaino
Associate II
Posted on August 07, 2016 at 08:54

Okay duh, I had understood incorrectly how DMA transfers the samples from multiple channels.

The issue was here:

static u16 gChannelRawValue[10];

Number of array elements should be the number of channels, 6 in this case.

static u16 gChannelRawValue[10]