Frequenza PWM

Con Fsys indico la frequenza a cui lavora l'Atmega328 dell'Arduino (16000000 Hz = 16 MHz).
Il prescaler è un divisore, non è il registro contatore del timer. Serve a dividere la frequenza di sistema per un fattore predefinito preso fra quelli disponibili (riportati sul datasheet). Nell'esempio abbiamo usato un fattore 8, quindi prescaler /8 significa clock di sistema diviso 8. Per cui all'uscita del prescaler la frequenza effettiva con cui viene aggiornato il timer diventa 16000000/8=2000000 Hz = 2 MHz.
Il contatore del timer è a 8 bit, quindi 256 valori massimi. Usando la modalità FastPWM per ottenere la frequenza si usa la formula che ti ho citato:
Fsys/(Presc*256)

Sappiamo che dobbiamo ottenere una frequenza finale di 25 KHz. Se noi usassimo tutti i 256 valori del contatore e la frequenza piena di clock otterremmo una frequenza di:
16000000/(8*256)=7812,5 Hz.
Non va bene. Però noi abbiamo ridotto la frequenza a 2 MHz usando un prescaler a 8.
Quindi da 2 MHz per ottenere 25 KHz dobbiamo usare un contatore di
2000000/25000=80

Ma il nostro registro può contenere 256 valori. Come fare? Semplicemente immettendo nel registro un valore di partenza, in modo da farlo arrivare prima all'overflow:
256-80=176

Quindi ad ogni overflow dobbiamo scatenare un interrupt che chiami una routine che aggiorni il contatore del timer.

Tradotto il tutto in codice devi scrivere le seguenti righe:

void setTimer2() {
cli(); //fermo gli interrupt
TIMSK2 &= ~((1<<TOIE2) | (1<<OCIE2A) | (1<<OCIE2B)); //disattivo tutti gli interrupt sul timer 2
ASSR &= ~(1<<AS2); //clock prelevato dal clock di sistema
//imposto il timer in modalità FastPWM
TCCR2A |= ((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
//imposto il toggle sul pin OC2A (pin D11 di Arduino)
TCCR2A &= ~(1<<COM2A1);
TCCR2A |= (1<<COM2A0);
//prescaler a /8
TCCR2B &= ~((1<<CS22) | (1<<CS20));
TCCR2B |= (1<<CS21);
TCNT2 = 176; //valore iniziale del timer
TIMSK2 |= (1<<TOIE2); //attivo un interrupt sull'overflow del timer2
sei(); //riattivo gli interrupt
}

//routine di overflow
ISR(TIMER2_OVF_vect) {
TCNT2 = 176; //reimposto il valore iniziale del timer
}

A questo punto attivi il generatore facendo un pinMode(OUTPUT) mentre per fermare il tutto metti un pinMode(INPUT).
Se hai un oscilloscopio o un DSO, prova e fammi sapere, non ho testato il codice perché non ho nessuno dei 2 apparecchi citati per controllare quindi ho scritto il codice di getto.