possibile soluzione per la consegna sul PWM via polling
Se dobbiamo operare a 100KHz significa che il ciclo PWM si ripete ogni 1 / 100000 = 0.000010s = 10micros = 10us.
Siccome vogliamo parzializzare su 256 livelli significa che il tempo minimo in cui dobbiamo tenere acceso il pin di uscita è 1/256 di 10us = 0.0390625us = 39ns (per valori di dutycicle maggiori di 1/256 dovremo semplicemente tenere acceso il pin per un tempo maggiore).
Dover agire a controllo di programma significa che:
- la mcu inizializza una variabile dutycicle che specifica quante volte ripetere un ciclo di attesa, basato sulla durata del clock del processore e sul numero di cicli di clock richiesti per le istruzioni del ciclo stesso,
- accende il pin (scrive 1 nel bit del registro periferica la cui out è il pin di uscita),
- entra in ciclo a condizione iniziale che risulta falsa la prima volta,
- incrementa contatore e salta al test sulla condizione iniziale, che risulta vera,
- esce dal ciclo e spegne il bit del registro periferica.
Quindi il software potrebbe avere una struttura come la seguente:
dutycicle = valore; contatore = 0; accendibit; while(contatore < dutycicle) contatore++; spegnibit;
In "assembly mips" (noi in realtà abbiamo un arm) potrebbe essere qualcosa del genere, considerando ad esempio di avere in $a0 il dutycicle ($a0 è registro contenente il primo parametro, dutycicle, di ingresso della procedura) ed in $a1 l'indirizzo del registro dati della periferica ($a1, secondo parametro di ingresso della procedura):
move $t0,$zero #contatore = 0 li $t1,0x000000ab #supponendo che il registro periferica sia da 8bit, #questo immediato ha ad 1 il bit che ci interessa #sia ad 1 affinché si accenda l'uscita periferica li $t2,0x000000cd #supponendo che il registro periferica sia da 8bit, #questo immediato ha a 0 il bit che ci interessa #sia ad 1 affinché si accenda l'uscita perifericasb $t1,0($a1) #accendibit ciclo: bne $t0,$a0,esci addi $t0,$t0,1 j ciclo esci: sb $t2,0($a1) #spegnibit
Pertanto nell'effettuare un ciclo vengono eseguite 3 istruzioni (bne, addi, j); supponendo per semplificare che richiedano tutte 4 cicli di clock, si deduce che per effettuare un ciclo si impiegano 12 cicli di clock. Se vogliamo che 1 ciclo duri 39ns, bisogna che la durata del ciclo di clock sia almeno 39 / 12 = 3.25ns ovvero la frequenza del clock sia almeno 1 / 3.25ns = 307692307Hz = 307.692307MHz
Per valori di clock maggiori (periodi inferiori) sarà necessario incrementare il contatore di un valore superiore ad 1.
Si tratta comunque di una soluzione approssimata in quanto lo spegnimento avviene dopo i cicli di clock della istruzione sb di spegnimento, la grana minima gestibile è la durata dell'esecuzione di un ciclo con un certo valore del clock del processore, che non è detto che coincida con il valore desiderato (39ns), etc.