I work on a project that need 36 PWM signal to drive 36 MOSFETs. Can I use a microcontroller with a limited number of PWM and configure all pins as PWM output or do I need to find a microcontroller with 36 PWM pins?
First of all
So, can I use a microcontroller with a limited number of PWM and configure all pins as PWM output
you can not configure every MCU pin as PWM output. Physically controlled PWM output must be controlled by a timer. But you can set MCU as GPIO output pin and control it by software.
It may be hard to find MCU with 36 PWM outputs. So if PWM frequency isn't very high you can implement SOFTWARE PWM using one or more timers. Also as a solution, you may use MCU and shift registers to drive 36 PWM outputs. But in this case, driving speed of Shift Register must be high enough. I have used this solution for driving LEDs at low PWM speed just about 100 HZ.
You can select MCU from STM32 series with many timers. But this will bring extra expenses.
I don't know if your use case allows for it, but consider not using PWM at all, as hardware PWM with 36 individual outputs is a bit impractical.
You could try software PWM, but even then you would likely have problems toggling each pin at the right time in worst case scenarios (like multiple pins set to near identical values), due to the interrupt processing time.
Instead of PWM, you could output the most significant bit of all duty cycle values to the respective pins, simultaneously. Then you'd output the second-to-most-significant bits, and so on. Each set of bits in the sequence would be applied to the outputs for a time T proportional to 2N, where N is the ordinal number of the bits (e.g. the least significant bits for 10μs, the next ones for 20μs, then 40μs and so on). Although not strictly PWM, this scheme allows for modulating the average amplitude of dozens of outputs very cheaply.
Here's a simple example of four outputs controlled by 4-bit duty cycle values, but the concept scales very well for more outputs. The bits don't necessarily have to be output in any specific order, as long as they are applied to the outputs for the proper duration.
You'd probably have an array of individual duty cycle values for each output in your code (e.g.
uint8_t dutyCycle), which you need to transpose (make rows into columns and vice versa) into an array of output states (like
uint64_t outputStates or
uint8_t outputStates), so that you can output them to the I/O registers.
Here's the operation done on the previous example:
There are a few ways to do this bitwise transpose efficiently, probably better explained by hacker's delight