2020-09-21 12:26 AM
I need to be able to toggle between 3V and 5V per pin for about 40pins. i.e command output_high_3V would get 3V etc. I am not sure the best way to go about it since STM32 are only 3V3 pins. I was thinking of using GPIO Expanders, or some transistor,diode,resistor array configuraiton to pass in the 5V. But I figure I asked first before adding additional circuitry to my design. Maybe there is a chip for this?
2020-09-21 01:01 AM
"Best" depends on the price / complexity (in terms of both hardware and software) / timing / impedance requirements. You haven't explained enough for us to make those judgements.
Output expanders require commands to be sent to them. These commands take time so you wouldn't want to block an interrupt handler waiting for one of them to happen. You might then choose to have a queue for storing these commands, but then you don't have full control of the precise timing.
Do you actually need 3.0 V? If so, hardware will be much simpler if your Vdd also happens to be 3.0 V. Stm32 are happy to run at that voltage.
Do you ever want to do anything other than output 3.0 V and output 5.0 V? If not, a level-shifter or opto-isolator type approach might work.
How hard do you need to drive to 5.0 V? For something like I2C, a pull-up resistor to 5.0 V is often satisfactory. That might work for you, depending on many factors. You could achieve 0.0 V by driving the output to logic 0, Vdd by driving the output to logic 1 and 5.0 V by changing the pin to digital input. But all the time it's not 5.0 V, you'll be burning current through that resistor. And the rise / solidity of the 5.0 V also depends on the value of the resistor.
Hope this helps,
Danish
2020-09-21 06:41 AM
If it's a global setting, I'd use a level shifter and then control the input voltage to that shifter.
2020-09-21 12:22 PM
This is helpful @Danish and @TDK I'll reach out if I have any more questions.
2020-09-21 01:57 PM
Pins are always using the STM32 Vddio voltage (usually Vdd 3.3V).
A 5V tolerant pin means that the pin can be under the right circumstances be connected as an input from a 5V device without harm to the STM32. The exact tolerance levels on the 5V tolerant pins is found in the electrical specifications section of the datasheet for your chip. For example one that I look at right now says "Vin Input Voltage on FT_xx min -0,3 max Vdd+4.0, To sustain a voltage higher than 4 V the internal pull-up/pull-down resistors must be disabled."
If the STM32 is to drive the pin as an output to the other device then you need to verify that the other device handles the output levels from the STM32 correctly. Often it works fine to connect a 3.3V 5V tolerant device to a 5V device, but you need to verify I/O levels carefully to ensure there is sufficient margins on a logical one, especially in the direction 3.3V -> 5V. If in doubt then use a level shifter to ensure that I/O levels are compatible.
2020-09-21 02:13 PM
Sorry, misread the question slightly, thought you were talking about native GPIO pins.
I fully agree with @TDK on the use of a shift register with variable supply.
Or if you need to vary the pins individually then a more complex design is needed, for example using two SPI GPIO 5V tolerant expanders in parallell with different supply and individual tri-state control per pin. For 3.3V you drive the output pin on the 3.3V powered GPIO expander, for 5V output you drive the output pin of the 5V powered GPIO expander. For safety add a small resistor in series on the 3.3V GPIO expander outputs just in case you activate both drivers at the same time, if your current drive requirements allows.
The above can also be done using two 5V tolerant shift registers with output enable signal, but then for all pins of that shift register group. But can be done more safely this way by using an inverter, making sure that OE of one is always the inverse of the other.
2020-09-21 02:21 PM
If you don't need a high speed GPIO, you can configure GPIO pins as Open-drain (GPIO_MODE_OUTPUT_OD). That way, GPIO output MOS will just pull output to ground when you write a 0 (RESET), and will float when you write 1 (SET).
Then, you can tie some pull-up resistors between +5V and GPIO pins (make sure you are using 5V torelant pins). Be aware about 0 to 1 rise time, as it will be quite slow due to pull-up. Also check GPIO pin max drain current when you calculate pull-up resistor.
2020-09-21 08:06 PM
Hey guys @VictorPr @Henrik Nordström @TDK @Danish. The problem is that these 40 pins go under fast switching from Input high pullup to input no pullup hundreds of times per second. I don't know if any of these configurations would work. There are three steps here, the first step being all 40 pins under go rapid cycling from input high pullup and then input no pullup. After first phase, mcu determines which pins actually need to cycle about 24-32pins, with the renaming 8-16 pins not used. In the second phase we need to determine a output high and output low configuration of the remaining of the unused pins, with some needing 3v and some needed 5v. After this phase, 24-32 pins will continue to cycle for ever while the remaining 8-16 pins will not do anything or some will be output high at 3V or 5v and some will be output low permanently . I was thinking connecting a gpio expander pin with a diode to each pin for the mcu, when in the second phase I can try output high from the mcu for 3V and if that doesn't work then output high 5V from the expander, would that work is there an alternative?
2020-09-22 12:39 AM
Ok so that's a bit more detail you've given us. The more you give us, the better we can suggest approaches.
You want to be able to do input-with-pull-up and input-without-pull-up as digital output.
"Hundreds of times a second" isn't necessarily difficult for any of the suggested approaches. But you might need to think carefully as to whether all the lines need to be switching at precisely the same time, or whether it is acceptable to have them all switching at that frequency but e.g. pin A happens to switch a few microseconds before pin B.
My guess is that you have some form of automatic configuration of your system no matter how it might be connected to some external device(s). We can help you more if you tell us what the possible electrical characteristics of the connections to your external device(s).
Some points: If you're driving LEDs, and you want to drive them in excess of 10 mA (even for short pulses), you are likely to find the stm32 GPIO pins are inadequate as outputs.
If you need to drive more than 1 mA at +5 V, then external pull-up resistor to a +5V rail is probably not sufficient to drive it to that level.
2020-09-22 06:13 AM
The dual GPIO expander option I meantioned earlier will do this easily for up to several kHZ update frequency and can generally drive output of about 10mA per pin (depending on the selected GPIO expander specifications), and also reduces the number of pins required on the STM considerably.
Using a mix of a GPIO expander or shift register with diode in combination with 5V tolerant GPIO pins on the STM as you mention is also an option. But I am not 100% sure that the pins are 5V tolerant in output mode so you better be careful that no STM pins are in output mode if the pin is at the same time driven internally or externally to 5V. Adding current limiting resistors on the STM pins helps, but limits the drive capacity in 3V operation.
No diode is needed with GPIO expander, those can generally do input/push/pull all in one pin with high impedance in input mode. And with an series resistor they can operate as fully configurable pull up/down (high impedance input = no pullup/down. output high = pullup, output low = pulldown)