我有一个从vhdl中的FPGA馈送的14位数据,NIos II处理器从FPGA读取14位数据并执行一些处理任务,其中Nios II系统用C代码编程
14位数据可以是正数,零或负数。在Altera编译器中,我只能将数据定义为8,16或32.所以我将其定义为16位数据。
首先,我需要检查数据是否为负数,如果是负数,我需要将前两个MSB填充为位'1',以便系统将其检测为负值而不是正值。
其次,我需要将这个二进制表示的实际值计算为BOTH整数和分数的十进制值。
我从这个链接(Correct algorithm to convert binary floating point "1101.11" into decimal (13.75)?)中了解到,我可以将二进制(由整数和分数组成)转换为十进制值。
要指定,我可以使用此链接引用的代码(Correct algorithm to convert binary floating point "1101.11" into decimal (13.75)?),如下所示:
#include <stdio.h>
#include <math.h>
double convert(const char binary[]){
int bi,i;
int len = 0;
int dot = -1;
double result = 0;
for(bi = 0; binary[bi] != '\0'; bi++){
if(binary[bi] == '.'){
dot = bi;
}
len++;
}
if(dot == -1)
dot=len;
for(i = dot; i >= 0 ; i--){
if (binary[i] == '1'){
result += (double) pow(2,(dot-i-1));
}
}
for(i=dot; binary[i] != '\0'; i++){
if (binary[i] == '1'){
result += 1.0/(double) pow(2.0,(double)(i-dot));
}
}
return result;
}
int main()
{
char bin[] = "1101.11";
char bin1[] = "1101";
char bin2[] = "1101.";
char bin3[] = ".11";
printf("%s -> %f\n",bin, convert(bin));
printf("%s -> %f\n",bin1, convert(bin1));
printf("%s -> %f\n",bin2, convert(bin2));
printf("%s -> %f\n",bin3, convert(bin3));
return 0;
}
我想知道这段代码是否可用于检查负值?我尝试使用二进制字符串11111101.11,它输出253.75 ...
我有两个问题:
我知道我可以进行位移(如下所示)来检查msb是否为1,如果是1,我知道它是负值......
if (14bit_data & 0x2000) //if true, it is negative value
问题是,因为它涉及小数部分(但不仅仅是整数),如果方法仍然有效,它会让我感到困惑......
答案 0 :(得分:2)
好的,所以我专注于你想要重复使用你在问题开头提到的算法的事实,并假设你签名的数字的二进制表示是Two's complement但是我根据你的意见,我不确定你的输入是否与算法使用的输入相同
首先填充2 MSB以具有16位表示
16bit_data = (14_bit_data & 0x2000) ? ( 14_bit_data | 0xC000) : 14_bit_data ;
如果值为正,则值将保持不变,如果为负,则这将是16位上正确的二进制补码表示。
对于分数部分,与您在问题中提到的算法相比,一切都是相同的 对于整数部分,除了MSB的处理外,一切都是相同的 对于无符号数,MSB(即位[15])表示pow(2,15-6)(6是frationnal部分的宽度),而对于2的补码表示中的带符号数,它表示-pow(2,15-6)意思是算法成为
/* integer part operation */
while(p >= 1)
{
rem = (int)fmod(p, 10);
p = (int)(p / 10);
dec = dec + rem * pow(2, t) * (9 != t ? 1 : -1);
++t;
}
或者如果你不想要*运营商
则说不同/* integer part operation */
while(p >= 1)
{
rem = (int)fmod(p, 10);
p = (int)(p / 10);
if( 9 != t)
{
dec = dec + rem * pow(2, t);
}
else
{
dec = dec - rem * pow(2, t);
}
++t;
}
对于你提到的第二个算法,考虑到格式化如果dot == 11和i == 0我们是MSB(10个整数位后跟点)所以代码变为
for(i = dot - 1; i >= 0 ; i--)
{
if (binary[i] == '1')
{
if(11 != dot || i)
{
result += (double) pow(2,(dot-i-1));
}
else
{
// result -= (double) pow(2,(dot-i-1));
// Due to your number format i == 0 and dot == 11 so
result -= 512
}
}
}
警告:在brice算法中,输入是字符串,如“11011.101”,而根据您的描述,您有一个整数输入,因此我不确定此算法是否适合您的情况
答案 1 :(得分:1)
我认为这应该有效:
float convert14BitsToFloat(int16_t in)
{
/* Sign-extend in, since it is 14 bits */
if (in & 0x2000) in |= 0xC000;
/* convert to float with 6 decimal places (64 = 2^6) */
return (float)in / 64.0f;
}
要将任何数字转换为字符串,我会使用sprintf
。请注意,它可能会显着增加您的应用程序的大小。如果您不需要浮动以及保留小型应用程序的内容,则应该创建自己的转换函数。