概述
目前有许多ADC芯片都是24位精度的,这个位数稍显尴尬,因为在常用的变量类型中,有8bit、16bit、32bit,唯独没有24bit,这就导致我们在很多情况下,需要自己敲代码去处理这个24bit的有符号数据。
十六进制 -> 十进制
在开始之前,需要清楚计算机中是如何表示负数的。
对于有符号24位整型值,0x000001~0x7FFFFF是对应十进制的正数区间0~8388607,达到正的最大值之后,再往后加1,就来到了负数的地盘。负数有些不同,0x800000表示的是负的最大值,~0xFFFFFF则对应十进制的负数区间~-1。如下表:
十六进制数从0x000000开始逐渐增大,表示的十进制也是从0开始逐渐增大。一直增大到0x7FFFFF时,来到了正负数的分界点。0x7FFFFF是正数的最大值,再往后+1,就变成了0x800000,这是负数的最小值。十六进制数继续增大,表示的十进制负数也随之增大,一直增大到0xFFFFFF时,这个十六进制数的范围到了尽头,对应十进制的值也到了负数区间的尽头:-1。具体值见下表:
十六进制 | 十进制 |
---|---|
00 00 00 | 0 |
00 00 01 | 1 |
………………… | ……………… |
7F FF FF | 8388607 |
80 00 00 | -8388608 |
80 00 01 | -8388607 |
………………… | ……………… |
FF FF FF | -1 |
以上是对24bit有符号数据的描述,32bit有符号数据的正负区间规律类似,只不过正负分界点多了8位,变成了0x7F FF FF FF和0x80 00 00 00。
在大部分编译器中,并没有24bit这样一个尴尬的数据类型,因此我们需要用一个32bit的变量来将就一下,比如在大部分X86、X64的PC,以及32位单片机中的int,下面我们就以int为例。
int是32位(XX XX XX XX),而我们的数据是24位(XX XX XX),最高位缺了一个字节(XX),而这个字节恰恰决定了数据的正负号。因此,我们在用32位变量来装24位数据时,为了确保不把符号弄丢,要进行补位:
- 如果24位数据的最高位大于等于0x80,表明这是一个负数,要在前面补上一个8个1(0xFF)构成32位变量。
- 如果24位数据的最高位小于0x80,表明这是一个正数,在前面补上一个8个0(0x00)即可。
十进制 -> 实际电压
将十六进制转换到我们熟悉的十进制后,还需要将其转换成实际的电压值。一些24位AD芯片的手册上是这样写的:
读上表,可以看到该芯片的测量范围Vrang是单倍参考电压(有些芯片可能是二倍参考电压,或者参考电压减去几伏,需要注意),不难得到换算公式:实际电压 =十进制原始值* 测量范围/0x7FFFFF
参考代码
以下代码是在STM32上通过SPI实现24位AD数据的采集,并将其转换为实际值(单位mV)的过程。
//AD_DEC的数据类型应定义为32位有符号型。
//int对于大部分X86、X64的PC,以及32位单片机来说都是32位
int AD_DEC;
double AD_mV;
long double get_AD_data()
{
char data1,data2,data3;
//……
//其余代码略
//……
//读24位数据(高位在前)
HAL_SPI_Receive(&hspi1, &data1, 1, 10);
HAL_SPI_Receive(&hspi1, &data2, 1, 10);
HAL_SPI_Receive(&hspi1, &data3, 1, 10);
//转换为十进制
AD_DEC = (unsigned int)(data1<<16)|(data2<<8)|data3;
//如果大于800000,说明是负数,最高位补一个FF
if(data1&0x80)
AD_DEC |= 0xFF000000;
//十进制转换为mV (这里以测量范围-5V~5V为例)
AD_mV = AD_DEC*0.000596046518808;
return AD_mV;
}
利用python解析24位原始AD数据的hex文件并绘图
AD采集到数据之后,我们往往想要画出AD数据的变化趋势图来直观地分析问题。
在一些对采样率要求较高的场景下,我们往往不是保存转换后的实际电压值,因为这样太耗费时间了,而是直接将原始的十六进制数据放进HEX文件,存入大容量的SD卡中。
接下来就介绍如何使用python解析存有原始24位AD数据的HEX文件,并绘出曲线。
本文用来举例的hex文件格式如下图所示。前9字节是文件头,存储了一些信息,从第10字节开始,就是一个挨一个密集存放的24位原始数据。
在python中,不需要我们亲自处理24bit有符号数据,直接使用int.from_bytes( )即可。因此,整个python代码看起来非常简单。
import matplotlib.pyplot as plt
fin = open('F://bottom-2000-1-1-0-37-41.hex', mode = 'rb')
# 跳过前9字节的文件头。如果你的文件没有文件头,可以删掉下面这一行
fin.seek(9)
hex_dat = fin.read()
fin.close()
value = []
for i in range(0, len(hex_dat), 3):
# 读取三个Byte组成一个24bit数
value.append(0.000596046518808*int.from_bytes(hex_dat[i:i+3], byteorder = 'big', signed = 'true'))
plt.plot(value)
plt.show()
如果你的hex文件没有前9个字节的文件头,将程序中的fin.seek(9) 删除即可。
运行结果如下图:
最后
以上就是纯真硬币为你收集整理的24位ADC数据转换,保存为hex文件,并利用python解析hex文件画图十六进制 -> 十进制十进制 -> 实际电压参考代码利用python解析24位原始AD数据的hex文件并绘图的全部内容,希望文章能够帮你解决24位ADC数据转换,保存为hex文件,并利用python解析hex文件画图十六进制 -> 十进制十进制 -> 实际电压参考代码利用python解析24位原始AD数据的hex文件并绘图所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复