QPSK调制与解调详解
一、QPSK基本原理
QPSK(Quadrature Phase Shift Keying)是一种高效的数字调制技术,通过载波的四种相位状态传输数据。每个符号携带2比特信息,频谱利用率是BPSK的两倍。
数学表达式:
s(t) = I(t)·cos(2πf₀t) - Q(t)·sin(2πf₀t)
其中:
I(t) = 同相分量(In-phase)
Q(t) = 正交分量(Quadrature)
f₀ = 载波频率
星座图映射规则(格雷码编码):
比特对 | 相位 | I分量 | Q分量 | 复数表示 |
---|---|---|---|---|
00 | 45° | +1/√2 | +1/√2 | (1+1j)/√2 |
01 | 135° | -1/√2 | +1/√2 | (-1+1j)/√2 |
11 | 225° | -1/√2 | -1/√2 | (-1-1j)/√2 |
10 | 315° | +1/√2 | -1/√2 | (1-1j)/√2 |
二、调制解调流程
调制过程:
- 二进制数据分组成2比特符号
- 映射为I/Q两路基带信号
- 分别与正交载波相乘
- 合成射频信号
解调过程:
- 接收信号与正交载波相乘
- 低通滤波提取基带信号
- 采样判决I/Q分量
- 逆映射恢复二进制数据
具体调制解调流程如下图所示:
三、Python完整仿真代码
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter
# 参数设置
num_symbols = 1000 # 符号数
sps = 16 # 每符号采样数
sample_rate = 1e6 # 采样率 (Hz)
carrier_freq = 0.1e6 # 载波频率 (Hz)
noise_power = 0.01 # 噪声功率
# 生成随机二进制数据
data = np.random.randint(0, 2, num_symbols * 2)
# ================== QPSK调制 ==================
# 数据分组:每2比特 -> 1个符号
symbols = data.reshape(-1, 2)
# 比特映射(格雷码)
def bits_to_qpsk(bits):
if bits[0] == 0 and bits[1] == 0: return (1 + 1j) / np.sqrt(2)
if bits[0] == 0 and bits[1] == 1: return (-1 + 1j) / np.sqrt(2)
if bits[0] == 1 and bits[1] == 1: return (-1 - 1j) / np.sqrt(2)
if bits[0] == 1 and bits[1] == 0: return (1 - 1j) / np.sqrt(2)
# 生成符号流
symbol_stream = np.array([bits_to_qpsk(sym) for sym in symbols])
# 上采样(插值)
tx_signal = np.zeros(num_symbols * sps, dtype=complex)
tx_signal[::sps] = symbol_stream
# 设计成型滤波器(根升余弦)
beta = 0.35 # 滚降系数
t = np.arange(-4*sps, 4*sps) / sps
h = np.sinc(t) * np.cos(np.pi*beta*t) / (1 - (2*beta*t)**2)
h = h / np.sqrt(np.sum(h**2)) # 归一化
# 脉冲成形
tx_shaped = np.convolve(tx_signal, h, mode='same')
# 载波调制
t = np.arange(len(tx_shaped)) / sample_rate
tx_real = np.real(tx_shaped) * np.cos(2*np.pi*carrier_freq*t)
tx_imag = np.imag(tx_shaped) * -np.sin(2*np.pi*carrier_freq*t)
tx_wave = tx_real + tx_imag
# ================== 信道模拟 ==================
# 添加高斯白噪声
noise = np.sqrt(noise_power/2) * (np.random.randn(len(tx_wave)) + 1j*np.random.randn(len(tx_wave)))
rx_signal = tx_wave + noise
# ================== QPSK解调 ==================
# 正交下变频
t = np.arange(len(rx_signal)) / sample_rate
rx_i = rx_signal * np.cos(2*np.pi*carrier_freq*t)
rx_q = rx_signal * -np.sin(2*np.pi*carrier_freq*t)
# 低通滤波
def butter_lowpass(cutoff, fs, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='low', analog=False)
return b, a
b, a = butter_lowpass(carrier_freq/2, sample_rate)
rx_i_filt = lfilter(b, a, rx_i)
rx_q_filt = lfilter(b, a, rx_q)
rx_baseband = rx_i_filt + 1j*rx_q_filt
# 匹配滤波
rx_shaped = np.convolve(rx_baseband, h, mode='same')
# 采样判决
rx_samples = rx_shaped[sps//2::sps] # 符号中心点采样
# 解映射
def qpsk_to_bits(symbol):
angle = np.angle(symbol)
if angle >= 0 and angle < np.pi/2: return [0, 0]
if angle >= np.pi/2 and angle < np.pi: return [0, 1]
if angle < 0 and angle >= -np.pi/2: return [1, 0]
return [1, 1]
rx_bits = []
for sym in rx_samples:
rx_bits.extend(qpsk_to_bits(sym))
rx_bits = np.array(rx_bits[:len(data)]) # 截断至原始长度
# ================== 性能分析 ==================
# 计算误码率
ber = np.sum(data != rx_bits) / len(data)
print(f"误码率 (BER): {ber:.2%}")
# 绘制星座图
plt.figure(figsize=(10, 8))
plt.scatter(np.real(rx_samples), np.imag(rx_samples), alpha=0.6)
plt.axhline(0, color='k', linestyle='--')
plt.axvline(0, color='k', linestyle='--')
plt.grid(True)
plt.title("接收信号星座图")
plt.xlabel("I分量")
plt.ylabel("Q分量")
plt.axis('equal')
plt.show()
四、关键代码解析
- 格雷码映射:最小化相邻符号的比特差异,降低误码率
- 脉冲成形:使用根升余弦滤波器消除码间干扰
- 相干解调:需要精确的载波同步
- 匹配滤波:最大化信噪比的最佳接收方案
五、仿真结果分析
-
星座图:展示接收信号在I-Q平面的分布
-
误码率:量化系统性能,典型值10⁻²~10⁻⁵
误码率 (BER): 0.05%
- 噪声影响:噪声功率增大时,星座点会扩散
六、实际应用场景
- 卫星通信(DVB-S2标准)
- 4G/5G移动通信(LTE控制信道)
- WiFi(802.11a/g/n)
通过调整噪声功率(
noise_power
参数),可观察不同信噪比下的系统性能变化。在理想信道中,BER趋近于0;当噪声功率超过0.5时,误码率显著上升。
研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)