本节摘要:模数转换器(ADC)与数模转换器(DAC)是模拟世界与软件世界的唯一通道。本节讲清三件事:I/Q 复数采样为什么用两路正交通道就能完整描述射频信号;8bit 量化在数据里呈现为什么样、数学上限是什么;转换器的关键参数(速率、位数、带宽)如何联合决定一台 SDR 的能力上限。
任何射频信号在某时刻都可以用两个量完整描述:幅度与相位。复数恰好是"幅度加相位"的数学载体——把它想成一支在复平面上旋转的指针:指针长度是瞬时幅度,旋转角是瞬时相位,转一圈的速率就是频率。I 是指针在横轴的投影,Q 是纵轴的投影。
为什么必须两路?如果只采一路实数信号,正频率与负频率的分量会折叠在一起无法区分;两路相差 90 度的正交采样,相当于记录下指针旋转的"方向",从而把正负频率分开。这就是复数采样的全部秘密:I 加 jQ 一个复数,携带了完整的幅度与相位信息,解调、滤波、变频都变成对复数序列的算术运算。第 4 章解调 FM 时,你会直接利用相位对时间的变化率提取声音——没有 I/Q,相位信息在实数采样里就丢了。
RTL-SDR 输出的每个复数样本占用两个字节:I 一个字节(无符号 0 到 255),Q 一个字节。实际数值减去 127.5 才是以零为中心的信号幅度——这就是第 1 章示例代码里那句 (raw - 127.5) / 128.0 的来历。
用一个实验直接看量化。下面这段 Python 代码合成一个正弦信号,分别用 8bit 和 12bit 量化,对比误差:
import numpy as np t = np.arange(0, 1, 1/2048000) # 2.048 MSPS 采样 1 秒 signal = 0.8 * np.sin(2 * np.pi * 1000 * t) # 1 kHz 正弦,幅度 0.8 def quantize(x, bits): levels = 2 ** bits # 8bit 有 256 级,12bit 有 4096 级 q = np.round(x * (levels / 2 - 1)) # 四舍五入到最近的量化台阶 q = np.clip(q, -(levels / 2 - 1), levels / 2 - 1) return q / (levels / 2 - 1) for bits in (8, 12): q = quantize(signal, bits) err = np.sqrt(np.mean((signal - q) ** 2)) # 均方根误差 snr = 10 * np.log10(np.var(signal) / err ** 2) print(f"{bits}bit 量化信噪比约 {snr:.1f} dB")
运行结果:8bit 约 49 dB,12bit 约 74 dB——与理论公式(6.02 乘位数加 1.76)吻合。49 dB 意味着信号与噪声的功率比最多呈现约八万倍;听着不少,但频谱上是另一回事:强台比噪声底高 45 dB 时,一个只高出 3 dB 的邻道弱信号就彻底湮没。量化误差还会产生谐波失真,让频谱里出现原信号频率的整数倍假峰——把增益调低让信号只占半量程,假峰会减轻,但信噪比同时下降。这就是 8bit 设备"增益要恰到好处"的数学原因。
复数样本流的速率账很好算:2.048 MSPS 乘 2 字节,等于每秒约 4 MB;若开到 2.4 MSPS 则约 4.8 MB 每秒。USB 2.0 的实际有效带宽约 35 MB 每秒,看似宽裕,但采样数据以固定周期批量传输,主机稍有卡顿(磁盘写入慢、CPU 被别的进程占满)就会来不及取走数据,驱动报"overflow"丢块。这正是所有 RTL-SDR 排错第一课:出现 overflow,先降低采样率或减少处理负载,再查 USB 控制器。写到磁盘的实验建议用内存盘或高速 SSD,机械硬盘在 4 MB 每秒持续写入时偶发停顿足以造成丢块。
转换器的另一端 DAC 在发射型 SDR(如 HackRF、USRP)里承担逆过程:把软件生成的复数样本变成模拟波形。位数、速率的取舍逻辑与 ADC 完全对称,只是方向相反——ADC 逼问"信号有多小也能听见",DAC 逼问"波形有多快能造出来"。
三个参数互相咬合:速率决定瞬时带宽(复数采样下约等于采样率),位数决定动态范围(每加一位约 6 dB),功耗随速率与位数指数上升。行业里每一代转换器都在这三个约束里挪动边界:RTL2832U 用 8bit 换低价低功耗;USRP B210 的 AD9361 用 12bit、56 MHz 带宽换性能,价格随之差出两个数量级;科研级 16bit 设备再上一个量级。没有全能的转换器,只有匹配场景的选择——这正是第 7 章选型章存在的理由。
先想清实验对动态范围的真实需求。广播、航空、ADS-B、气象卫星这些目标的信号强度都在 45 dB 范围内安排得开,8bit 足够;要在强广播台旁边找弱遥测、或者做频谱监测研究,12bit 的额外 30 dB 才是真需求。几十元试错再加千元升级的路径,比一步到位更不容易买错。
RTL2832U 的硬件输出就是无符号字节(0 到 255),偏置 127.5 代表零幅度。这是接口约定而非数学必然——不同硬件约定不同:有些 SDR 输出有符号 8bit、16bit 甚至浮点,读取时按设备文档的格式解释即可。
热噪声来自电子热运动,存在于采样之前,滤波可以降低其总功率但单位带宽密度不变;量化噪声来自 ADC 的台阶近似,是采样过程的产物,与信号强度相关、分布在带宽内。区分它们的方法是看信号强弱变化时噪声底跟不跟着动:跟动的是量化成分,不动的是热与环境成分。
两者都是把无符号字节归一到正负 1 区间的近似,差别只在满量程数值的细微不同。工程上纠结这个没有意义——解调只关心相对幅度,归一化系数最终会被 AGC 或音频增益吸收。要较真的地方是偏置:减 127.5 与减 128 的差会变成一个恒定直流,影响的是鉴频输出的偏置而非音质。
到这里,硬件的账全部算清。下一节正式开动:装驱动、跑命令,让第一段广播从扬声器里流出来。