C语言24位数据转换为32位

codeblocks测试工程下载:https://www.lanzous.com/i2u7tjc

 

一般情况下,ADC与单片机的通讯方式都是串行的,可能是IIC、SPI等。假设现在有一个24位的ADC,那么在正常工作时,单片机将依次接收到24bit的数据。ADC的数据是24位的,但是没有24位的数据类型。在单片机中,int类型的数据一般是32位的。所以需要一个函数来完成两者的转换。

首先我们要搞清楚计算机中数字的二进制存储形式。对于一个24位数,其计算关系可用下面的公式表达:

对于一个32位数,其计算关系可用下面的公式表达:

显而易见,对于一个正数来说,要拓宽它的位数,只需要在其多出来的位上补0即可。因为只是多项式中多加了几个0而已,并不会改变数据的大小。

而如果我们转换的数据是一个负数,问题就不那么简单了。

首先我们要搞清楚负数是怎么存储的。计算机中的负数是以补码形式存储的,即补码=原码取反+1。就是对正数先取反码,然后再加1。前面我们已经搞清楚了对一个正数该怎么拓宽,即补0。如果对拓宽后的这个正数再进行取反然后加1,那么我们是不是得到了一个位数改变的负数呢?答案肯定是对的。

假设我们现在有一个负数,我们可以先倒推回去,将其变成正数,然后用我们确定正确的方式对这个正数进行转换,然后把正数再变成负数。此时得到的负数位数已经是改变了的。可能有点绕,但确实是可行的。我们会发现,其实最终的效果是在多出来的位上补了1。这是因为我们对正数补0之后取了反,那就相当于直接补1了。

下面开始编写我们的代码。这里定义一个数组adc[3],用来存储ADC的数据。将接收到的三字节数据由低到高依次放置到数组中。即adc[0]放置低字节,adc[1]放置中间的字节,adc[2]放置高字节。

int adc24to32(unsigned char *padc);

此函数的输入参数为数组的地址。函数内部完成数据的转换,返回值为转换之后的32位数据。

在函数内定义一个int型的数据value,然后再定义一个指向value的指针。然后将数组中的数据搬到value所在的地址中。

    *p = *padc;
    *(p+1) = *(padc+1);
    *(p+2) = *(padc+2);

此处我们默认按照正数处理,然后判断其符号。判断是不是负数只需要判断*(padc+2)的最高位是不是1即可,将其与0x80相与,如果结果为1则表示其为负数,反之则不是。即:

    if(*(padc+2) & 0x80)
    {
        *(p+3) = 0xff;
        return value;
    }
    else
    {
        return value;
    }

假设我们现在有如下数据,下面对其一一进行检验。

原始数据(二进制)

理论值(十进制)

0X7FFFFF

8388607

0X400000

4194304

0X000001

1

0X000000

0

0XFFFFFF

-1

0XC00000

-4194304

0X800000

-8388607

这里定义三个数组来存储我们的原始数据,LL为数据的低字节,MM是数据的中间字节,HH为数据的高字节。在测试的时候,给adc[ ]赋值,然后调用刚才编写的函数。最后将结果打印出来,跟预期的结果进行对比,就可以知道我们的函数有没有错误。

unsigned char LL[7] = {0xff,0x00,0x01,0x00,0xff,0x00,0x00};

unsigned char MM[7] = {0xff,0x00,0x00,0x00,0xff,0x00,0x00};

unsigned char HH[7] = {0x7f,0x40,0x00,0x00,0xff,0xc0,0x80};

然后我们定义一个for循环,依次取出其中的数据进行检验

int main( )
{
    int i;
    for(i = 0; i < 7; i++)
    {
        adc[0] = LL[i];
        adc[1] = MM[i];
        adc[2] = HH[i];

        value = adc24to32(adc);

        printf("\nThis 24bit value %02x%02x%02x change to int32 is %d\n",adc[2],adc[1],adc[0],value);
    }
    return 0;
}

程序运行的结果如下:

跟表格里的结果进行对比,可知程序没有错误。

猜你喜欢

转载自blog.csdn.net/Zd_c000/article/details/86237379