Come vengono gestiti i numeri con punto decimale in un MCU?


8

Per favore, dimmi come fanno gli MCU a gestire i numeri decimali come '23 .3 ',' 3.24 'ecc.? Come viene archiviato in un registro di memoria? So che devo usare il tipo di dati float quando gestisco questi numeri durante la programmazione. Ma in realtà ciò che sta accadendo all'interno di un MCU durante la gestione di questi tipi. Dimmi anche come fanno le MCU senza unità FPU a gestire il tipo di dati Float.

Risposte:


13

I numeri all'interno dei tipici microcontrollori non hanno affatto punti decimali. Sono numeri interi binari. Non ci sono decimali all'interno della macchina. Il compilatore o l'assemblatore può consentire di specificare le costanti in questo modo, ma vengono convertiti in binari prima che la macchina li veda.

Tuttavia, puoi decidere quali unità desideri per i valori interi. Ad esempio, supponiamo di voler rappresentare dollari all'interno di un micro. Non può fare nativamente $ 3,21, ma potrebbe fare 321 centesimi. Il micro funziona solo sul valore 321, ma sai che rappresenta unità di 1/100 di dollari.

Questo è solo un esempio per illustrare il concetto di unità arbitrarie. Spesso i numeri sono rappresentati con diversi bit di frazione binari. Ciò equivale a dire che ogni conteggio rappresenta un valore di 2 -N , dove N è il numero di bit di frazione. Questa rappresentazione si chiama "punto fisso". Decidi in anticipo di quanta risoluzione hai bisogno e fai finta che ci siano abbastanza bit a destra del punto binario immaginato per supportare quella risoluzione. Ad esempio, supponiamo che devi rappresentare qualcosa con almeno una risoluzione di 1/100. In tal caso useresti almeno 7 bit di frazione da 2 7 = 128. Questo ti darà effettivamente una risoluzione di 1/128.

La macchina non ha idea che stia succedendo. Aggiungerà e sottrarrà questi numeri come numeri interi ordinari, ma tutto funziona ancora. Diventa un po 'complicato quando si moltiplicano e si dividono i valori in punti fissi. Il prodotto di due valori in virgola fissa con bit di frazione N avrà bit di frazione 2N. A volte tieni semplicemente traccia del fatto che il nuovo numero ha bit di frazione 2N, oppure a volte puoi spostarlo a destra di N bit per tornare alla stessa rappresentazione di prima.

La virgola mobile è la stessa cosa, ma il numero di bit di frazione viene memorizzato insieme alla parte intera in modo che questa regolazione possa essere effettuata in fase di esecuzione. L'esecuzione di operazioni matematiche su numeri in virgola mobile può richiedere diversi cicli. L'hardware in virgola mobile fa tutto questo per te in modo che le operazioni vengano completate rapidamente. Tuttavia, le stesse manipolazioni possono essere eseguite anche nel software. Non c'è motivo per cui non è possibile scrivere una subroutine per aggiungere due numeri in virgola mobile, solo che ci vorrebbe molto più tempo che l'hardware dedicato esegua la stessa cosa.

Ho definito un formato a virgola mobile a 3 byte per PIC a 8 bit e ho scritto un sacco di routine per manipolarli. I microcontrollori di solito hanno a che fare con valori del mondo reale con una precisione di 10 o 12 bit al massimo. Il mio formato a virgola mobile utilizza 16 bit di precisione, che è abbastanza buono per diversi calcoli intermedi.

Ho anche un formato a 32 bit per i PIC a 16 bit. Questo utilizza una parola a 16 bit per la mantissa, che accelera i calcoli poiché questi PIC possono operare su 16 bit alla volta.

Queste routine sono incluse nella mia versione degli strumenti di sviluppo PIC . Dopo l'installazione, guardare i file con "fp24" nel loro nome nella directory SOURCE> PIC e "fp32f" nella directory SOURCE> DSPIC.


Standard a virgola mobile Esiste anche uno standard IBM che ha appena rovinato il bias.
NickHalden,

4

L'aritmetica a punto fisso viene solitamente utilizzata per eseguire calcoli frazionari nelle MCU.

Il trucco è dire che (per esempio), i 16 bit superiori di a uint32_tsono prima del punto decimale e i 16 inferiori sono dopo, cioè. il numero intero memorizzato è in 1/2 ^ 16 secondi. Con alcuni piccoli avvertimenti, l'aritmetica regolare "funziona".

Ecco una panoramica .


voto da parte mia per quel link "Panoramica".
0xakhil,

3

A meno che l'MCU non sia un DSP con moltiplicatore in virgola mobile, tutto viene archiviato come numeri a 16 bit (o 8 o 32 a seconda della piattaforma). Questo è tutto ciò che l'MCU attuale conosce.

Oltre a questo hai il tuo codice "C" e il compilatore C. Il compilatore "conosce" vari tipi di dati come char, int's, uint's, float, double e così via.

