【问题标题】:Convert 24-bit ADC serial read data from 3-byte format to signed integer (int32) in Matlab在 Matlab 中将 24 位 ADC 串行读取数据从 3 字节格式转换为有符号整数(int32)
【发布时间】:2016-12-06 15:11:27
【问题描述】:

我正在通过串行接收来自 24 位 ADC 的 EEG 数据。 ADC 数据以 3 个字节从 MSB 传输到 LSB。完整的数据包是 21 个字节:

第一个字节是起始字节 - 0xFF(十进制的 255) 然后是包号字节。 然后接下来的 3 个字节是 24 位 ADC 值分解为 MSB LSB2 LSB1 我可以很好地解析数据,但重新构造一个 2 的补码有符号 int32 数会导致问题。我得到的值当然不能反映 ADC 应该给出的值。

下面是读取和解析 504 个样本的行(这给了我 24 个 ADC 值(504 个样本/21 个字节 = 24 个值))。我尝试了 uint8 而不是 uchar ,结果相似(当我尝试 int8 时,我得到一个无效的指定精度错误)。

comEEGSMT = serial(com,'BaudRate',3000000);
fopen(comEEGSMT);
rawData(1:504) = fread(comEEGSMT, 504, 'uchar');
fclose(comEEGSMT);
startPackets = find(rawData == 255);
bytes = rawData([startpackets+2 startpackets+3 startpackets+4]);

我尝试了以下方法来重构该值:

ADC_value = bytes(:,1)*256^2 + bytes(:,2)*256 + bytes(:,3);

下面一行是将上述数字转换为伏特的公式:

ADC_value_volts = ADC_value*(5/3)*(1/(2^32));

值在 4000 - 8000 微伏的范围内,具有较大的值跳跃。值应在 200 - 600 微伏范围内,变化很小。

我发现了与类似问题相关的其他问题,但尝试以下链接中的建议解决方案没有成功:

https://uk.mathworks.com/matlabcentral/answers/137965-concatenate-3-bytes-array-of-real-time-serial-data-into-single-precision

非常感谢任何帮助,因为我已经坚持了很长时间。

谢谢马克

【问题讨论】:

    标签: matlab casting serial-port bit-shift adc


    【解决方案1】:

    从 ADC_value 作为 int32 开始,值为 0,然后:

    ADC_value |= MSB << 16;
    ADC_value |= LSB2 << 8;
    ADC_value |= LSB1;
    

    然后,要找出相应的伏特值,假设您的 ADC 有一个参考电压 VREF,以伏特为单位(例如 5.0V):

    ADC_value_volts = (ADC_value * VREF)/2^24
    

    因为您的转换器是 24 位,而不是 32 位。 请注意,以上表达式是 C 语言等价的,而不是 Matlab。

    编辑:

    ADC data sheet 告诉我们 PGA 增益可以设置为以下值: 1、2、4、6、8、12、24,每个通道一次一个值。 测量的 FSR(满量程)为:(2*VREF)/Gain = 5/3,对于增益 = 6, (eq.(5) page 23)所以这必须在计算电压的表达式中考虑 价值观。 (如果您可以访问硬件并且可以制作一些 测量)。

    ADC 产生的数据已经是二进制补码形式,24 位。 奇怪的是数据表从 1 开始计数位,而不是 0,所以这个 这就是为什么用“17”而不是 16 移动的原因——这实际上是 16 用于编码。 (显示在图 47,第 42 页)。

    所以ADC_value_volts的计算公式应该是:

    ADC_value_volts = (AC_value * FSR/(2^23))/3 (1LSB=FSR/(2^23), pg.37)
    

    如果对原始文件进行了其他一些计算/修改,则必须由提供者解释。 如果提供者不友好,值得改变......

    【讨论】:

    • 不幸的是没有运气。我的串行数据看起来像这样。 rawData = [255; 2; 24; 106; 200; ... ; 255; 3; 24; 128; 142; ... ; 255; 4; 24; 134; 2] startPackets = find(rawData == 255) ADC_Value = rawData(startPackets+2)*256^2 + rawData(startPackets+3)*256 + rawData(startPackets+4) ADC_Value_Volts = ADC_Value*(5/3)*(1/(2^24)) 生成的 ADC_Value_Volts 在 0.15 V 范围内,而不是大约 0.5 毫伏。
    • 您能解释一下为什么使用 *(5/3) - 什么是参考电压?对于 500 uV,序列 0x18、0x6A、0xC8 太大。你能用电压表或示波器验证测量结果吗? startPackets 有什么价值?
    • 我正在使用 EEG 采集设备,它是一个封闭的盒子。支持文档仅包含以下有关解释数据的内容。 " 重构为 2 的补码的公式,带符号的 int32 是:data = (MSB&lt;&lt;24 + LSB2&lt;&lt;17 + LSB1&lt;&lt;10)。EEG 通道到伏特的转换因子是:EEG = data*(5/3)*(1/2^32)。"
    • 左移 17 和 10 对我来说似乎很奇怪;但... 。还有一个问题:您的 ADC 是否有一个可编程增益放大器作为模拟前端?如果是,那么你应该将结果除以实际增益,如果使用它,得到大约 500 uV 的值。
    • 是的,增益设置为 3。我根本无法计算出 24、17、10 的班次。无法找到使用它的任何其他应用程序。非常令人费解!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多