Assuming your microcontroller has a PWM module, then it's quite simple. You need to read the datasheet and set up your module accordingly, then load the appropriate values into the duty cycle (usually "compare") register. Here's a rough example:
You set up a timer for your desired (fixed) PWM frequency, then alter a register to change the ON/OFF time in this period.
Say you have a 10-bit PWM module. 10 bits = 2^10 = 1024. So for 50% duty cycle you need to load 512 into the register, for 25% 256 and so on (the specific operation of your PWM module may be a bit different)
Then you add a low pass filter (simple RC filter usually will suffice) in front of the PWM to average out the PWM and produce a varying DC voltage:

For the filter you need to make sure the PWM frequency is attenuated greatly, leaving the lower frequencies - since you say all you need is DC, then something like R = 10k C = 0.1uF will do. This will create a cut off of 1 / (2pi * 10k * 0.1uF) = 159Hz. Pick a PWM frequency well above this (e.g. 10kHz)
I noticed the AVR tag - I don't use AVR (so I cannot vouch personally for the below information) but I googled and found a couple of pretty good tutorials:
Aquaticus PWM guide
AVR Freaks PWM guide
PWM sine wave example
In case you don't want to use the PWM module (or need PWM on a specific pin) here's some "soft" PWM code:
// The following two ISRs are doing "poor man's PWM"
// but this allows it to be on a pin of my choice
ISR(TIMER0_COMP_vect) {
// clear the output pin on OCR0 match
PORTC &= ~(1<<PC0);
}
ISR(TIMER0_OVF_vect) {
// set the output pin at timer overflow
PORTC |= (1<<PC0);
}
int main(void) {
// going to use PORTC.0 to PWM the contrast voltage
DDRC = (1<<DDC0);
TIMSK |= ((1<<OCIE0) | (1<<TOIE0)); // use both interrupts
OCR0 = 10; // 10 out of 256 means very short on period (low voltage)
TCCR0 = (1<<CS00); // timer on - nice high PWM frequency
// Might later consider PWMing the backlight voltage too
// so it would also be adjustable ...
sei();