cancel
Showing results for 
Search instead for 
Did you mean: 

Changing the pin configuration at run-time

Iman Hosseinzadeh
Associate III
Posted on July 17, 2017 at 09:17

Hi All,

I would like to read a resistive touch screen with a STM32F407 micro butwithout a driver chip. For that I should change the pin functionality at run-time.

First I set the configurations like below:

 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 
 GPIO_InitStruct.Pin = GPIO_PIN_1;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
 
 
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV6;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = 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(__FILE__, __LINE__);
 }
 /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Everything works nice. I set PA1 as input because it should be Hi-Z. Alternatively I can set it to OpenDrain output and High value. So:

PA0 -> ADC-IN0

PA1 -> Hi-Z

PA2 -> HIGH

PA3 -> LOW

But when I change the pin configuration as follows:

PA0 ->

HIGH

PA1 -> LOW

PA2 -> ADC-IN2

PA3 ->

Hi-Z

to read the other dimension, the program does not work. Even the digital outputs are not set correctly:

 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 
 GPIO_InitStruct.Pin = GPIO_PIN_3;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
 
 
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV6;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = 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(__FILE__, __LINE__);
 }
 /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_112CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 _Error_Handler(__FILE__, __LINE__);
 }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Any suggestions?

I think a same code worked with STM32f But I'm not sure.

#stm32f407 #runtime #resistive-touch #pin-configuration
4 REPLIES 4
S.Ma
Principal
Posted on July 17, 2017 at 10:40

The way the GPIO between F103 and F4 have changed much, for example the alternate function management has changed. Best is to have the proper sequence on the GPIO register to avoid transients on the GPIO.

To debug it, go to debug mode (if using IAR or KEIL) and open the HW register window to play manually on these registers. If monitoring pins with scope probes, it will help make sure everything works fine.

Iman Hosseinzadeh
Associate III
Posted on July 18, 2017 at 07:51

Thanks for reply.

I can not understand why the first code works but second one does not. If I make the second configuration with STM32CubeMX, the program works nicely but again if I change it to the first code manually, everything become wrong.

Perhaps the CubeMX software changes some invisible settings!

RSabl
Associate II

Don't use HAL to change the pin direction, modify the MODER register directly and it should work.

S.Ma
Principal

First, activate the GPIO clocks if not already done/

Second, set the output push pull level FIRST before even switch as output.

Now when you want to read analog input, you'll have to reconfigure the gpio pin to ANALOG (MODE pin = (1,1), remove pull-ups (if needed), then ADC conversion to take place.

As it's a resistive touchscreen, glitches during the GPIO reprogramming is non critical here.

Setting the GPIO as analog input seems missing here.

Hunt for something like:

#define GPIO_MODE_ANALOG            ((uint32_t)0x00000003)  /*!< Analog Mode */

#define GPIO_MODE_ANALOG_ADC_CONTROL      ((uint32_t)0x0000000B)  /*!< Analog Mode for ADC conversion */