Change Pin mode from analog to digital in run time.
See my code below..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-08 3:37 AM
I want to use pin to work as output pin for some time and then Analog pin for some time.
how can I change the mode of pin in run time.
GPIO_InitTypeDef GPIO_InitStruct = {0};
ADC_ChannelConfTypeDef sConfig = {0};
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
- Labels:
-
ADC
-
STM32F7 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-08 3:57 AM
If you use HAL, carefully check the HAL code for side effects. I do so by directly manipulating the GPIO registers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-08 7:46 PM
Can you please give me example code ?
I want to use same 2 pins as digital for time and analog for some time.
I used following command for mode configuration, and kept the rest same -
GPIOC->MODER |= 0x01;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-08 9:20 PM
Which registers I need to modify to convert pin from analog to digital and digital to analog ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-08 11:47 PM
Which STM32?
GPIO_MODER, as you've done.
There are two bits per pin, Out is 0b01 and Analog is 0b11. So, switching from Out to Analog is
GPIOC->MODER |= 0x02;
and back to Out
GPIOC->MODER &= ~0x02;
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-08 11:54 PM
I am using STM32F746BG.
I made following changes in code for conversion, and kept the ADC function same.
Still I am not getting required output.
To make PC0 Digital -
GPIOC->MODER &= ~((1<<0) | (1<<1));
GPIOC->MODER |= (1<<0);
GPIOC->OTYPER &= ~(1<<0);
GPIOC->OSPEEDR &= ~((1<<0) | (1<<1));
GPIOC->PUPDR |= (1<<0);
To make PB3 Analog-
GPIOA->MODER |= ((1<<7) | (1<<6));
GPIOA->OTYPER &= ~(1<<3);
GPIOA->PUPDR &= ~((1<<7) | (1<<6));
To make PB3 Digital-
GPIOA->MODER &= ~((1<<6) | (1<<7));
GPIOA->MODER |= (1<<6);
GPIOA->OTYPER &= ~(1<<3);
GPIOA->OSPEEDR &= ~((1<<6) | (1<<7));
GPIOA->PUPDR |= (1<<3);
To make PC0 Analog-
GPIOC->MODER |= ((1<<1) | (1<<0));
GPIOC->OTYPER &= ~(1<<0);
GPIOC->PUPDR &= ~((1<<1) | (1<<0));
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-09 3:13 AM
OTYPER and OSPEEDR will be ignored during Analog mode, so you don't need to change them.
PUPDR has two bits, so
GPIOA->PUPDR |= (1<<3);
is incorrect for PA3.
You say To make PB3 Analog- but you then access GPIOA registers.
At the end of the day, if something does not work as expected, read out the relevant registers content and check if they are set as expected.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-09 3:31 AM
void GET_X(void)
{
uint16_t AD_RES = 10;
ADC_ChannelConfTypeDef sConfig = {0};
GPIOB->MODER &= ~((1<<0) | (1<<1));
GPIOB->MODER |= (1<<0);
GPIOB->OTYPER &= ~(1<<0);
GPIOB->OSPEEDR &= ~((1<<0) | (1<<1));
GPIOB->PUPDR &= ~ (1<<0);
GPIOB->ODR |= 1<<0;
GPIOA->MODER |= ((1<<7) | (1<<6));
GPIOA->OTYPER &= ~(1<<3);
GPIOA->PUPDR &= ~((1<<7) | (1<<6));
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_3;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1);
AD_RES = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
}
void GET_Y(void)
{
uint16_t AD_RES = 20;
ADC_ChannelConfTypeDef sConfig = {0};
GPIOA->MODER &= ~((1<<6) | (1<<7));
GPIOA->MODER |= (1<<6);
GPIOA->OTYPER &= ~(1<<3);
GPIOA->OSPEEDR &= ~((1<<6) | (1<<7));
GPIOA->PUPDR |= (1<<3);
GPIOA->ODR |= (1<<3);
GPIOB->MODER |= ((1<<1) | (1<<0));
GPIOB->OTYPER &= ~(1<<0);
GPIOB->PUPDR &= ~((1<<1) | (1<<0));
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_8;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1);
AD_RES = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
}
void GET_XY(void)
{
GET_X();
osDelay(500);
GET_Y();
osDelay(500);
}
I tried with above code.
I m not able to get second analog channel value.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-03-09 4:26 AM
By reading the values on ADC2 i am able to get both ADC values.
But the readings are not stable, however the input is stable.
How can i get stable readings ?
