In STM32, if a pin is set to Alternate Function in its GPIOx_MODER setting, and a connected peripheral is selected in the respective GPIOx_AFR[] field, the pin's digital input is connected to the selected peripheral's input (if the associated peripheral pin's function is input). Similarly, the associated peripheral's output (if there's any) is connected to the pin's output driver.
There are two output signals, though, going from peripheral to GPIO: output level and output enable. The peripheral controls both. Usually, when the peripheral's clock is disabled in its respective RCC_AxBx_ENR, output enables for the peripheral's outputs are also disabled - this functionality is not properly documented, though, so cannot be relied upon, but has to be taken into account as a possibility. In some peripherals, outputs' enables are disabled when peripheral's "global enable" bit is cleared.
Some peripherals even have explicit output enable bit/bits - e.g. in timers, TIMx_CCER.CCxE/CCxNE function in this way, and in Advanced timers, the whole BREAK-related circuitry is geared towards output enable/disable.
Some library functions are aimed at delivering functionality which has a definitive duration, e.g. a function for communication interface may transmit a single packet. Some of those functions, after having accomplished their action, simply switch off the given peripheral. There also may be interface functions which are directly aimed at "stopping" a given peripheral. All these may result in output pins assigned to given peripheral to be threestated.
And, as such, they may change their state after some time, depending on associated leakages and parasitic capacitancies. Usually, voltage on them slowly decrease, but that's not necessarily always so. If there's strong enough crosstalk from a neighbouring track, the signal may even oscillate.
This may result in surprising behaviour of connected external peripheral, as signal which is output from a mcu usually controls some functionality, or serves as a clock.
There are several remedies to this issue:
- don't use library functions which switch off given functionality
- use internal or external pullup/pulldown (considering the parasitics and also increase of consumption while output is active)
- use such functionality of controlling peripheral which does not result in threestating, e.g. if in timer one desires to stop PWM output, some of the "set on match" or "forced" modes of Output Compare can be used instead of switching the channel off in TIMx_CCER
- before switching off the peripheral, change the given pin to Output in respective GPIOx_MODER, with output state in GPIOx_ODR set to the desired "idle" level