PIC: ottimizzare la velocità con il compilatore Hi-Tech C

PIC: OTTIMIZZARE LA VELOCITÀ CON IL COMPILATORE HI-TECH C

Ecco alcuni consigli su come ottimizzare la velocità di esecuzione del  codice  nella programmazione  dei microcontrollori  PIC:

  • La fase di inizializzazione del PIC è piuttosto lunga in termini di tempo di esecuzione; per aumentare al massimo la velocità è consigliato inizializzare per primi i registri nel bank 0 quindi quelli nel bank 1 e così via;
  • Ricordarsi che non tutte le variabili necessitano di essere inizializzare;
  • Ove possibile riordinare gli operatori aritmetici  in modo da minimizzare l’uso da parte del compilatore del registro W o di locazioni temporanee;
  • Per evitare inutili commutazioni di banco, utilizzare in una stessa operazione aritmetica variabili appartenenti allo stesso banco di memoria;
  • Se possibile preferire l’uso di variabili byte anziché word;
  • Se possibile utilizzare utilizzare puntatori  piuttosto che array indicizzati;
  • Una serie di  comandi  IF/ELSE  IF  spesso genera meno codice dell’equivalente costrutto case;
  • In  un  costrutto   switch/case,  preferire  numeri sequenziali consecutivi;
  • A seconda dei banchi di memoria coinvolti, i comandi
    var=valore1;
    if (!flag)
    var=valore2;
  • generano un codice più  ottimizzato  rispetto alla soluzione
    if (!flag)
    val=valore1
    else
    val=valore2;
  • La chiamata a funzioni  comporta  un impiego  di risorse piuttosto pesante per cui è preferibile sostituire con macro le piccole funzioni;
  • Nei cicli ripetitivi  è preferibile utilizzare un decremento della variabile di conteggio in quanto è più semplice verificare se una variabile in RAM ha raggiunto il valore nullo piuttosto che verificare che la stessa variabile abbia raggiunto un valore specifico. Si consideri infatti i due cicli FOR seguenti:
    unsigned char i;
    for(i=0;i<250;i++) azione();
    for(i=250;i!=0;i—) azione();

I due cicli eseguono la funzione azione() per 250 volte ma mentre il primo lo fa in 3,25ms (supponendo  un  quarzo a 4MHz),  il  secondo lo  fa in 2,5ms. I due cicli vengono infatti tradotti in assembler nel seguente modo:

for(i=0;i<250;i++) azione();
//esecuzione in 3251 cicli
1617 01B8 clrf 0x38
1618 260F call 0x60F
1619 0AB8 incf 0x38
161A 3008 movlw 0xFA
161B 0238 subwf 0x38,W
161C 1C03 btfss 0x3,0x0
161D 2E18 goto 0x618
for(i=250;i!=0;i—) azione();
//esecuzione in 2502 cicli
1621 3008 movlw 0xFA
1622 00B8 movwf 0x38
1623 260F call 0x60F
1624 0BB8 decfsz 0x38
1625 2E23 goto 0x623

 

  • Nel caso di gestioni di timeout piuttosto lunghi un primo approccio potrebbe essere quello di utilizzare un ciclo FOR nel seguente modo:
    unsigned int timeout;
    for(timeout=0;timeout<20000 timeout++)
    azione(); //380011 cicli
    for(timeout=20000;timeout!=0;timeout—)
    azione();//320011 cicli

è possibile ottimizzare  l’operazione nel seguente modo:

unsigned int timeout;
#define
hibyte(x) ((unsigned char)(x>>8))
#define
lobyte(x) ((unsigned char)(x&0xff))
//keeps lobyte(timeout)==0
timeout=(20000/0x100)*0x100;
for(;hibyte(timeout)!=0;timeout—)
azione(); //295704 cicli

questo accorgimento esegue il controllo solo sulla parte alta della variabile timeout controllando quando tale byte diviene nullo. Per la gestione del timeout il modo più efficiente è quello di utilizzare i timer interni del micro ed i relativi flag di interrupt.

  • Per effettuare divisioni e  moltiplicazioni per fattori che sono potenze di due, è consigliato utilizzare operazioni di shift a destra o sinistra anziché l’operazione di divisione o moltiplicazione  vera e propria. Questo, oltre a velocizzare il calcolo, permette di risparmiare da 13 a 23 byte di RAM.
Scarica subito una copia gratis

Una risposta

  1. Maurizio Di Paolo Emilio Maurizio 9 Maggio 2016

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend