umbez: " utilizzare due processori, uno per l'unità di controllo e un nano per l'unità dro"
lo trovo uno spreco di risorse inutile. I timer chiamano interrupt specifici che devi comunque usare per aggiornare la frequenza del PWM e nei quali puoi anche tenere traccia della posizione, non ha senso usare un altro micro esterno per fare una cosa così banale.
Davide:"per programmare in asm o lo fai tutti i giorni o, se lo fai di rado, non ti passa più ..."
Diciamo piuttosto che al massimo lo potevi fare tutti i giorni negli anni 80, e forse qualcuno pure nei 90, ma oggi credo che i programmatori di ASM siano tutti in pensione o peggio, passati a miglior vita

Programmare un microcontrollore (o qualsiasi altra cosa) in ASM al giorno d'oggi con la complessità che abbiamo è un'impresa titanica...
raunarde, la SetPWM() serve a impostare il timer e la relativa uscita come fast PWM mode. Quel pin (e il timer associato) lo puoi usare in diversi modi, nel firmware del ELS lo uso essenzialmente in due modi diversi:
FastPWM: per gli avanzamenti, quando mi serve portare il motore a una certa velocità conmtrollata, tenendo traccia della posizione ma senza vincolare in modo preciso il motore stepper all'encoder
SingleShot: per le filettature, ovvero quando mi serve avere un controllo preciso e puntuale del passo da dare alla vite. Nella modalità SingleShot il PWM genera un impulso di step solo e poi si ferma. La uso per non impegnare il micro con delay quando devo eseguire un passo. In pratica l'operazione che tu eseguivi nel tuo codice alzando il pin, aspettando e poi abbassandolo di nuovo. La differenza sostanziale è che io do un'istruzione ( FireStep(), nello specifico ) e pensa lui a dare un impulso della durata corretta senza che questo sia bloccante per il codice. Per usare questa modalità lancio prima la funzione di configurazione SetOneShot() in alternativa a SetPWM(). Se ti scarichi il mio codice del ELS e ti studi la pirma parte (quella nella scheda principale) capisci meglio il tutto.
Tornando alla modalita Fast PWM, che è quella che più ti interessa, per variare la frequenza vario il valore della variabile TOP. Questa varibile viene caricata nel registro di comparazione del Timer ad ogni interrupt, dando la possibilità di variare la frequenza ad ogni ciclo. Se non varia verrà caricato lo stesso valore e la frequenza resterà costante. Questa variabile è un intero senza segno a 16 bit, quindi con valore compreso tra 0 e 65535. Se il valore è basso la frequenza è alta, se il valore è alto la frequenza è bassa. Quindi la minima frequenza la avrai con TOP = 65535, la massima con TOP = 0 (non proprio a 0 perchè altrimenti non va visto che non ha il tempo di dare nemmeno il singolo impulso). In pratica TOP è il valore di partenza del Timer con conterà alla rovescia dal valore che imposti a 0. Il pin di uscita cambierà di stato quando il valore del Timer incrocia quella del resistro OCR1A che io ho impostato a 3 quindi cambierà di stato nuovamente quando il Timer arriva a 0. Il valore di OCR1A ti da quindi la durata dell'impulso di step.
Un po' di matematica per fare chiarezza: con prescaler impostato a clk/64 la frequenza del singolo impulso sarà appunto quella del clock (16Mhz) / 64 = 250Khz. Quindi il tuo timer farà 250000 "scatti" al secondo. Essendo che il Timer conta fino a 65535, avrai quindi 3,81 cicli di Timer completi in un secondo. Se imposti quindi TOP = 65535 avrai 3,81 step del motore al secondo. Partendo da qui ti puoi calcolare gli step al secondo per ognuno dei valori di TOP, sapendo che comunque la velocità minima sarà quella qui sopra calcolata, ovvero 3,81step/secondo....