1
\$\begingroup\$

I need to read 15 channels ADC. However my MCU is specific named STM32F042K6T6. I decided to use an analog MUX to read every channel from just one pin. But, I didn't read accurately the datas by writing these codes:

for ( z = 0; z <= 15; z += 1 )
{
HAL_GPIO_WritePin(GPIOA, ADC_CH_SELECT0_Pin, ( z >> 0) & 0x01 ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, ADC_CH_SELECT1_Pin, ( z >> 1) & 0x01 ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, ADC_CH_SELECT2_Pin, ( z >> 2) & 0x01 ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, ADC_CH_SELECT3_Pin, ( z >> 3) & 0x01 ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

When I decrease the repetition count of for, namely for (z=0; z<=2; z++)

The results is OK. But I can not read all the channels with that. Because of this problem, I decided to use an adc interrupt. I have set all the settings like ADC resolution, Cycle, right alignment, NVIC e.t.c. with STMCUBEMX. These codes are here:

static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}

And I know that when the configurations are OK, I need to Start ADC INT with that code:

HAL_ADC_Start_IT(&hadc);

I have inserted the code within main function above from while.

And I know that after every reading cycle, our program must jump to that function:

void HAL_ADC_ConvtCpltCallback(ADC_HandleTypeDef* hadc)
{
Temporary_ADC_Value[0] = HAL_ADC_GetValue(hadc);  
}

When I try to read adc value from Temporary_ADC_Value[0], I have not experienced a appropriate value. What may be the problem about issue? Is there any point that I forget? That issue is important for me. Thanks in advance.

MUX Schematic

\$\endgroup\$
  • \$\begingroup\$ It looks like you are cycling the mux select pins as fast as the for loop will go, are you allowing the ADC to complete a sample before selecting another channel to read? Usually after selecting the channel you will have to wait for a conversion to complete before changing the channel. I would allow 2 conversions in case the conversion started in the middle of your mux switch. There is also a non-zero time for the mux to select a new channel and output it. \$\endgroup\$ – Ron Beyer May 1 at 21:18
  • \$\begingroup\$ Also make sure that you are setting your ADC_CH_SELECT_EN to low to enable the output on the mux. \$\endgroup\$ – Ron Beyer May 1 at 21:21
  • \$\begingroup\$ Thanks a lot. I understand you absolutely. How can i do these things for stm32 MCU? or How can I use a for repetition about this issue. \$\endgroup\$ – ber2bingol May 2 at 6:01
  • \$\begingroup\$ Actually I decided to use adc interrupt mode to cope with this issue. If the conversion is completed, the program will jump to interrupt function and will select the channels by turns. But I can not do it accurately. \$\endgroup\$ – ber2bingol May 2 at 6:45
  • \$\begingroup\$ I really thank you. Every person who is in there very helpful. On account of you, I managed to reach final. \$\endgroup\$ – ber2bingol May 26 at 12:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.