2016-08-06 08:38 AM
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);
}
}
2016-08-06 11:54 PM
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]