La rappresentazione più comune dei float sull'hardware è con un formato IEEE. Ciò separa la mantissa dall'esponente e utilizza due parole a 16 bit per memorizzare le informazioni. Dai un'occhiata a questo articolo wiki sui formati numerici IEEE.

Quindi è il compilatore che sa dove sono la mantissa e l'esponente e applica la matematica ad esso. Ricordi i logaritmi? come hanno reso più semplice la matematica aggiungendo potenza quando si voleva multiplo? bene il compilatore c fa qualcosa di simile con gli esponenti e moltiplica la mantissa per calcolare la risposta. Quindi per una moltiplicazione in virgola mobile il compilatore creerà il codice assembler che aggiunge gli esponenti ed esegue la moltiplicazione della mantissa.

l'MCU non sa nulla del numero !!! proprio quello che gli viene detto di fare, caricare una memoria in un registro, aggiungere una memoria al registro e impostare il flag carry se necessario, e così via fino al completamento della moltiplicazione.

È il compilatore C e il codice che "estrae" il concetto di numeri, punti decimali e così via dall'MCU.

In una nota a margine, alcune lingue supportano anche il tipo di dati "decimali" che è utile per i sistemi finanziari, cosa non comune nelle piattaforme incorporate poiché i float utilizzano meno memoria ed eseguono in modo efficace.


1

Allo stesso modo i processori completi senza una fpu (ad esempio la maggior parte degli ARM) gestiscono il virgola mobile. Con un software fpu. C'è una libreria che esegue le operazioni matematiche / bit a bit. Se ricordi di aver fatto addizioni, moltiplicazioni, ecc. Nella scuola elementare con carta e matita, non è cambiato molto il giorno in cui sei passato da numeri interi a numeri con un punto decimale. Hai fatto la matematica nello stesso modo in cui hai dovuto regolare i numeri in modo che i punti decimali fossero allineati prima di iniziare (addizione e sottrazione) o dopo aver terminato (moltiplicazione o divisione). I fpus hard e soft non sono diversi, regolano i bit prima e dopo l'operazione, ma l'operazione è sostanzialmente un'operazione a numero intero.

Non ricordo esattamente dove trovarlo ora, ma gli strumenti texas avevano un ottimo documento relativo ai loro prodotti DSP. Ha spiegato il loro formato in virgola mobile ed è arrivato al punto di spiegare come funzionavano le operazioni. Il loro formato non ha arrotondamenti e denormali e infinito e silenzioso e segnali nani come IEEE, quindi è molto più facile da capire e significativamente più veloce dei formati IEEE. Dopo aver visto quel formato in azione, hai fatto il primo passo verso il formato IEEE. L'arrotondamento richiede alcune spiegazioni e riflessioni, ma il resto, le basi del segno, dell'esponente e della mantissa sono le stesse.

È molto costoso, in termini di risorse (memoria, flash, cicli di CPU) usare librerie soft float e lo scoraggerei in un sistema incorporato o in un microcontrollore. 12.3 e 24.5 sono abbastanza facili da gestire come i numeri interi 123 e 245, ad esempio, purché ricordi o forse se ti assicuri che tutta la tua matematica associata capisca che i numeri sono tutti moltiplicati per dieci e se / quando visualizzi un l'utente su quella conversione aggiungi il punto decimale. Risparmia tonnellate di codice e prestazioni. Ovviamente la divisione intera è una cosa negativa con i microcontrollori e i sistemi integrati, così come la maggior parte dei processori non ha un'istruzione di divisione, e questo include la divisione per 10 da convertire in decimale da visualizzare all'utente. E la stessa risposta, la divisione che ottieni dal tuo codice C viene fatta usando una libreria.


0

I float sono memorizzati in formato binario a 32 bit e il 1o bit indica se il float è un numero pos / neg, gli 8 bit successivi sono l'esponente -127, quindi ci sono 23 bit che sono il numero completo compreso il decimale, ovvero :
1 00010001 00010001000000000000000
Quindi 1 è che è negativo, i successivi 8 bit indicano l'esponente in questo caso:
0001 0001 = 17 (17-127 = -110)
Quindi la mantissa viene divisa:
(1+1/4+1/128)2^5

2^5era il movimento del decimale quando il float veniva spostato in binario. Il risultato perde alcune cifre durante la conversione, ma sono vicine. 1.5ex10-110
Potrei aver commesso errori seguendo gli altri, ma questa è l'idea generale di come i float vengono salvati in memoria.


2
Questo post può contenere tracce di informazioni, ma è nascosto in alcuni messaggi di chat non formattati wall-of-text. Stack Exchange non è Facebook, quindi per favore prova ad usare un linguaggio più professionale e si prega di utilizzare gli strumenti di formattazione messi a disposizione per rendere le informazioni leggibili, a partire dai paragrafi.
pipe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.