2026/4/18 14:53:53
网站建设
项目流程
缘魁上海网站建设,微信分享按钮wordpress高级版,品牌推广理论,wordpress 324如图25.8中频域所示#xff0c;数字下变频的一般方法源自模拟下变频和采样。第1行和“”
行上的频谱表示系统中不同节点上的信号#xff0c;“*”行和“x”行上的频谱分别表示把那些把信
号相关起来的频谱卷积以及逐点频谱相乘运算。图中第1行画出了一个实数中频#xff08;…如图25.8中频域所示数字下变频的一般方法源自模拟下变频和采样。第1行和“”行上的频谱表示系统中不同节点上的信号“*”行和“x”行上的频谱分别表示把那些把信号相关起来的频谱卷积以及逐点频谱相乘运算。图中第1行画出了一个实数中频IF信号示意图这个信号的单边带宽和双边带宽分别为40MHz和80MHz正频率分量和负频率分量的中心分别位于75MHz和-75MHz。图25.8中的第二行用一个-75MHz的本振频率通过频谱卷积将中频信号频移很快我们将看到这是如何用硬件实现的。第3行上的结果的频率分量中心位于0Hz和-150MHz。与第4行中的低通滤波器频率响应相乘于是去除了-150MHz的分量只留下第5行的复数基带信号这个信号有一个双边带宽和40MHz的奈奎斯特频率。第6行上的频率卷积对应于在时域上将第5行表示的信号与一个以50MHz采样频率采样的均匀脉冲序列相乘。在时域中结果就是一个50MHz的采样脉冲序列其值是第5行信号在采样时刻的采样值我们忽略比例因子)。当然我们在硬件中不会生成第7行中的脉冲而是在寄存器中以数来数字地实现脉冲区域。通俗解释就是第 1 行 — 实数中频IF信号两个对称的频谱包图 1 行画的是一个实值中频信号的频谱。实信号在频域总是成对出现正频率分量和负频率分量是对称的。在图中这两个“包”各自围绕 75 MHz 和 −75 MHz 展开两侧合起来是“总带宽”。比喻就像频谱在 75 和 −75 两个地方各站了一群人能量每群人占一定宽度带宽。第 2 行 — 用本振LO把频谱“搬走”频率变移 / 混频在图里把中心在 75MHz 的那一群移动到 0Hz基带而原来在 −75MHz 的那一群被移动到 −150MHz。于是频谱变成了两个新的“包”一个在 0Hz另一个在 −150MHz第 3 行所示结果。第 3 → 第 4 行 — 用低通滤波器去掉远处的“镜像”现在你有两个“包”靠近 0 的包有价值和远在 −150MHz 的包镜像 / 图像成分。把信号通过低通滤波器LPF可以把靠近 0 的包保留下来去掉远处的 −150MHz 包。这是经典的去除混频后“镜像频谱”的做法。结果是第 5 行只剩下靠近 0Hz 的那部分 —— 这就是复数基带信号complex baseband。第 5 行 — 复数基带信号把频谱移到 0 附近剩下的信号称为复数基带它在中心 0 附近对称展开即双边带围绕 0。复数基带的好处带通信息被“搬到”低频便于数字处理而且 I/Q 能区分正负频率信息防止二义性。第 6 行 — 采样在频域就是把频谱“复制”成很多份第 7 行 — 在时域上看采样用脉冲“挑取”取样点在实际数字系统中我们不会物理上产生窄脉冲把模拟信号“打孔”而是用 ADC模数转换器在时刻把值读入寄存器数学上等价于乘以冲激列。第 7 行就是展示了被采样后的离散脉冲序列的频谱每个脉冲代表一个采样值以及在寄存器中以数字形式保存的效果。为什么要先下变频再采样把高频信息搬到低频便于用较低速率的 ADC 采样节省硬件资源或降低后续数字处理的计算量。用低通滤波去掉镜像可以得到干净的基带避免 aliasing。IQ复数基带能保留相位信息这是很多通信 / 雷达处理不可或缺的例如相位解调、方位信息等。常见的两种实现方式硬件上直接射频复数下变频IQ 混频→ 低通 → ADC 采样基带这是现代接收机常见形式能得到复数基带直接供数字处理。先用实 LO 混频成低频再用 LPF → ADC如果仅用实余弦作 LO会产生对称镜像必须滤掉适用于只需要功率或幅值的场合。小结图中先把 IF 的频谱“搬移”混频使有用部分落到 0 附近再用低通滤波把不需要的镜像去掉得到复数基带最后用采样ADC把连续时间基带变成离散时间序列——在频域上采样会把基带频谱周期性复制所以设计采样率和滤波器时要注意避免频谱重叠 / 折叠。代码实现及可视化#!/usr/bin/env python3 # -*- coding: utf-8 -*- IF - IQ 混频 - LPF - 采样 仿真中文注释与绘图 保存图像为 PNG 并在终端打印参数说明中文。 依赖 pip install numpy matplotlib 用法 python if_iq_sim_chinese.py 注意 - 脚本会尝试在系统字体中选择常见中文字体SimHei、Noto Sans CJK、WenQuanYi 等。 如果系统没有中文字体matplotlib 可能无法正确显示中文文字脚本会打印提示并继续运行。 - 可修改脚本顶部的参数来改变采样率、带宽、SNR 等。 import numpy as np import matplotlib import matplotlib.pyplot as plt from matplotlib import font_manager import os # ------------------ 参数区可调整 ------------------ # 内部“模拟”采样率用于离散化连续时间以做 FFT / 仿真 fs_cont 500e6 # Hz duration 1e-4 # 秒 N int(np.round(fs_cont * duration)) t np.arange(N) / fs_cont f_center 75e6 # 中频中心频率 75 MHz bandwidth 40e6 # 信号带宽双边带总宽度Hz half_bw bandwidth / 2 Fs 50e6 # ADC 采样率最终采样率Hz decim int(np.round(fs_cont / Fs)) if decim 1: decim 1 SNR_dB 20.0 # 添加噪声的目标 SNR (dB) # LPF 截止频率单位Hz建议 Fs/2留有过渡带 lpf_cutoff 25e6 # 输出图像保存目录 out_dir sim_plots os.makedirs(out_dir, exist_okTrue) # ------------------ 自动选择中文字体 ------------------ def choose_chinese_font(): # 常见中文字体候选名称或文件名中匹配 candidates [ SimHei, SimSun, Noto Sans CJK, NotoSansCJK, WenQuanYi, AR PL, Microsoft YaHei, PingFang, Heiti SC, STHeiti, Source Han Sans, SourceHanSans, Noto Sans CJK SC, Arial Unicode MS ] sys_fonts font_manager.findSystemFonts(fontpathsNone, fontextttf) sys_names [font_manager.FontProperties(fnamef).get_name() for f in sys_fonts] # 尝试按优先候选匹配系统字体名称 for cand in candidates: for idx, name in enumerate(sys_names): if cand.lower() in name.lower(): return sys_fonts[idx], name # 如果没有候选尝试返回第一个系统字体 if sys_fonts: return sys_fonts[0], font_manager.FontProperties(fnamesys_fonts[0]).get_name() return None, None font_path, font_name choose_chinese_font() if font_path: try: matplotlib.rcParams[font.sans-serif] [font_name] matplotlib.rcParams[font.family] sans-serif matplotlib.rcParams[axes.unicode_minus] False font_notice f已选用系统字体{font_name}文件{os.path.basename(font_path)} except Exception: font_notice 尝试设置中文字体失败仍使用 matplotlib 默认字体显示。 else: font_notice (未在系统中找到可识别的字体。若中文不能正常显示 请在系统中安装常见中文字体例如 SimHei、Noto Sans CJK、WenQuanYi 或 Microsoft YaHei。) print(font_notice) # ------------------ 构造实值 IF 信号在频域直接造谱以便控制形状 ------------------ freqs np.fft.fftshift(np.fft.fftfreq(N, d1/fs_cont)) Spec np.zeros(N, dtypecomplex) # 在 75 MHz 附近创建一个宽带平顶谱示意 mask_plus np.logical_and(freqs (f_center - half_bw), freqs (f_center half_bw)) # 由实信号对称负频谱为共轭镜像 np.random.seed(2) Spec[mask_plus] np.exp(1j*2*np.pi*np.random.rand(mask_plus.sum())) Spec[np.logical_and(freqs (-f_center half_bw), freqs (-f_center - half_bw))] np.conj(Spec[mask_plus]) # 变回时域确保为实信号 sig_if np.real(np.fft.ifft(np.fft.ifftshift(Spec))) * N sig_if sig_if / np.std(sig_if) # 归一化信号功率为 1 # ------------------ IQ 混频复数 LO ------------------ lo np.exp(-1j * 2 * np.pi * f_center * t) # 复数 LO把 f_center 下移到 0 sig_mixed sig_if * lo # 结果为复数I jQ # ------------------ 加 AWGN根据指定 SNR ------------------ power_sig np.mean(np.abs(sig_mixed)**2) SNR_linear 10**(SNR_dB / 10.0) noise_power power_sig / SNR_linear noise np.sqrt(noise_power/2) * (np.random.randn(N) 1j*np.random.randn(N)) sig_mixed_noisy sig_mixed noise # ------------------ 低通滤波器FIR 窗口化 sinc ------------------ num_taps 801 # 滤波器 taps越大过渡带越窄但计算量增大 m np.arange(num_taps) - (num_taps - 1) / 2 fc_norm lpf_cutoff / fs_cont # 截止频率相对于采样率 h 2 * fc_norm * np.sinc(2 * fc_norm * m) h * np.hamming(num_taps) h / np.sum(h) # 卷积滤波same 长度 sig_filtered np.convolve(sig_mixed_noisy, h, modesame) # ------------------ 采样降采样 / 抽取 ------------------ sig_sampled sig_filtered[::decim] fs_sampled fs_cont / decim t_sampled np.arange(len(sig_sampled)) / fs_sampled # ------------------ 频谱绘图辅助函数中文注释 ------------------ def plot_spectrum_save(x, fs, title, filename, xlim_mhz300, ref_max_db0): 绘制并保存频谱图 - x: 信号可以为复数 - fs: 采样率Hz - title: 图标题中文 - filename: 保存文件路径 Nfft len(x) X np.fft.fftshift(np.fft.fft(x)) mag 20 * np.log10(np.abs(X) 1e-12) mag mag - np.max(mag) ref_max_db # 以峰值为参考 freqs_mhz np.fft.fftshift(np.fft.fftfreq(Nfft, d1.0/fs)) / 1e6 plt.figure(figsize(10,4)) plt.plot(freqs_mhz, mag, linewidth1) plt.xlim(-xlim_mhz, xlim_mhz) plt.ylim(-80, 5) plt.grid(True, linestyle:) plt.xlabel(频率 / MHz) plt.ylabel(幅度 / dB相对于峰值) plt.title(title) # 添加图中文字体说明若字体可用 plt.tight_layout() plt.savefig(filename, dpi200) plt.close() def plot_time_save(t_axis, x, title, filename, samples_to_plot800): plt.figure(figsize(10,3)) n min(samples_to_plot, len(x)) # 若是复数绘制实部与虚部 if np.iscomplexobj(x): plt.plot(t_axis[:n]*1e6, x[:n].real, label实部) plt.plot(t_axis[:n]*1e6, x[:n].imag, label虚部, alpha0.8) else: plt.plot(t_axis[:n]*1e6, x[:n], label波形) plt.xlabel(时间 / 微秒) plt.ylabel(幅度) plt.title(title) plt.legend() plt.grid(True, linestyle:) plt.tight_layout() plt.savefig(filename, dpi200) plt.close() # ------------------ 保存图像 ------------------ # 1) 原始 IF 频谱连续模拟仿真 plot_spectrum_save(sig_if, fs_cont, 1) 原始实值 IF 频谱±75 MHz, os.path.join(out_dir, 01_if_spectrum.png), xlim_mhz300) # 2) IQ 混频后75 MHz → 0Hz plot_spectrum_save(sig_mixed, fs_cont, 2) IQ 混频后将 75 MHz 下移到 0 Hz, os.path.join(out_dir, 02_mixed_spectrum.png), xlim_mhz300) # 3) 混频并加噪 plot_spectrum_save(sig_mixed_noisy, fs_cont, f3) 混频后 AWGNSNR {SNR_dB} dB, os.path.join(out_dir, 03_mixed_noisy_spectrum.png), xlim_mhz300) # 4) 低通滤波后复基带 plot_spectrum_save(sig_filtered, fs_cont, f4) 低通滤波后截止 {lpf_cutoff/1e6:.1f} MHz→ 复基带, os.path.join(out_dir, 04_filtered_spectrum.png), xlim_mhz100) # 5) 采样后显示重复谱 plot_spectrum_save(sig_sampled, fs_sampled, f5) 采样后Fs {fs_sampled/1e6:.1f} MHz — 频谱周期复制出现, os.path.join(out_dir, 05_sampled_spectrum.png), xlim_mhz150) # 6) 时域波形快照原始 IF、混频后、采样后 plot_time_save(t, sig_if, 时域原始实值 IF前若干样本, os.path.join(out_dir, time_if.png)) plot_time_save(t, sig_mixed_noisy, 时域混频后复基带含噪声, os.path.join(out_dir, time_mixed_noisy.png)) plot_time_save(t_sampled, sig_sampled, 时域采样后复基带实部显示, os.path.join(out_dir, time_sampled.png)) # ------------------ 打印参数与说明中文 ------------------ print(仿真参数中文说明) print(--------------------------------------------) print(f内部等效采样 fs_cont {fs_cont/1e6:.1f} MHz仿真样本数 N {N}) print(fIF 中心频率 f_center {f_center/1e6:.1f} MHz信号带宽 {bandwidth/1e6:.1f} MHz双边带) print(f目标 ADC 采样率 Fs {Fs/1e6:.1f} MHz抽取因子 decim {decim}实际采样率 fs_sampled {fs_sampled/1e6:.3f} MHz) print(fLPF 截止频率 {lpf_cutoff/1e6:.1f} MHzFIR taps {num_taps}) print(f添加噪声的 SNR {SNR_dB:.1f} dB参考混频后信号功率) print() print(f图像已保存到目录{os.path.abspath(out_dir)}) print(主要图像文件) for fn in sorted(os.listdir(out_dir)): print( -, fn) print() print(说明) print( 1) 原始 IF实值在频域表现为 ±75 MHz 对称的两个带对应书中第 1 行。) print( 2) IQ 混频相当于把 75 MHz 带下移到 0 Hz负频谱部分会被移到 -150 MHz对应书中第 2、3 行。) print( 3) 低通滤波会保留靠近 0 的基带去掉远处的镜像对应书中第 4、5 行。) print( 4) 采样会在频域产生每 Fs 周期的谱复制对应书中第 6、7 行若 LPF 过宽或 Fs 过低会造成频谱重叠混叠。) print() print(如果需要) print( - 我可以把脚本改为在绘图窗口直接弹出显示交互式或把每张图的分辨率 / 轴范围 / LPF 参数进一步调优。) print( - 或者我可以把脚本改为 Jupyter ipywidgets 交互版实时调整 SNR、Fs、LPF 截止等参数。)运行结果仿真参数中文说明 -------------------------------------------- 内部等效采样 fs_cont 500.0 MHz仿真样本数 N 50000 IF 中心频率 f_center 75.0 MHz信号带宽 40.0 MHz双边带 目标 ADC 采样率 Fs 50.0 MHz抽取因子 decim 10实际采样率 fs_sampled 50.000 MHz LPF 截止频率 25.0 MHzFIR taps 801 添加噪声的 SNR 20.0 dB参考混频后信号功率 图像已保存到目录D:\workplace\LLM\sim_plots 主要图像文件 - 01_if_spectrum.png - 02_mixed_spectrum.png - 03_mixed_noisy_spectrum.png - 04_filtered_spectrum.png - 05_sampled_spectrum.png - time_if.png - time_mixed_noisy.png - time_sampled.png 说明 1) 原始 IF实值在频域表现为 ±75 MHz 对称的两个带对应书中第 1 行。 2) IQ 混频相当于把 75 MHz 带下移到 0 Hz负频谱部分会被移到 -150 MHz对应书中第 2、3 行。 3) 低通滤波会保留靠近 0 的基带去掉远处的镜像对应书中第 4、5 行。 4) 采样会在频域产生每 Fs 周期的谱复制对应书中第 6、7 行若 LPF 过宽或 Fs 过低会造成频谱重叠混叠。运行可视化