MIMO技术核心概念回顾
在开始仿真之前,快速回顾一下MIMO的核心思想:

- 多天线:在发送端和接收端都使用多个天线。
- 空间分集:通过多个独立的空间路径传输相同的数据,可以显著对抗信道衰落,提高链路的可靠性,常用的方法有 Alamouti 空时编码(2x2 MIMO的特例)和 空频编码。
- 空间复用:在相同的频带上,同时传输多个独立的数据流,从而成倍地提高系统容量,一个 2x2 MIMO 理论上可以将信道容量翻倍,代表算法是 贝尔实验室分层空时架构。
- 波束赋形:通过调整各天线信号的相位和幅度,将信号能量集中指向期望的用户,从而提高信号强度和信噪比。
本示例将重点实现最经典的 2x2 MIMO Alamouti 空时编码系统,因为它结构清晰,能很好地展示MIMO的基本原理。
MIMO系统仿真基本流程
一个完整的MIMO链路仿真通常遵循以下步骤:
- 参数配置:设置仿真所需的基本参数,如天线数量、调制方式、信噪比范围、仿真点数等。
- 信道建模:生成MIMO信道矩阵,这是仿真的核心,信道可以是瑞利衰落信道或莱斯衰落信道,对于空间分集,信道矩阵的元素通常是独立复高斯随机变量。
- 信源生成:产生随机的二进制比特流。
- 调制:将比特流映射为复杂的调制符号(如QPSK, 16QAM, 64QAM)。
- MIMO编码:根据所选的MIMO方案(如Alamouti)对符号进行编码。
- 信道传输:将编码后的信号通过MIMO信道进行传输,并叠加高斯白噪声。
- MIMO解码:接收端利用信道信息和相应的解码算法(如ZF, MMSE, ML)恢复出发送的符号。
- 解调:将恢复出的符号映射回比特流。
- 误码率计算:比较原始比特和接收比特,计算误码率。
- 结果可视化:绘制BER vs. SNR 的曲线图,评估系统性能。
完整MATLAB仿真示例:2x2 MIMO Alamouti 系统
下面是一个完整的、可运行的MATLAB脚本,用于仿真一个采用Alamouti编码的2x2 MIMO-QPSK系统。
仿真目标
比较以下三种方案的性能:

