Question
STM32F1 ADC DMA multichannel continuous mode troubles
Posted on October 19, 2016 at 11:23
Hi everyone,
I have troubles getting the ADC working properly. This is my set-up : - STM32F103CB - ADC1 with 8 channels - DMA set on ADC1 I would like to make the conversion of the 8 channels continuously in order to show the value on a screen in real-time. I made the initialization and started the ADC. I get values which are correct considering the analog input, but sometimes I get only 0 for all channels, and then it shows the values again. Here are my code for ADC Initialization (ADC_FOR_CHANNELS_INPUTS = ADC1)
:void vHILCHANNELS_Initialize(uint16_t *__pu16_DMAChannelsResults)
{
ADC_ChannelConfTypeDef __t_ChannelConfig;
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* Common config */
_t_ADC1Handle.Instance = ADC_FOR_CHANNELS_INPUTS;
_t_ADC1Handle.Init.ScanConvMode = ADC_SCAN_ENABLE;
_t_ADC1Handle.Init.ContinuousConvMode = ENABLE;
_t_ADC1Handle.Init.DiscontinuousConvMode = DISABLE;
_t_ADC1Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
_t_ADC1Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
_t_ADC1Handle.Init.NbrOfConversion = 8;
if (HAL_ADC_Init(&_t_ADC1Handle) != HAL_OK)
{
printf(''Error while initialization of ADC for channels inputs\n'');
}
/*Configure Regular CH1 */
__t_ChannelConfig.Channel = ADC_CHANNEL_0;
__t_ChannelConfig.Rank = 1;
__t_ChannelConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC CH1\n'');
}
/*Configure Regular CH2 */
__t_ChannelConfig.Channel = ADC_CHANNEL_1;
__t_ChannelConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC CH2\n'');
}
/*Configure Regular CH3 */
__t_ChannelConfig.Channel = ADC_CHANNEL_2;
__t_ChannelConfig.Rank = 3;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC CH3\n'');
}
/*Configure Regular CH4 */
__t_ChannelConfig.Channel = ADC_CHANNEL_3;
__t_ChannelConfig.Rank = 4;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC CH4\n'');
}
/*Configure Regular CH5 */
__t_ChannelConfig.Channel = ADC_CHANNEL_4;
__t_ChannelConfig.Rank = 5;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC CH5\n'');
}
/*Configure Regular CH6 */
__t_ChannelConfig.Channel = ADC_CHANNEL_5;
__t_ChannelConfig.Rank = 6;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC CH6\n'');
}
/*Configure Regular Z */
__t_ChannelConfig.Channel = ADC_CHANNEL_6;
__t_ChannelConfig.Rank = 7;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC Z\n'');
}
/*Configure Regular INTENS_BLK */
__t_ChannelConfig.Channel = ADC_CHANNEL_7;
__t_ChannelConfig.Rank = 8;
if (HAL_ADC_ConfigChannel(&_t_ADC1Handle, &__t_ChannelConfig) != HAL_OK)
{
printf(''Error while initialization of ADC INTENS_BLK\n'');
}
/* Enables ADC and starts conversion of the regular channels */
if(HAL_ADC_Start(&_t_ADC1Handle) != HAL_OK)
{
printf(''Error while Starting ADC\n'');
}
/* Enables ADC DMA request */
if(HAL_ADC_Start_DMA(&_t_ADC1Handle,(uint32_t *)__pu16_DMAChannelsResults, 8) != HAL_OK)
{
printf(''Error while Starting DMA for ADC\n'');
}
}
Here are my code for MSP redefined :
void HAL_ADC_MspInit(ADC_HandleTypeDef* __pt_ADCHandle)
{
GPIO_InitTypeDef __t_GPIO_InitStruct;
if(__pt_ADCHandle->Instance == ADC_FOR_CHANNELS_INPUTS)
{
/* Peripheral clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA0-WKUP ------> ADC1_IN0
PA1 ------> ADC1_IN1
PA2 ------> ADC1_IN2
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4
PA5 ------> ADC1_IN5
PA6 ------> ADC1_IN6
PA7 ------> ADC1_IN7
*/
__t_GPIO_InitStruct.Pin = ADC_CH1_PIN|ADC_CH2_PIN|ADC_CH3_PIN|ADC_CH4_PIN
|ADC_CH5_PIN|ADC_CH6_PIN|ADC_Z_PIN|ADC_INTENS_BLK_PIN;
__t_GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(ADC_PORT, &__t_GPIO_InitStruct);
/* Peripheral DMA init*/
_t_DMAADC1.Instance = DMA_ADC_CHANNELS_INPUTS;
_t_DMAADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;
_t_DMAADC1.Init.PeriphInc = DMA_PINC_DISABLE;
_t_DMAADC1.Init.MemInc = DMA_MINC_ENABLE;
_t_DMAADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
_t_DMAADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
_t_DMAADC1.Init.Mode = DMA_CIRCULAR;
_t_DMAADC1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
if (HAL_DMA_Init(&_t_DMAADC1) != HAL_OK)
{
printf(''Error during initialization of DMA for ADC'');
}
__HAL_LINKDMA(__pt_ADCHandle,DMA_Handle,_t_DMAADC1);
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* __pt_ADCHandle)
{
if(__pt_ADCHandle->Instance == ADC_FOR_CHANNELS_INPUTS)
{
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA0-WKUP ------> ADC1_IN0
PA1 ------> ADC1_IN1
PA2 ------> ADC1_IN2
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4
PA5 ------> ADC1_IN5
PA6 ------> ADC1_IN6
PA7 ------> ADC1_IN7
*/
HAL_GPIO_DeInit(ADC_PORT, ADC_CH1_PIN|ADC_CH2_PIN|ADC_CH3_PIN|ADC_CH4_PIN
|ADC_CH5_PIN|ADC_CH6_PIN|ADC_Z_PIN|ADC_INTENS_BLK_PIN);
/* Peripheral DMA DeInit*/
HAL_DMA_DeInit(__pt_ADCHandle->DMA_Handle);
}
}
Here is the main function :
uint16_t _au16_ChannelsResults[8];
void main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
vHILSTM32F103CB_SystemClockConfig();
/* Initialize all configured peripherals */
vHILCHANNELS_Initialize(_au16_ChannelsResults);
while (1)
{
printf(''***** ADC VALUES :\n'');
printf(''CH1 = %03X\nCH2 = %03X\nCH3 = %03X\nCH4 = %03X\nCH5 = %03X\nCH6 = %03X\nZ = %03X\nINTENS_BLK = %03X\n'', _au16_ChannelsResults[0], _au16_ChannelsResults[1], _au16_ChannelsResults[2], _au16_ChannelsResults[3], _au16_ChannelsResults[4], _au16_ChannelsResults[5], _au16_ChannelsResults[6], _au16_ChannelsResults[7]);
HAL_Delay(200);
}
Here are the Terminal log for print (Z always at 0 is normal), where you can see the 0s on values sometimes:
***** ADC VALUES :
CH1 = 000
CH2 = 000
CH3 = 000
CH4 = 000
CH5 = 000
CH6 = 000
Z = 000
INTENS_BLK = 000
***** ADC VALUES :
CH1 = FC6
CH2 = FB4
CH3 = FB0
CH4 = FBC
CH5 = FC7
CH6 = FAC
Z = 000
INTENS_BLK = E5E
***** ADC VALUES :
CH1 = FC2
CH2 = FB6
CH3 = FA8
CH4 = FBA
CH5 = FD2
CH6 = FBC
Z = 000
INTENS_BLK = E5A
***** ADC VALUES :
CH1 = 000
CH2 = 000
CH3 = 000
CH4 = 000
CH5 = 000
CH6 = 000
Z = 000
INTENS_BLK = 000
***** ADC VALUES :
CH1 = FBF
CH2 = FAC
CH3 = F9D
CH4 = FB4
CH5 = FC4
CH6 = FAA
Z = 000
INTENS_BLK = E53
***** ADC VALUES :
CH1 = FC4
CH2 = FB4
CH3 = FAC
CH4 = FB4
CH5 = FCD
CH6 = FB4
Z = 000
INTENS_BLK = E60
***** ADC VALUES :
CH1 = FC2
CH2 = FAC
CH3 = FA8
CH4 = FB6
CH5 = FBF
CH6 = FA6
Z = 000
INTENS_BLK = E5A
***** ADC VALUES :
CH1 = FC5
CH2 = FB0
CH3 = FA3
CH4 = FB6
CH5 = FC8
CH6 = FA9
Z = 000
INTENS_BLK = E59
***** ADC VALUES :
CH1 = 000
CH2 = 000
CH3 = 000
CH4 = 000
CH5 = 000
CH6 = 000
Z = 000
INTENS_BLK = 000
***** ADC VALUES :
CH1 = FC5
CH2 = FB4
CH3 = FAD
CH4 = FB7
CH5 = FCC
CH6 = FB0
Z = 000
INTENS_BLK = E5C
***** ADC VALUES :
CH1 = FCE
CH2 = FB5
CH3 = FB2
CH4 = FBA
CH5 = FCE
CH6 = FB2
Z = 000
INTENS_BLK = E60
I tried different ways : changing sample rate, increasing the values buffer for DMA. Always get 0 at one time and it distorts my calculations.
I would be grateful if someone could help me on this.
If I miss some information, please tell me.
Thank you,
Marc
#adc #dma #stm32f1