Generating simple alert tone MCU project
You can use PWM to produce audio tones in (at least) two ways.

The first, and simplest, solution is to use a PWM module to produce a square wave (with duty cycle 50%) at the desired frequency of the tone.  It is usually desirable to then pass the square wave through a low pass filter to round the corners off (resulting in a "cleaner" sound) by removing the upper harmonics.  If you want to mix tones using this method then you need to use one PWM module and LPF per tone, and post-mix them with an op-amp.

The second, more complex and ultimately more satisfying, solution is to use a PWM module as a DAC and drive it with a software Direct Digital Synthesiser (DDS) to generate as many mixed tones as you want (within the limits of your available processing power).

To use a PWM as a DAC, drive it at the highest possible frequency, preferably well over 20kHz to ensure that any spectral artifacts not removed later are outside the normal human hearing range (nominally up to 20kHz).  When you feed the high-frequency PWM through a LPF with corner frequency around 5-8kHz, the output amplitude of the LPF, as a percentage of rail voltage, will approximate the duty cycle of the PWM signal fed to the LPF.  For example, with a rail voltage of 5V and a duty cycle of 50%, the output of the LPF will be approximately 2.5V.

The DAC output can be modulated by varying the duty cycle of the PWM.  To modulate it with a sine wave of a given frequency, the "lowest cost" approach is to use a lookup table that contains a set of pre-calculated fixed-point duty cycle values that map a sine wave and can be fed to the DAC.  The lookup table needs to cover only 1/4 of the period of a sine wave because you can use reflection to reconstruct the other 3/4 of the wave from the first 1/4.  The rate at which you feed the sine lookup table into the PWM module governs the output frequency of the audio it produces.  So, an 8-point lookup table (so, 32 points for the entire sine wave) used to update a PWM signal at a 20kHz rate will produce an audio tone of 20,000 / 32 = 625Hz.  This is a software DDS.

If you want to combine multiple tones into the DDS, you need to provide a substantially higher resolution lookup table.  Where before 8 points (or even 4 points) for a 1/4 wave was adequate, you are now looking at 128, 256, even 1024 if you want good resolution.  To vary the frequency of the modulated output, step through the lookup table at different rates for each tone.  So, for the 625Hz example above and a 1024-point table, you would increment the table pointer by 128 on each update.  If you want to add a second tone, at say 1600Hz, you would increment a seperate pointer by 1600/625*128 = 328 (giving an actual frequency of ~1602Hz).  Add the two values extracted from the table together, add a DC offset, and feed the result to the PWM module at a 20kHz rate and it will output an audio signal containing both tones.

In order for either DDS approach to produce "nice" tones, you need to pay careful attention to the PWM update timing.  Jitter minimisation is the key.  Use a high-priority interrupt to do the updates, and (here's the key) pre-calculate the next update before you leave the interrupt service routine.  When you arrive in the ISR next time, immediately feed the PWM module with the pre-calculated update value, then calculate and store the next update value.  This should ensure that the amount of time between the ISR firing and the update being fed to the PWM module is constant.