1

我正在使用 C 中的 PIC 微处理器。它是 16F,所以它不能保存大于 32 位的整数(无符号int32是可用的最大数据大小)

从阅读器那里,我收到一个 5 字节的 ID 代码。要传输它,我必须逐位编码为 BCD。我无法将其冲刺成字符串,因为它大于数据大小,并且无法处理它。我不能划分它,因为没有为它定义任何操作。

我想不出任何可能的解决方案,以前有没有人处理过这个问题?

编辑:

我收到一系列 5 个字节的数字:

FF-FF-FF-FF-FF

我需要将其转换为十进制

0123456789012

(13 位,十进制长度为 256^5)通过 RS232 发送。第二个函数(获取 ASCII,然后发送)我已经让它工作了,但我需要完整数字的字符串表示,然后才能对它做任何事情。

4

5 回答 5

4

假设您有 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**16y < 2**24)。

这基本上2**24是基于 2 位值的长除法,但预先计算的术语知道除数是 1000。选择一千是因为它是大于 10 的最小幂2**8

因此,首先计算最低三位数字,使用(2**32) % 1000 == 296. 所以这次我们将x作为最高字节,y作为低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 位领域,并且可以使用正常循环生成剩余的数字。

顺便说一句,如果我是你,我会检查结果:我没有测试过这个,我可能在某个地方犯了错误。应该很容易与在 PC 上使用 64 位整数中的常用方法完成的 bcd 转换结果进行比较。

于 2009-07-17T15:10:20.043 回答
1

我要做的是实现编码为字符串的数字的加法和乘法(BigNum 的一种)。这样,您可以将 ID 的最高有效字节 sprintf 到字符串“A”,将它与字符串“4294967296”(256^4)相乘,得到字符串“B”,将 ID 的 4 个最低有效字节冲入另一个字符串“C”,最后加上“B”和“C”。

它不是很性感,尤其是在微控制器上,但它有效:)

于 2009-07-17T14:45:46.037 回答
1

PIC16F 没有硬件乘法或除法单元,因此除非您用 2 的幂进行乘法或除法,否则会对处理器造成负担。这是一个对 32 位数字执行 BCD 且不需要除法或乘法的例程。您可以通过分块将其调整为 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);                           

}

于 2009-07-29T21:06:34.480 回答
0

您始终可以自己手动将其“sprintf”转换为字符串。逐个字节地检查数据字节,并通过附加单个字符将其转换为数字字符串。

于 2009-07-17T13:43:47.763 回答
0

我要说的这个问题的核心是转换为十进制的“长除法”之一。与您在小学学习的长除法并不完全不同,尽管使用二进制数,长除法要简单得多。但它仍然有很多工作。

尝试:
http://mathforum.org/library/drmath/view/55951.html

您将必须实现自己的多字节减法和移位例程。

于 2009-07-17T15:00:16.040 回答