Como os números com ponto decimal são tratados em um MCU?

8

Diga-me como os MCUs lidam com números decimais como '23 .3 ',' 3,24 'etc.? Como é armazenado em um registro de memória? Eu sei que tenho que usar o tipo de dados flutuante ao lidar com esses números durante a programação. Mas, na verdade, o que está acontecendo dentro de um MCU ao lidar com esses tipos. Diga-me também como os MCUs sem unidade FPU lidam com o tipo de dados Float.

0xakhil
fonte

Respostas:

13

Os números dentro dos microcontroladores típicos não têm pontos decimais. Eles são números inteiros binários. Não há decimal acontecendo dentro da máquina. O compilador ou montador pode permitir que você especifique constantes dessa maneira, mas elas são convertidas em binárias antes que a máquina as veja.

No entanto, você pode decidir quais unidades desejar para os valores inteiros. Por exemplo, suponha que você queira representar dólares dentro de um micro. Não pode nativamente fazer $ 3,21, mas poderia custar 321 centavos. O micro está operando apenas com o valor 321, mas você sabe que representa unidades de 1/100 dólares.

Esse é apenas um exemplo para ilustrar o conceito de unidades arbitrárias. Muitas vezes, os números são representados com vários bits de fração binária. É o mesmo que dizer que cada contagem representa um valor de 2- N , onde N é o número de bits da fração. Essa representação é chamada "ponto fixo". Você decide antecipadamente quanta resolução precisa e finge que há bits suficientes à direita do ponto binário imaginado para suportar essa resolução. Por exemplo, digamos que você precise representar algo com pelo menos uma resolução de 1/100. Nesse caso, você usaria pelo menos 7 bits de fração desde 2 7 = 128. Isso fornecerá uma resolução de 1/128.

A máquina não tem idéia do que está acontecendo. Ele irá adicionar e subtrair esses números como números inteiros comuns, mas tudo ainda funciona. Fica um pouco complicado quando você multiplica e divide valores de pontos fixos. O produto de dois valores de ponto fixo com N bits de fração terá 2N bits de fração. Às vezes, você apenas acompanha o fato de que o novo número tem 2N bits de fração ou, às vezes, pode alterá-lo para N bits para voltar à mesma representação de antes.

O ponto flutuante é a mesma coisa, mas o número de bits de fração é armazenado junto com a parte inteira, para que esse ajuste possa ser feito em tempo de execução. A execução de operações matemáticas em números de ponto flutuante pode levar vários ciclos. O hardware de ponto flutuante faz tudo isso para você, para que as operações sejam concluídas rapidamente. No entanto, as mesmas manipulações também podem ser executadas em software. Não há razão para que você não possa escrever uma sub-rotina para adicionar dois números de ponto flutuante, apenas que levaria muito mais tempo que o hardware dedicado fazendo a mesma coisa.

Eu defini um formato de ponto flutuante de 3 bytes para PICs de 8 bits e escrevi várias rotinas para manipulá-las. Os microcontroladores geralmente lidam com valores do mundo real com precisão de 10 ou 12 bits, no máximo. Meu formato de ponto flutuante usa 16 bits de precisão, o que é suficiente para vários cálculos intermediários.

Eu também tenho um formato de 32 bits para os PICs de 16 bits. Isso usa uma palavra de 16 bits para a mantissa, o que acelera os cálculos, pois esses PICs podem operar em 16 bits por vez.

Essas rotinas estão incluídas na minha versão das Ferramentas de desenvolvimento PIC . Após a instalação, observe os arquivos com "fp24" em seu nome no diretório SOURCE> PIC e "fp32f" no diretório SOURCE> DSPIC.

Olin Lathrop
fonte
Padrão de ponto flutuante Há também um padrão da IBM que apenas brincou com o viés.
NickHalden
4

A aritmética de ponto fixo é geralmente usada para realizar cálculos fracionários em MCUs.

O truque é dizer que (por exemplo), os 16 bits superiores de a uint32_testão antes do ponto decimal e os 16 inferiores estão depois, ou seja. o inteiro armazenado está em 1/2 ^ 16ths. Com algumas pequenas advertências, a aritmética regular "simplesmente funciona".

Aqui está uma visão geral .

Toby Jaffey
fonte
voto de mim para o link "Visão geral".
0xakhil
3

A menos que o MCU seja um DSP com multiplicador de ponto flutuante, tudo é armazenado como números de 16 bits (ou 8 ou 32, dependendo da sua plataforma). Isso é tudo o que o MCU conhece.

Acima disso, você tem o código "C" e o compilador C. O compilador "conhece" sobre vários tipos de dados, como char, int, uint, floats, doubles e assim por diante.