- SISO (Single-Input Single-Output):单天线收发,作为性能基准。
- MIMO ( Alamouti + MRC ):2x2 MIMO Alamouti编码,接收端采用最大比合并。
- MIMO ( Alamouti + ZF ):2x2 MIMO Alamouti编码,接收端采用迫零均衡。
%% MIMO MATLAB 仿真: 2x2 Alamouti 编码系统
% 作者: AI Assistant
% 日期: 2025-10-27
%% 1. 参数配置
clear; clc; close all;
N = 10^5; % 每个SNR点的仿真符号数
M = 4; % 调制阶数 (QPSK)
numBitsPerSym = log2(M); % 每个符号的比特数
numTx = 2; % 发射天线数
numRx = 2; % 接收天线数
% 定义SNR范围 (dB)
SNR_dB = 0:2:20;
numSNRs = length(SNR_dB);
% 预存储BER结果
ber_siso = zeros(1, numSNRs);
ber_mrc = zeros(1, numSNRs);
ber_zf = zeros(1, numSNRs);
%% 2. 主仿真循环
for i = 1:numSNRs
SNR = SNR_dB(i);
current_siso_errors = 0;
current_mrc_errors = 0;
current_zf_errors = 0;
% 生成随机比特流
tx_bits = randi([0 1], N * numBitsPerSym, 1);
% ------------------- SISO 仿真 -------------------
% 调制
tx_symbols_siso = bi2de(reshape(tx_bits, numBitsPerSym, [])', 'left-msb');
tx_symbols_siso = qammod(tx_symbols_siso, M, 'UnitAveragePower', true);
% 信道 (1x1 瑞利衰落)
h_siso = (randn(1,1) + 1i*randn(1,1)) / sqrt(2);
% 加噪声
noise_var_siso = 1 / (10^(SNR/10)); % 假设信号功率为1
rx_symbols_siso = h_siso * tx_symbols_siso + sqrt(noise_var_siso/2) * (randn(1,N) + 1i*randn(1,N));
% 解调 (MRC for SISO is just simple channel inversion)
rx_symbols_siso = rx_symbols_siso / conj(h_siso);
% 计算误码
tx_symbols_siso_demod = qamdemod(rx_symbols_siso, M, 'UnitAveragePower', true);
tx_bits_siso = de2bi(tx_symbols_siso_demod, numBitsPerSym, 'left-msb')';
tx_bits_siso = tx_bits_siso(:);
current_siso_errors = biterr(tx_bits, tx_bits_siso);
% ------------------- MIMO Alamouti 仿真 -------------------
% 调制
tx_symbols_mimo = bi2de(reshape(tx_bits, numBitsPerSym, [])', 'left-msb');
tx_symbols_mimo = qammod(tx_symbols_mimo, M, 'UnitAveragePower', true);
% Alamouti 编码 (N个符号 -> 2N个时隙)
% [s1 -s2*]
% [s2 s1*]
tx Alamouti symbols
tx_alamouti = zeros(2, 2*N);
for j = 1:N
s1 = tx_symbols_mimo(j);
s2 = tx_symbols_mimo(j+N);
tx_alamouti(1, 2*j-1) = s1;
tx_alamouti(1, 2*j) = -conj(s2);
tx_alamouti(2, 2*j-1) = s2;
tx_alamouti(2, 2*j) = conj(s1);
end
% 信道 (2x2 瑞利衰落)
% [h11 h12]
% [h21 h22]
h_mimo = (randn(numRx, numTx) + 1i*randn(numRx, numTx)) / sqrt(2);
% 接收信号 (2个天线 x 2N个时隙)
noise_var_mimo = 1 / (10^(SNR/10));
rx_mimo = h_mimo * tx_alamouti + sqrt(noise_var_mimo/2) * (randn(numRx, 2*N) + 1i*randn(numRx, 2*N));
% Alamouti 解码
% 接收信号矩阵 Y
% [y1 y2]
% [y3 y4]
% 解码后的信号为 H^H * Y
decoded_symbols = zeros(2, N);
for j = 1:N
% 提取两个时隙的接收信号
y1 = rx_mimo(1, 2*j-1);
y2 = rx_mimo(1, 2*j);
y3 = rx_mimo(2, 2*j-1);
y4 = rx_mimo(2, 2*j);
% 构建接收向量
Y = [y1; y3];
% Alamouti 解码矩阵 H^H * H
H_conj = conj(h_mimo);
H_H_H = H_conj' * h_mimo;
% 计算解码后的符号
s_hat = (1 / det(H_H_H)) * H_conj' * Y;
decoded_symbols(1, j) = s_hat(1);
decoded_symbols(2, j) = s_hat(2);
end
% 合并两个数据流并解调
rx_symbols_mimo = decoded_symbols(:);
% MRC 和 ZF 性能比较 (这里Alamouti解码已经隐含了合并过程)
% 我们直接比较解码后的符号
% --- MRC (最大比合并) ---
% 在Alamouti解码中,最优合并已经完成,这里直接计算BER
rx_symbols_mrc = rx_symbols_mimo;
tx_symbols_mrc_demod = qamdemod(rx_symbols_mrc, M, 'UnitAveragePower', true);
tx_bits_mrc = de2bi(tx_symbols_mrc_demod, numBitsPerSym, 'left-msb')';
tx_bits_mrc = tx_bits_mrc(:);
current_mrc_errors = biterr(tx_bits, tx_bits_mrc);
% --- ZF (迫零均衡) ---
% 如果我们想单独做ZF,可以这样:
% H_inv = pinv(h_mimo); % 使用伪逆
% rx_symbols_zf = H_inv * rx_mimo(:);
% 但在Alamouti结构中,上面的解码方式是等效的且更优的。
% 为了演示ZF,我们可以在符号层面进行迫零操作
H_inv = pinv(h_mimo); % 2x2 信道矩阵的伪逆
rx_symbols_zf_vec = H_inv * rx_mimo(:);
rx_symbols_zf = reshape(rx_symbols_zf_vec, 2, N);
tx_symbols_zf_demod = qamdemod(rx_symbols_zf(:), M, 'UnitAveragePower', true);
tx_bits_zf = de2bi(tx_symbols_zf_demod, numBitsPerSym, 'left-msb')';
tx_bits_zf = tx_bits_zf(:);
current_zf_errors = biterr(tx_bits, tx_bits_zf);
% 计算当前SNR点的BER
ber_siso(i) = current_siso_errors / (N * numBitsPerSym);
ber_mrc(i) = current_mrc_errors / (2 * N * numBitsPerSym); % 注意:MIMO传输了2倍的数据
ber_zf(i) = current_zf_errors / (2 * N * numBitsPerSym);
fprintf('SNR = %d dB, SISO BER = %e, MIMO Alamouti BER = %e, MIMO ZF BER = %e\n', ...
SNR_dB(i), ber_siso(i), ber_mrc(i), ber_zf(i));
end
%% 3. 结果可视化
figure;
semilogy(SNR_dB, ber_siso, 'b-o', 'LineWidth', 2, 'DisplayName', 'SISO');
hold on;
semilogy(SNR_dB, ber_mrc, 'r-s', 'LineWidth', 2, 'DisplayName', 'MIMO Alamouti + MRC');
semilogy(SNR_dB, ber_zf, 'g-^', 'LineWidth', 2, 'DisplayName', 'MIMO Alamouti + ZF');
grid on;
axis([min(SNR_dB) max(SNR_dB) 10^-4 1]);
xlabel('SNR (dB)');
ylabel('Bit Error Rate (BER)');'2x2 MIMO Alamouti 系统性能比较');
legend('show', 'Location', 'southwest');
代码关键模块解析
信道建模
h_mimo = (randn(numRx, numTx) + 1i*randn(numRx, numTx)) / sqrt(2);
randn生成标准正态分布(均值为0,方差为1)的随机数。1i*randn生成虚部,两者结合形成复高斯随机变量。- 除以
sqrt(2):为了保证信道系数的功率(即E[|h|^2])为1,这是无线信道仿真的标准做法,这使得信噪比的计算更直接。
Alamouti 编码
tx_alamouti = zeros(2, 2*N);
for j = 1:N
s1 = tx_symbols_mimo(j);
s2 = tx_symbols_mimo(j+N);
tx_alamouti(1, 2*j-1) = s1;
tx_alamouti(1, 2*j) = -conj(s2);
tx_alamouti(2, 2*j-1) = s2;
tx_alamouti(2, 2*j) = conj(s1);
end
- 将N个符号对
(s1, s2)编码成2x2的矩阵。 - 在第一个时隙,天线1发送
s1,天线2发送s2。 - 在第二个时隙,天线1发送
-conj(s2),天线2发送conj(s1)。 - 这种编码结构使得接收端可以非常简单地实现联合解码和合并。
Alamouti 解码
H_conj = conj(h_mimo); H_H_H = H_conj' * h_mimo; s_hat = (1 / det(H_H_H)) * H_conj' * Y;
H_conj'是信道矩阵h_mimo的共轭转置,也称为Hermitian转置。H_H_H是H^H * H,这是一个2x2的矩阵。s_hat = H^H * Y / (H^H * H)是Alamouti解码的核心公式,它等效于对两个天线接收到的信号进行线性合并,并完美地分离出原始的s1和s2。- 这种解码方式实现了最大似然检测的性能,并且在计算上非常高效。
误码率计算
ber_mrc(i) = current_mrc_errors / (2 * N * numBitsPerSym);
- 注意分母:对于2x2 MIMO Alamouti系统,我们实际上在2个时隙内传输了2个符号,总的传输比特数是
2 * N * numBitsPerSym,而SISO系统是N * numBitsPerSym,这是比较BER时需要注意的地方。 - 如果你想比较频谱效率,应该确保两者在相同带宽下传输相同数量的比特,但在这个仿真中,我们主要关注MIMO相对于SISO的性能增益。
如何扩展和进阶
这个示例是MIMO仿真的一个绝佳起点,您可以基于此进行扩展:
- 空间复用:修改代码,实现一个简单的V-BLAST系统,这需要更复杂的检测算法,如串行干扰消除。
- 更高级的信道模型:使用MATLAB的
comm.RayleighChannel或comm.TDLChannel对象来创建具有时延扩展、多普勒频移等更真实特性的信道。 - OFDM + MIMO:将MIMO技术与OFDM结合,这是5G等现代通信系统的核心,您需要在每个OFDM子载波上执行上述MIMO处理。
- 波束赋形:在发送端,设计一个预编码矩阵(如基于信道状态信息的ZF或MMSE预编码),将信号能量聚焦到接收端。
- 其他调制方式:尝试使用16QAM或64QAM,观察不同调制方式下的性能差异。
- 使用MATLAB通信工具箱:上述代码是“手动”实现的,有助于理解原理,在实际工程中,可以使用
comm.MIMOEncoder和comm.MIMODetector等内置对象来简化代码,它们经过了高度优化。
希望这个详细的指南能帮助您顺利开始MIMO技术的MATLAB仿真之旅!

