32位 DMIC 数据 其中高八位为符号位扩展位的理解
核心概念分解
DMIC 的有效数据位宽 (通常为 24 位):
现代数字麦克风(尤其是 PDM 或 I²S 接口的高精度麦克风)的核心 ADC 通常是 24 位 精度的。这意味着它们能产生从 -8388608 到 +8388607 (-2²³ 到 +(2²³ - 1)) 的原始采样值。
32 位传输宽度的原因:
微控制器、DSP 或音频编解码器的数据总线或 FIFO 通常是 32 位 对齐的(或者 32 位操作更高效)。
为了简化硬件设计和数据传输,将 24 位有效数据放入一个 32 位 的“容器”中进行传输是常见的做法。
符号扩展 (Sign Extension):
符号扩展是处理 有符号整数 时,当需要将其放入一个更宽位宽的容器中,同时 保持其数值不变 的标准方法。
规则:将原始数据的 最高位(符号位) 复制到新容器中所有新增的高位上。
目的:
保持数值正确性:确保扩展后的 32 位数值与原始 24 位数值代表的十进制数完全相同。这对于负数和正数的边界值尤其重要。
简化硬件处理:CPU/DSP 可以像处理原生 32 位有符号整数一样直接处理这些数据,无需在软件中额外进行移位或掩码操作来调整符号(大部分硬件指令自动处理符号扩展)。
“32位数据,高8位为符号扩展”的含义
32 位数据 (DATA[31:0]):指的是从 DMIC 接收或通过接口(如 I²S)传输过来的完整 32 位数据字。
高 8 位 (DATA[31:24]):指的是这个 32 位数据字的最高 8 位 (Bit 31 到 Bit 24)。
符号扩展:这高 8 位的值 不是 新的信息或额外的精度,而是 由原始 24 位有效数据的最高位(Bit 23)复制而来 的。
具体结构解析
假设我们有一个 24 位的有符号采样值 S[23:0](S[23] 是符号位,S[22:0] 是数值位)。
原始 24 位数据: S[23] S[22] S[21] … S[1] S[0]
扩展到 32 位后的数据:
DATA[31:24] (高 8 位): S[23] S[23] S[23] S[23] S[23] S[23] S[23] S[23] (即符号位 S[23] 被复制了 8 次)
DATA[23:16]: S[23] S[22] S[21] S[20] S[19] S[18] S[17] S[16] (原始最高字节)
DATA[15:8]: S[15] S[14] S[13] S[12] S[11] S[10] S[9] S[8]
DATA[7:0] (低 8 位): S[7] S[6] S[5] S[4] S[3] S[2] S[1] S[0]
总结 32 位数据字的结构:
DATA[31:0] = { {8{S[23]}}, S[23:0] }
{8{S[23]}}:表示将 S[23] 重复 8 次,构成高 8 位 (DATA[31:24])。
S[23:0]:原始的 24 位有效数据,占据低 24 位 (DATA[23:0])。
为什么需要这样理解?(实际意义)
直接当作 32 位有符号整数使用:
当你的程序(C/C++等)读取这个 32 位数据并存储到一个 int32_t (或 s32) 类型的变量时,这个变量的值 自动地、正确地 就等于原始 24 位采样值的数值。
无需手动移位或掩码:因为高 8 位是符号扩展,符合 CPU/DSP 对有符号整数的存储和处理规则。例如:
c
int32_t raw_sample = ((volatile int32_t)&dmic_data_register); // 直接读取
float sample_voltage = (float)raw_sample / (1 << 23); // 直接转换为浮点电压 (假设满量程对应 2²³)
这个 raw_sample 的值就是正确的 -8388608 到 +8388607。
忽略高 8 位的具体值:
你不需要关心 DATA[31:24] 里面具体是 0xFF 还是 0x00 或者其他值。它们只是原始符号位 S[23] 的副本,没有提供新的信息。真正有用的数据在 DATA[23:0],并且它已经通过符号扩展准备好被当作 32 位整数使用了。
区分于零扩展 (Zero Extension):
如果高 8 位是用 0 填充(零扩展),那么对于负数(S[23] = 1),直接当作 32 位整数解读会得到一个巨大的正数,结果是错误的。符号扩展避免了这个问题。
图示示例
示例 1:正数 (小值)
原始 24 位: 0x000123 (十六进制,十进制值为 291)
符号位 S[23] = 0
32 位符号扩展后: 0x00000123 (高 8 位是 0x00, 值仍是 291)
示例 2:正数 (边界值,最大值)
原始 24 位: 0x7FFFFF (十六进制,十进制值为 8388607)
符号位 S[23] = 0
32 位符号扩展后: 0x007FFFFF (高 8 位是 0x00, 值仍是 8388607)
示例 3:负数 (小值)
原始 24 位: 0xFFFFFD (十六进制,二进制补码,十进制值为 -3)
符号位 S[23] = 1
32 位符号扩展后: 0xFFFFFFFD (高 8 位是 0xFF, 值仍是 -3)
示例 4:负数 (边界值,最小值)
原始 24 位: 0x800000 (十六进制,二进制补码,十进制值为 -8388608)
符号位 S[23] = 1
32 位符号扩展后: 0xFF800000 (高 8 位是 0xFF, 值仍是 -8388608)
结论
“32位DMIC数据,高8位为符号扩展”意味着:
这 32 位数据包含一个实际有效的 24 位有符号音频采样值。
低 24 位 (DATA[23:0]) 存储了这个原始采样值。
高 8 位 (DATA[31:24]) 不是独立的数据,而是原始 24 位数据最高位(符号位)的 8 份拷贝。
这样做的目的是让整个 32 位数据 可以直接当作一个标准的 32 位有符号整数 (int32_t) 来使用和处理,其数值完全等同于原始的 24 位采样值,无需额外的位操作来修正符号。在编程时,直接读取到 int32_t 变量中即可得到正确的数值