A representação mais comum de flutuadores no hardware é com um formato IEEE. Isso separa a mantissa do expoente e usa duas palavras de 16 bits para armazenar as informações. Confira este artigo da wiki sobre os formatos de número IEEE.

Portanto, é o compilador que sabe onde está a mantissa e o expoente e aplica a matemática a ele. Lembre-se de aprender sobre logaritmos? como eles tornaram a matemática mais fácil, adicionando energia quando você queria múltiplos? bem, o compilador c faz algo semelhante com os expoentes e multiplica a mantissa para calcular a resposta. Portanto, para uma multiplicação de ponto flutuante, o compilador criará código assembler que adiciona os expoentes e executa a multiplicação de mantissa.

o MCU não sabe nada sobre o número !!! exatamente o que é solicitado a fazer, carregue uma memória em um registro, inclua uma memória no registro e defina o sinalizador de transporte, se necessário, e assim por diante até que a multiplicação esteja concluída.

É o compilador C e seu código que "abstrai" o conceito de números, pontos decimais e assim por diante no MCU.

Em uma nota lateral, alguns idiomas também suportam o tipo de dados "decimal", que é útil para sistemas financeiros - não é comum em plataformas incorporadas, pois os flutuadores usam menos memória e desempenham com eficiência.

smashtastic
fonte
1

Da mesma maneira que os processadores completos sem um processador central (a maioria dos ARMs, por exemplo) lida com ponto flutuante. Com um processador de software. Há uma biblioteca que executa as operações matemáticas / bit a bit. Se você se lembra de fazer adição, multiplicação etc. na escola com lápis e papel, não mudou muito o dia em que passou de números inteiros para números com um ponto decimal. Você fez as contas da mesma maneira que tinha que ajustar os números para alinhar os pontos decimais antes de iniciar (adição e subtração) ou depois de terminar (multiplicação ou divisão). Os hard e soft fpus não são diferentes, eles ajustam os bits antes e depois da operação, mas a operação é basicamente uma operação com número inteiro.

Não me lembro exatamente onde encontrá-lo agora, mas os instrumentos do texas tinham um documento muito bom relacionado aos seus produtos DSP. Explicou o formato de ponto flutuante e chegou ao ponto de explicar como as operações funcionavam. Seu formato não possui arredondamentos, denormals, infinito e silêncio e sinalizações como IEEE, portanto, é muito mais fácil entender e significativamente mais rápido que os formatos IEEE. Depois de ver esse formato em ação, você deu o primeiro passo em direção ao formato IEEE. O arredondamento requer alguma explicação e pensamento, mas o resto, os conceitos básicos de sinal, expoente e mantissa são os mesmos.

É muito caro, em termos de recursos (memória, flash, ciclos de CPU) usar bibliotecas de flutuação suave e eu a desencorajaria em um sistema ou microcontrolador incorporado. 12.3 e 24.5 são bastante fáceis de gerenciar como os números inteiros 123 e 245, por exemplo, desde que você se lembre ou talvez se certifique de que toda a matemática associada entenda que os números são multiplicados por dez e se / quando você exibe um usuário nessa conversão, você adiciona o ponto decimal. Economiza toneladas de código e desempenho. É claro que a divisão inteira é uma coisa ruim com microcontroladores e sistemas embarcados, assim como a maioria dos processadores não possui uma instrução de divisão, e isso inclui a divisão por 10 para converter em decimal para exibir para o usuário. E a mesma resposta, a divisão que você obtém do seu código C é feita usando uma biblioteca.

old_timer
fonte
0

Os flutuadores são armazenados no formato binário de 32 bits e o 1º bit é para indicar se o flutuador é um número pos / negativo, os próximos 8 bits são o expoente -127, então existem 23 bits que são o número completo, incluindo a casa decimal, ou seja, :
1 00010001 00010001000000000000000
Então 1 é que é negativo, os próximos 8 bits devem indicar o expoente neste caso:
0001 0001 = 17 (17-127 = -110)
Então a mantissa é dividida:
(1+1/4+1/128)2^5

2^5foi o movimento da casa decimal quando o flutuador foi movido para o binário. O resultado perde alguns dígitos durante a conversão, mas eles estão próximos. 1.5ex10-110
Posso ter cometido erros ao seguir outras pessoas, mas essa é a ideia geral de como os carros alegóricos são salvos na memória.

Mike C
fonte
2
Esta postagem pode conter vestígios de informações, mas está oculta em algumas mensagens de bate-papo não formatadas. Stack Exchange não é Facebook, por favor, tente usar uma linguagem mais profissional e , por favor use as ferramentas de formatação disponíveis para tornar a informação legível, começando com os parágrafos.
pipe