最近做了一个功率计的项目,检测芯片用的是 CS5460A,它采样到的数据是 24 位,AD 结果(如电压和电流)还要乘以一个系数才可以得到适合显示的 BCD 码,电压和电流的系数都比较大。并且,在计算功率时,还要把两个系数相乘,然后再乘以 24 位的功率值,才得到可显示的数据,最终的结果远大于四字节整数所能表示的数值,因此,需要用到大整数乘法。
在网上搜了一下,没找到合适的,就写了一个,我把此段程序整理出来,放在这里,希望能给需要的朋友带来方便,如果有更好的方法,也请指正。
如果你写的程序,或者你在别的地方看到过类似的程序,也请指出,只能表明我见识不过,还请原谅,但我的程序决不是抄别人的,只想为需要的朋友带来一点方便。
程序实现的是两个四字节无符号数相乘,结果为 8 个字节,根据程序原理,你也可以设计出任意长度的数据相乘。
不过,请注意,项目中使用的芯片是 51 类的,编译器自然也是 KEIL C51,它使用的是大端数据结构,如果将程序移植到使用小端结构的程序中,需要修改后才能使用,但原理相同。下面是程序:
-------------------------------------------------------------
#include <intrins.h>
union
{
Uint16 D16[2];
Uint32 D32;
} Data0, Data0; //乘数和被乘数
Uint8 ResultOfMul[8]; //乘法运算结果
void main(void)
{
while (1)
{
Data0.D32 = 0x12345678;
Data1.D32 = 0x87654321;
BigNumMul(); //ResultOfMul 中的数据为 0x09A0CD0570B88D78
Data0.D32 = 0xFFFFFFFF;
Data1.D32 = 0xFFFFFFFF;
BigNumMul(); //ResultOfMul 中的数据为 0xFFFFFFFE00000001
}
}
void BigNumMul(void)
{
Uint8 i;
Uint32 Temp;
for (i = 0; i < 8; i++)
{
ResultOfMul[i] = 0;
}
Temp = Data0.D16[1];
Temp *= Data1.D16[1];
*(Uint32 *)&ResultOfMul[4] = Temp;
Temp = Data0.D16[0];
Temp *= Data1.D16[0];
*(Uint32 *)&ResultOfMul[0] = Temp;
Temp = Data0.D16[0];
Temp *= Data1.D16[1];
*(Uint32 *)&ResultOfMul[2] += Temp;
if (_testbit_(CY)) //if (PSW & 0x80)
{
(*(Uint16 *)&ResultOfMul[0])++;;
}
Temp = Data0.D16[1];
Temp *= Data1.D16[0];
*(Uint32 *)&ResultOfMul[2] += Temp;
if (_testbit_(CY)) //if (PSW & 0x80)
{
(*(Uint16 *)&ResultOfMul[0])++;;
}
}
-------------------------------------------------------------
在上面的程序中,有一句为:
if (_testbit_(CY)) //if (PSW & 0x80)
它表示可以用注释中的语句代替前面的语句,完全等效,只不过,使用前面的语句时,必须在文件的前面使用
#include <intrins.h>
才可以使用它里面的本征函数 _testbit_。此句用来检测进位位被设置,移植到其它类单片机中时,注意替代此句。
|