CONVERTIRE UN NUMERO BINARIO AD 8 BIT IN DECIMALE CON PIC16F873A
Quello che presento in questa pagina è un semplice programmino in assembler che converte un numero binario ad otto bit in uno decimale a tre cifre, ovviamente tale lavoro è stato fatto esclusivamente per fini didattici ma ciò non toglie, a chi ne avesse la volontà, di migliorarlo per convertire numeri binari più grandi. A tale scopo il volenteroso dovrà usare un processore con più memoria dati o usare quella flash riservata al programma oppure usarne una esterna, in ogni caso, una volta compreso il funzionamento del mio programmino, è abbastanza semplice modificarlo per una maggiore performance.
Per la spiegazione farò uso del simulatore incorporato in MPLAB Ver.8.92, ma ne va bene uno qualsiasi di vostra appartenenza, l’importante è che esso dia la possibilità di visualizzare la memoria dati in maniera chiara e coerente, per rendere il lavoro più tangibile, alla fine della pagina, fornirò un programma che oltre a possedere le routine presenti in questo ne avrà altre in modo che sia possibile immettere le cifre binarie tramite dei tasti e visualizzarle, come il risultato in decimale, su di un display 16X2.
Bene iniziamo.
Un numero decimale può essere rappresentato come la somma dei prodotti delle cifre del numero stesso per potenze decrescenti di 10, ad esempio il numero 1234 (milleduecentotrentaquattro) è rappresentato come segue:
[1]
(si ricorda che un numero elevato alla zero da sempre e soltanto uno)
Gli esponenti di 10 valgono la posizione della cifra nel numero, per le unità (cifra 4) è pari a 0, per le decine (cifra 3) è pari a 1, per le centinaia (cifra 2) è pari a 2, per le migliaia (cifra 1) è pari a 3, e così via.
Lo stesso discorso si può applicare ad un numero binario sostituendo le potenze di dieci con quelle di due ottenendo una rappresentazione in decimale.
Esempio il numero binario 10111 è rappresentato come segue:
[2]
Come si può vedere la suddetta rappresentazione altro non è che una conversione tra binario e decimale, questo ci fa intendere che se riuscissimo a far sommare quei valori decimali al processore otterremmo il nostro convertitore, ma dato che questo microcontrollore non può eseguire direttamente operazioni matematiche in decimale occorre trovare un modo un pochino più complesso per fargli fornire il risultato, il mio è questo che segue.
Faccio scrivere al programma una serie di numeri in tre locazioni di memoria dati distinte; la prima per le unità, la seconda per le decine, la terza per le centinaia. Ovviamente occorrono solo tre locazioni dato che per rappresentare un numero binario ad 8 bit servono solo 3 cifre decimali (11111111 = 255). Ma quanti numeri bisogna immettere in queste locazioni? Per saperlo occorre sommare prima tutte le unità, poi le decine più il riporto delle unità, poi le centinaia più il riporto delle decine, in poche parole una semplice somma della rappresentazione [2] del numero binario a 8 bit però al massimo valore, ovvero 11111111:
Quindi per le unità:
[3]
Il numero di locazioni di memoria dati da riservare alle unità è quindi 35 più lo zero che da un totale di 36 locazioni, si noti che la cifra 3 del numero suddetto è il riporto che andrà aggiunto al numero delle locazioni per le decine.
Per le decine:
[4]
Il numero di locazioni di memoria dati da riservare alle decine è quindi 12 più lo zero più il riporto delle unità danno 16 locazioni, si noti che la cifra 1 del numero suddetto è il riporto che andrà aggiunto al numero delle locazioni per le centinaia.
Per le centinaia:
[5]
Il numero di locazioni di memoria dati da riservare alle decine è quindi 1 più lo zero più il riporto delle decine danno 3 locazioni. Abbiamo così determinato il numero più alto che potrà essere usato per ogni cifra, come nella tabella sottostante.
CENTINAIA |
DECINE |
UNITA’ |
0 |
0 |
0 |
1 |
1 |
1 |
2 |
2 |
2 |
|
3 |
3 |
|
4 |
4 |
|
5 |
5 |
|
6 |
6 |
|
7 |
7 |
|
8 |
8 |
|
9 |
9 |
|
10 |
10 |
|
11 |
11 |
|
12 |
12 |
|
13 |
13 |
|
14 |
14 |
|
15 |
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
|
|
23 |
|
|
24 |
|
|
25 |
|
|
26 |
|
|
27 |
|
|
28 |
|
|
29 |
|
|
30 |
|
|
31 |
|
|
32 |
|
|
33 |
|
|
34 |
|
|
35 |
Si può notare che se si prende la prima cifra dell’ultimo numero delle tre colonne si ottiene 255 corrispondente al numero massimo convertibile, ovvero 11111111 = 255.
Si vedrà che per avere il risultato non occorrerà far fare somme di numeri decimali al processore ma sarà sufficiente fargli contare le locazioni per un numero di volte corrispondente alle potenze di due (tenendo conto del riporto che come si vedrà darà ancora qualche problemino).
Facciamo qualche esempio, proviamo a convertire in numero binario 101, allora:
[6]
Avremo solo le unità, contando (saltando come ci facevano fare nelle elementari) nella prima colonna a sinistra si otterrà proprio 5.
Atro esempio:
[7]
Per le unità dobbiamo contare nella corrispondente locazione per:
[8]
Ovvero conteremo fino alla locazione 25 nella prima colonna a sinistra, l’unità di questo numero è anche l’unità (il 5) del risultato, la decina (il 2) è il riporto che va sommato ai conteggi nella colonna delle decine.
[9]
Più il riporto:
[10]
Ovvero conteremo fino alla locazione 7 nella colonna centrale, l’unità di questo numero è la decina del risultato. In questo caso non si ha riporto per le centinaia.
Dato che le decina non ha riporto le centinaia sono semplicemente:
[11]
Ovvero conteremo fino alla locazione 1 nella colonna a sinistra, l’unità di questo numero è la centinaia del risultato.
Quindi leggendo solo le unità dei numeri posti nelle suddette locazioni da sinistra a destra otterremo il numero 175 ovvero il risultato decimale della conversione.
Abbiamo però un problemino. Come fa il processore ad estrarre i vari riporti da una cifra decimale? Per esempio come fa il processore ad estrarre la cifra 2 dal numero 25 dato che questo in binario è 11001 e anche dividendo il byte in due nipples otterremmo 0001 1001 che corrispondono alle cifre 1 e 9 che sono diverse da 2 e 5. Si risolve il problema memorizzando nelle tre locazioni non numeri decimali ma esadecimali avendo l’accortezza di scrivere dopo il 9 esadecimale il 10 esadecimale, dopo il 19 il 20 e così via. Ora questi numeri possono essere discriminate dal processore, ad esempio il numero 25 esadecimale è composto da due nipples binari che corrispondono rispettivamente proprio a 2 e a 5. Dato che il processore non fa nessun calcolo matematico decimale ma somma solo gli indirizzi delle locazioni di memoria, il fatto che i valori memorizzati in esse siano esadecimali anziché decimali non cambia nulla ai fini del risultato.
In fig.1 sono raffigurate le tre locazioni di memoria più le tre celle per il risultato (in questo caso 42). Quelle circondate da linee rosse sono riservate all’unità, quelle da linee gialle alle decine, quelle da linee blu alle centinaia e infine quelle da linee arancioni al risultato.
Fig.1
PROGRAMMA
Il numero binario da convertire va inserito nel registro VALORE fig .2
Fig.2
Successivamente le istruzioni di fig.3 servono a memorizzare i valori in esadecimale nelle tre locazioni di memoria. Faccio uso dell’indirizzamento indiretto; nel registro FSR va messo l’indirizzo della locazione e nel registro INDF il dato nella quale andrà
messo.
Fig.3
Nelle istruzioni raffigurate in fig.4 si carica nei registri CIFRA_X gli indirizzi iniziali delle tre locazioni.
Fig.4
Nelle successive istruzioni si effettua un incremento degli indirizzi solo per le cifre uno del numero binario (gli zero non portano ovviamente a nessun incremento dato che qualsiasi potenza di due moltiplicata per zero da sempre zero) fig.5.
Fig.4
Ad esempio se la cifra al terzo posto da sinistra del numero binario è uno allora il programma chiama la routine BINARIO_2 dove viene incrementato l’indirizzo di tante volte quanto è la potenza di e così per tutte le altre.
Quando il programma ha controllato tutte le cifre binarie avremo i vari incrementi memorizzati nei registri CIFRA_X (per il momento senza riporto).
Successivamente l’indirizzo delle unità viene copiato nel registro FSR e tramite il registro INDF il dato in DATO_X.
Il dato viene poi riversato nel registro MOMENTANO e da qui estratta la cifra delle decine tramite maschera AND e scambio dei nipples; la cifra così ottenuta andrà a incrementare (se c’è riporto) il registro successivo CIFRA_X e con questo estrarre la cifra delle decine e così via fino alle centinaia. Alla fine avremo nei tre registri DATO_X le tre cifre decimali del risultato dopo averli ripuliti con maschera and dal riporto fig.5.
Fig.5
Qui di seguito i file in asm:
Fabio