Преобразование шестнадцатеричного значения в десятичное, если ни один тип данных не может содержать полное число - PullRequest
1 голос
/ 17 июля 2009

Хорошо, я работаю с микропроцессором PIC в C. Это 16F, поэтому он не может содержать целые числа больше 32 бит (unsigned int32 - самый большой доступный размер данных)

От читателя я получаю 5-байтовый идентификационный код. Чтобы передать его, я должен закодировать в BCD, цифра за цифрой. Я не могу спринтить его в строку, так как он больше размера данных, и не могу его обработать. Я не могу разделить это, потому что никакая операция не определена для этого.

Я не могу найти какое-либо возможное решение, кто-нибудь имел дело с этим раньше?

EDIT:

Я получаю число в серии из 5 байтов: «FF-FF-FF-FF-FF». Мне нужно преобразовать его в десятичную "0123456789012" (13 цифр, длина 256 ^ 5 в десятичной), чтобы отправить его через RS232. Вторая функция (возьмите ASCII и отправьте его) У меня уже работает, но мне нужно строковое представление полного числа, прежде чем я смогу что-либо с ним сделать.

Ответы [ 5 ]

4 голосов
/ 17 июля 2009

Предполагая, что у вас есть 32-битная арифметика: 2 ** 24 = 16777216, таким образом, принимая x в качестве старшего значащего 2 байта и y в качестве младшего значащего 3:

  (16777216 * x + y) / 1000 
= (16777000 * x + 216 * x + y) / 1000
= 16777 * x + (216 * x + y) / 1000

Первый член может быть вычислен в 32 битах без переполнения (начиная с x < 2**16). Второй член также может быть вычислен без переполнения (так как x < 2**16 и y < 2**24).

Это в основном длинное деление по основанию 2**24 двухзначного значения, но с предварительно вычисленными терминами, зная, что делитель равен 1000. Одна тысяча выбрана, потому что ее наименьшая степень 10 больше 2**8.

Итак, сначала вычислите три младшие цифры, используйте тот факт, что (2**32) % 1000 == 296. Так что на этот раз мы возьмем х в качестве старшего байта и у в качестве младших 4 байта

((2**32) * x + y) % 1000 = ((2**32) * x) % 1000 + y % 1000 (modulo 1000)
                         = (296 * x) % 1000 + y % 1000     (modulo 1000)
((2**32) * x + y) % 1000 = ((296 * x) % 1000 + y % 1000) % 1000

Затем разделите оригинальное число на 1000, используя формулу выше. Тогда вы благополучно войдете в 32-битную территорию и сможете использовать оставшиеся цифры, используя обычный цикл.

Кстати, я бы проверил результаты на вашем месте: я не проверял это и, возможно, где-то допустил ошибку. Это должно быть легко сравнить с результатами преобразования bcd, выполненного обычным способом в 64-разрядном целом числе на ПК.

1 голос
/ 30 июля 2009

PIC16F не имеет аппаратного умножения или деления, поэтому, если вы не умножаете или делите на степень 2, это облагается налогом для процессора. Вот процедура, которая выполняет BCD для 32-битного числа и не требует деления или умножения. Вы можете адаптировать это к 5-байтовому числу, выполняя это кусками.

void BCD32 (int32u numIn) { цифра int8u = 0;

while (numIn >= 1000000000)
{
    numIn -= 1000000000;
    digit++;
}    
debug[0] = digit + 48;   
digit = 0;
while (numIn >= 100000000)
{
    numIn -= 100000000;
    digit++;
}    
debug[1] = digit + 48;            
digit = 0;
while (numIn >= 10000000)
{
    numIn -= 10000000;
    digit++;
}    
debug[2] = digit + 48;            
digit = 0;
while (numIn >= 1000000)
{
    numIn -= 1000000;
    digit++;
}    
debug[3] = digit + 48;            
digit = 0;
while (numIn >= 100000)
{
    numIn -= 100000;
    digit++;
}    
debug[4] = digit + 48;            
digit = 0;
while (numIn >= 10000)
{
    numIn -= 10000;
    digit++;
}
debug[5] = digit + 48;        
digit = 0;
while (numIn >= 1000)
{
    numIn -= 1000;
    digit++;
}
debug[6] = digit + 48;    
digit = 0;    
while (numIn >= 100)
{
    numIn -= 100;
    digit++;
}
debug[7] = digit + 48;

digit = 0;
while (numIn >= 10)
{
    numIn -= 10;
    digit++;
}
debug[8] = digit + 48;

digit = 0;
while (numIn >= 1)
{
    numIn -= 1;
    digit++;
}
debug[9] = digit + 48;    
debug[10] = CARRIAGE_RETURN;
debug[11] = NEW_LINE_FEED;
SendUart(12);                           

}

1 голос
/ 17 июля 2009

Что я хотел бы сделать, так это реализовать сложение и умножение чисел, закодированных в виде строки (вроде BigNum). Таким образом, вы можете поместить самый старший байт вашего идентификатора в строку «A», умножить его на строку «4294967296» (256 ^ 4), чтобы получить строку «B», спринтфить 4 младших байта вашего идентификатора другая строка «C» и, наконец, добавление «B» и «C».

Это не очень сексуально, особенно на микроконтроллере, но работает :) 1003 *

0 голосов
/ 17 июля 2009

Я бы сказал, что ядром этой проблемы является «длинное деление», которое нужно преобразовать в десятичную. В отличие от длинного деления, которое вы выучили в начальной школе, хотя с двоичными числами длинное деление намного проще. Но это все еще много работы.

попробуйте:
http://mathforum.org/library/drmath/view/55951.html

Вам нужно будет реализовать свои собственные многобайтовые процедуры вычитания и сдвига.

0 голосов
/ 17 июля 2009

Вы всегда можете "спринтфить" его в строку вручную. переберите байт данных за байтом и преобразуйте его в числовую строку, добавив отдельные символы.

...