Pin value of a GPIO pin set as high impedance
You have configured your pin correctly. The pin is in high impedance mode and will just have the leakage current as input current (in the order of microamperes).

Reading the value of the pin will give you the logical value of the voltage applied to the pin. The voltage levels which correspond to a 0 or 1 are available in the devices datasheet.



For example for the STM32F401 a voltage of up to (maximum) 0.35*VDD-0.04 V will be considered low or 0.

A voltage of at least 0.4*VDD is considered high or 1.

So if you supply your device with 3.3V everything on the pin up to 1.115 V will be considered a 0 and everything over 1.32 V will be considered a 1.

However, to prevent the pin to toggle rapidly between the two states there is a hysteresis of 0.45*VDD+0.3 V. So in order to switch between the two states you need a larger voltage change than just the difference between 1.115 V and 1.32 V.



Now if you have an unconnected pin and read the value of the input register, the value is basically undefined. It could be either 0 or 1 depending on a lot of factors, adjacent pin voltages, EMI and others.

The pin and connected track basically act as an antenna. Thus it picks up all sorts of signals and as only a tiny charge is required to bring the voltage from 0 levels to 1 levels it will switch between them readily. This is dependent on the capacitance of the track and pin, without added capacitors it is in the range of some picofarads, which can easily be charged and influenced.

This makes your controller susceptible for external disturbances. This can lead to erratic behaviour in case of strong EMI (hold a calling mobile phone near your microcontroller), some devices react a lot more sensitive so even waving your hand over it might disturb it.

Because of that it is considered a best practice to have some form of active drive on each input pin. Either the external circuit makes sure that it has a defined level all the time, or a pull-up or pull-down resistor is used. Most microcontrollers have built-in resistors, so external components are not necessary.

To enable the pull-up or pull-down resistor on a pin, you can use the GPIO_InitStruct.Pull. Set it to GPIO_PULLUP or GPIO_PULLDOWN respectively. Which one is the correct one depends on your application, typically if you are waiting for a high signal you would enable the pull-down to make sure you don't get an accidental high signal. This would also provide a reliable reading if the pin is not connected.

Unused pins can also be configured as output if left unconnected to prevent the bad effects.

Note: If you want to make a pluggable design you should think about additional ESD protection for the pin.