基于MATLAB和Simulink的2ASK、2PSK和2FSK系统设计、误码率性能分析和比较包含代码源代码文件仿真文件报告*2两份1万字报告第一步自动生成 Simulink 模型运行此脚本将自动创建一个包含 2ASK, 2PSK, 2FSK 三路并行系统的Simulink模型包含高斯白噪声信道和误码率计算模块。保存为 create_comms_model.m 并运行matlab编辑1function create_comms_model()2 model_name ‘comms_system’;3 if exist(model_name, ‘model’)4 close_system(model_name, 0);5 delete_system(model_name);6 end78 new_system(model_name);9 open_system(model_name);1011 % 全局参数设置 (在Model Workspace中定义) 12 % 这些变量将在主脚本中赋值13 param_list {‘Fs’, ‘Fc’, ‘Rb’, ‘EbNo_vec’};14 for i 1:length(param_list)15 add_block(‘simulink/Sources/Constant’, [model_name ‘/’ param_list{i}], …16 ‘Value’, ‘0’, ‘Position’, [50 50i40 80 80i40], ‘ShowName’, ‘on’);17 end1819 % 公共信号源 20 % 伯努利二进制发生器21 add_block(‘comm/Bernoulli Binary Generator’, [model_name ‘/Source’], …22 ‘Position’, [100 200 130 230], ‘SampleTime’, ‘1/Rb’, ‘SamplesPerFrame’, ‘1’);2324 % 示波器25 add_block(‘simulink/Sinks/Scope’, [model_name ‘/Scope_Constellation’], …26 ‘Position’, [900 100 930 130], ‘NumInputPorts’, ‘3’);2728 % 循环创建三个子系统 (ASK, PSK, FSK) 29 mod_types {‘2ASK’, ‘2PSK’, ‘2FSK’};30 y_positions [200, 350, 500];3132 for i 1:333 m_type mod_types{i};34 y_base y_positions(i);3536 % 1. 调制器37 if strcmp(m_type, ‘2ASK’)38 blk_name ‘DSB-AM Modulator Passband’;39 param_val ‘0’; % Carrier phase40 elseif strcmp(m_type, ‘2PSK’)41 blk_name ‘M-PSK Modulator Baseband’; % 使用基带然后上变频或者直接Passband42 % 为了统一我们使用简单的乘法器实现2PSK (BPSK)43 blk_name ‘Product’;44 else % 2FSK45 blk_name ‘Continuous Phase Frequency Modulator’;46 end4748 % 为了简化模型结构直接使用 MATLAB Function 模块实现调制解调这样更灵活且代码可控49 % 调制模块50 add_block(‘simulink/User-Defined Functions/MATLAB Function’, [model_name ‘/Mod_’ m_type], …51 ‘Position’, [200 y_base 250 y_base40], ‘Script’, get_mod_script(m_type));5253 % 加性高斯白噪声信道 (AWGN)54 add_block(‘comm/AWGN Channel’, [model_name ‘/Channel_’ m_type], …55 ‘Position’, [300 y_base 330 y_base40], ‘EbNo’, ‘EbNo_db’, ‘Mode’, ‘Signal to noise ratio (Eb/No)’, ‘SamplesPerSymbol’, ‘Fs/Rb’);5657 % 解调模块58 add_block(‘simulink/User-Defined Functions/MATLAB Function’, [model_name ‘/Demod_’ m_type], …59 ‘Position’, [400 y_base 450 y_base40], ‘Script’, get_demod_script(m_type));6061 % 误码率计算62 add_block(‘comm/Error Rate Calculation’, [model_name ‘/BER_Calc_’ m_type], …63 ‘Position’, [500 y_base 530 y_base40], ‘ComputeDelay’, ‘0’);6465 % 显示BER66 add_block(‘simulink/Sinks/Display’, [model_name ‘/BER_Display_’ m_type], …67 ‘Position’, [600 y_base 630 y_base40]);6869 % 连线70 add_line(model_name, ‘Source/1’, [‘Mod_’ m_type ‘/1’]);71 add_line(model_name, [‘Mod_’ m_type ‘/1’], [‘Channel_’ m_type ‘/1’]);72 add_line(model_name, [‘Channel_’ m_type ‘/1’], [‘Demod_’ m_type ‘/1’]);73 add_line(model_name, [‘Demod_’ m_type ‘/1’], [‘BER_Calc_’ m_type ‘/1’]);74 add_line(model_name, ‘Source/1’, [‘BER_Calc_’ m_type ‘/2’]); % 原始信号输入75 add_line(model_name, [‘BER_Calc_’ m_type ‘/1’], [‘BER_Display_’ m_type ‘/1’]);7677 % 将解调后的信号连到示波器 (可选用于观察波形)78 % add_line(model_name, [‘Demod_’ m_type ‘/1’], [‘Scope_Constellation/’ num2str(i)]);79 end8081 % 设置模型回调以便从工作区加载参数82 set_param(model_name, ‘PreLoadFcn’, ‘load_comms_params;’);8384 save_system(model_name);85 fprintf(‘✅ Simulink 模型 “%s.slx” 已生成。\n’, model_name);86end8788function script get_mod_script(type)89 switch type90 case ‘2ASK’91 script [‘function y fcn(u)\n’ …92 ‘persistent t_prev carrier_phase;\n’ …93 ‘if isempty(t_prev), t_prev 0; carrier_phase 0; end\n’ …94 ‘Fs get_param_from_base(’‘Fs’‘); Fc get_param_from_base(’‘Fc’‘);\n’ …95 ‘dt 1/Fs;\n’ …96 ‘t t_prev dt;\n’ …97 ‘carrier cos(2piFct carrier_phase);\n’ …98 ‘y u * carrier; %% OOK Modulation\n’ …99 ‘t_prev t;\n’];100 case ‘2PSK’101 script [‘function y fcn(u)\n’ …102 ‘persistent t_prev carrier_phase;\n’ …103 ‘if isempty(t_prev), t_prev 0; carrier_phase 0; end\n’ …104 ‘Fs get_param_from_base(’‘Fs’‘); Fc get_param_from_base(’‘Fc’‘);\n’ …105 ‘dt 1/Fs;\n’ …106 ‘t t_prev dt;\n’ …107 phase (u0)pi; %% BPSK: 0-0, 1-pi (or vice versa)\n’ …108 y cos(2piFct phase);\n’ …109 ‘t_prev t;\n’];110 case ‘2FSK’111 script [‘function y fcn(u)\n’ …112 ‘persistent t_prev phase_acc;\n’ …113 ‘if isempty(t_prev), t_prev 0; phase_acc 0; end\n’ …114 ‘Fs get_param_from_base(’‘Fs’‘); Fc get_param_from_base(’‘Fc’‘);\n’ …115 ‘deviation Fs/4; %% Standard FSK deviation\n’ …116 ‘dt 1/Fs;\n’ …117 ‘t t_prev dt;\n’ …118 freq Fc (u2 - 1)deviation; %% 0-Fc-fd, 1-Fcfd\n’ …119 phase_acc phase_acc 2pifreqdt;\n’ …120 ‘y cos(phase_acc);\n’ …121 ‘t_prev t;\n’];122 end123end124125function script get_demod_script(type)126 switch type127 case ‘2ASK’128 script [‘function y fcn(u)\n’ …129 ‘persistent t_prev carrier_phase filter_state;\n’ …130 ‘if isempty(t_prev), t_prev 0; carrier_phase 0; filter_state 0; end\n’ …131 ‘Fs get_param_from_base(’‘Fs’‘); Fc get_param_from_base(’‘Fc’‘); Rb get_param_from_base(’‘Rb’‘);\n’ …132 ‘dt 1/Fs;\n’ …133 ‘t t_prev dt;\n’ …134 ‘carrier cos(2piFct carrier_phase);\n’ …135 ‘mixed u * carrier; %% Coherent Demod\n’ …136 ‘%% Simple LPF using moving average or discrete filter approximation\n’ …137 filter_state 0.99filter_state 0.01*mixed; %% Very rough LPF\n’ …138 ‘%% Better: Downsample and threshold\n’ …139 ‘y double(filter_state 0.5); %% Threshold decision\n’ …140 ‘%% Note: For accurate BER, we need symbol synchronization. \n’ …141 ‘%% Simplified: Assume perfect sync and sample at end of bit period in main loop logic is hard in block.\n’ …142 ‘%% Alternative: Use Comm.BPSKDemodulator block logic inside here is complex.\n’ …143 ‘%% Let us use a simpler energy detection for ASK non-coherent or coherent with integrator.\n’ …144 ‘%% Re-implementing simple integrate and dump:\n’ …145 ‘persistent int_val sample_count;\n’ …146 ‘if isempty(int_val), int_val0; sample_count0; end\n’ …147 ‘int_val int_val mixed;\n’ …148 ‘sample_count sample_count 1;\n’ …149 ‘samples_per_bit Fs/Rb;\n’ …150 ‘if sample_count samples_per_bit\n’ …151 ’ y double(int_val 0);\n’ …152 ’ int_val 0; sample_count 0;\n’ …153 ‘else\n’ …154 ’ y -1; %% Hold previous or invalid, BER block ignores -1 if configured?\n’ …155 ’ %% Actually, let output the last valid bit to keep stream aligned\n’ …156 ’ y double(int_val 0); %% Output current estimate continuously for simplicity in this demo\n’ …157 ‘end\n’ …158 ‘t_prev t;\n’];159 % 修正上面的逻辑在Simulink单步中很难完美同步。160 % 为了保证BER计算准确我们将使用Comm库的标准解调器逻辑的简化版或者依赖主脚本的离线处理。161 % 但用户要求Simulink。这里使用一个简化的相干解调采样保持。162 script [‘function y fcn(u)\n’ …163 ‘coder.extrinsic(’‘demod_signal’‘);\n’ …164 ‘type ‘’’ type ‘’‘;\n’ …165 ‘y demod_signal(u, type);\n’];166 case ‘2PSK’167 script [‘function y fcn(u)\n’ …168 ‘coder.extrinsic(’‘demod_signal’‘);\n’ …169 ‘type ‘’’ type ‘’‘;\n’ …170 ‘y demod_signal(u, type);\n’];171 case ‘2FSK’172 script [‘function y fcn(u)\n’ …173 ‘coder.extrinsic(’‘demod_signal’‘);\n’ …174 ‘type ‘’’ type ‘’‘;\n’ …175 ‘y demod_signal(u, type);\n’];176 end177end178179% 辅助函数从Base工作区获取180function val get_param_from_base(varname)181 evalin(‘base’, [val ’ varname ‘;’]);182end183184% 外部解调函数 (将在主脚本中定义或在路径下)185% 注意由于simulink调用extrinsic我们需要确保该函数在路径中186% 这里我们动态创建一个临时文件或者在主脚本中定义并在运行前添加路径187% 为了简洁我们在主脚本中定义这个函数并确保它在运行sim之前存在。注意上面的Simulink模型使用了 coder.extrinsic 调用外部MATLAB函数进行解调这是处理复杂同步逻辑的最稳健方法。我们需要在主脚本中定义 demod_signal 函数。 第二步主仿真脚本 (误码率分析)保存为 main_simulation.m。这个脚本将设置参数循环不同的信噪比 (Eb/N0)运行Simulink收集误码率数据并绘图。matlab编辑1%% 主程序2ASK, 2PSK, 2FSK 系统仿真与误码率分析2clear; clc; close all;34% 1. 系统参数设置 5Fs 10000; % 采样频率 (Hz)6Fc 1000; % 载波频率 (Hz)7Rb 1000; % 比特率 (bps)8bits_per_sim 10000; % 每次仿真发送的比特数9EbNo_dB_range 0:2:12; % 信噪比范围 (dB)1011% 确保模型存在12model_name ‘comms_system’;13if ~exist([model_name ‘.slx’], ‘file’)14 fprintf(‘⚠️ 未找到模型正在生成…\n’);15 create_comms_model();16 % 需要创建外部解调函数文件17 create_demod_function();18end1920% 初始化结果存储21ber_ask zeros(size(EbNo_dB_range));22ber_psk zeros(size(EbNo_dB_range));23ber_fsk zeros(size(EbNo_dB_range));2425fprintf(‘ 开始仿真循环 (这可能几分钟)…\n’);2627% 2. 循环仿真不同 Eb/N0 28for i 1:length(EbNo_dB_range)29 EbNo_db EbNo_dB_range(i);30 fprintf(‘当前 Eb/N0 %d dB …\n’, EbNo_db);3132 % 设置工作区变量供 Simulink 使用33 assignin(‘base’, ‘Fs’, Fs);34 assignin(‘base’, ‘Fc’, Fc);35 assignin(‘base’, ‘Rb’, Rb);36 assignin(‘base’, ‘EbNo_db’, EbNo_db);3738 % 重置误码率计算器39 set_param([model_name ‘/BER_Calc_2ASK’], ‘ResetStatus’, ‘on’);40 set_param([model_name ‘/BER_Calc_2PSK’], ‘ResetStatus’, ‘on’);41 set_param([model_name ‘/BER_Calc_2FSK’], ‘ResetStatus’, ‘on’);4243 % 运行仿真44 % 设置仿真时间发送 bits_per_sim 个比特所需的时间45 sim_time bits_per_sim / Rb;46 simOut sim(model_name, ‘StopTime’, num2str(sim_time), ‘SrcWorkspace’, ‘current’, ‘DisplayProgress’, ‘off’);4748 % 获取误码率结果 (从Display模块或To Workspace获取这里简单起见从simOut提取如果配置了)49 % 由于Display模块不直接导出到simOut我们修改策略50 % 在 create_comms_model 中应该添加 To Workspace 模块或者在这里读取 Display 的 Value (不可行)51 % 最佳方案修改模型添加 To Workspace或者直接在 MATLAB 中计算 (但这违背了联合仿真初衷)52 % 让我们假设用户在第一次运行时我们动态添加了 To Workspace 模块。5354 inject_ber_logs(model_name);5556 simOut sim(model_name, ‘StopTime’, num2str(sim_time), ‘SrcWorkspace’, ‘current’, ‘DisplayProgress’, ‘off’);5758 % 提取数据 (变量名在 inject_ber_logs 中定义)59 ber_stats_ask simOut.get(‘ber_log_ask’);60 ber_stats_psk simOut.get(‘ber_log_psk’);61 ber_stats_fsk simOut.get(‘ber_log_fsk’);6263 % ErrorRateCalculation 输出格式[NumErrors, TotalBits, ErrorRate]64 if ~isempty(ber_stats_ask) ber_stats_ask(2) 065 ber_ask(i) ber_stats_ask(3);66 else67 ber_ask(i) 0; % 防止除零或无错误68 end6970 if ~isempty(ber_stats_psk) ber_stats_psk(2) 071 ber_psk(i) ber_stats_psk(3);72 else73 ber_psk(i) 0;74 end7576 if ~isempty(ber_stats_fsk) ber_stats_fsk(2) 077 ber_fsk(i) ber_stats_fsk(3);78 else79 ber_fsk(i) 0;80 end81end8283% 3. 理论值计算 (用于对比) 84% 2ASK (相干): 0.5 * erfc(sqrt(EbNo/4)) - 实际上通常是非相干或相干这里按相干算85% 2ASK 相干解调理论误码率: 0.5 * erfc(sqrt(EbNo/4))? 不是 0.5erfc(sqrt(EbNo/2)) for OOK?86% OOK (On-Off Keying) 相干: 0.5 * erfc(sqrt(EbNo/4)) (平均能量考虑)87% 2PSK (BPSK): 0.5 * erfc(sqrt(EbNo))88% 2FSK (相干): 0.5 * erfc(sqrt(EbNo/2))89% 2FSK (非相干): 0.5 * exp(-EbNo/2)9091EbNo_lin 10.^(EbNo_dB_range/10);92theoretical_ask 0.5 * erfc(sqrt(EbNo_lin/4)); % 近似93theoretical_psk 0.5 * erfc(sqrt(EbNo_lin));94theoretical_fsk 0.5 * erfc(sqrt(EbNo_lin/2));9596% 4. 绘图 97figure(‘Color’, ‘w’, ‘Name’, ‘BER Performance Comparison’);98semilogy(EbNo_dB_range, ber_ask, ‘ro-’, ‘LineWidth’, 2, ‘DisplayName’, ‘Sim 2ASK’);99hold on;100semilogy(EbNo_dB_range, theoretical_ask, ‘r–’, ‘DisplayName’, ‘Theory 2ASK’);101102semilogy(EbNo_dB_range, ber_psk, ‘bs-’, ‘LineWidth’, 2, ‘DisplayName’, ‘Sim 2PSK’);103semilogy(EbNo_dB_range, theoretical_psk, ‘b–’, ‘DisplayName’, ‘Theory 2PSK’);104105semilogy(EbNo_dB_range, ber_fsk, ‘g^-’, ‘LineWidth’, 2, ‘DisplayName’, ‘Sim 2FSK’);106semilogy(EbNo_dB_range, theoretical_fsk, ‘g–’, ‘DisplayName’, ‘Theory 2FSK’);107108grid on;109xlabel(‘Eb/N0 (dB)’);110ylabel(‘Bit Error Rate (BER)’);111title(‘BER Performance of 2ASK, 2PSK, and 2FSK over AWGN Channel’);112legend(‘Location’, ‘southwest’);113xlim([min(EbNo_dB_range) max(EbNo_dB_range)]);114ylim([1e-5 1]);115116fprintf(‘ 仿真完成图表已生成。\n’);117118%% 辅助函数 119120function create_demod_function()121 % 创建 demod_signal.m 文件122 code […123 ‘function y demod_signal(u, type)\n’ …124 ‘persistent buffer t_count Fs Rb carrier_phase;\n’ …125 ‘if isempty(buffer), buffer []; t_count 0; carrier_phase 0;\n’ …126 ’ Fs get_param_from_base(‘‘Fs’’); Rb get_param_from_base(‘‘Rb’’);\n’ …127 ‘end\n’ …128 ‘buffer [buffer; u];\n’ …129 ‘t_count t_count 1;\n’ …130 ‘samples_per_bit round(Fs/Rb);\n’ …131 ‘y 0; %% Default hold\n’ …132 ‘if length(buffer) samples_per_bit\n’ …133 ’ bit_data buffer(1:samples_per_bit);\n’ …134 ’ buffer []; %% Clear buffer\n’ …135 ’ if strcmp(type, ‘‘2ASK’’)\n’ …136 ’ %% Coherent Demod: Multiply by carrier and integrate\n’ …137 ’ t_vec (0:samples_per_bit-1)/Fs;\n’ …138 ’ carrier cos(2piget_param_from_base(‘‘Fc’’)t_vec);\n’ …139 ’ metric sum(bit_data .carrier);\n’ …140 ’ y double(metric 0);\n’ …141 ’ elseif strcmp(type, ‘‘2PSK’’)\n’ …142 ’ %% Coherent Demod: Correlate with carrier\n’ …143 ’ t_vec (0:samples_per_bit-1)/Fs;\n’ …144 ’ carrier cos(2piget_param_from_base(‘‘Fc’’)t_vec);\n’ …145 ’ metric sum(bit_data .carrier);\n’ …146 ’ y double(metric 0); %% Phase flip logic\n’ …147 ’ elseif strcmp(type, ‘‘2FSK’’)\n’ …148 ’ %% Non-coherent or Coherent Energy Detection\n’ …149 ’ fd get_param_from_base(‘‘Fs’’)/4;\n’ …150 ’ fc get_param_from_base(‘‘Fc’’);\n’ …151 ’ t_vec (0:samples_per_bit-1)/Fs;\n’ …152 ’ c0 cos(2pi*(fc-fd)t_vec);\n’ …153 ’ c1 cos(2pi*(fcfd)t_vec);\n’ …154 ’ e0 sum(bit_data .c0);\n’ …155 ’ e1 sum(bit_data .* c1);\n’ …156 ’ y double(e1 e0);\n’ …157 ’ end\n’ …158 ‘end\n’];159160 fid fopen(‘demod_signal.m’, ‘w’);161 fprintf(fid, ‘%s’, code);162 fclose(fid);163164 % 同时补充 get_param_from_base 到这个文件作用域或确保主空间有165 % 由于 demod_signal 被 extrinsic 调用它在 base workspace 运行所以没问题166 fprintf(‘✅ 解调函数 demod_signal.m 已创建。\n’);167end168169function inject_ber_logs(model_name)170 % 添加 To Workspace 模块来记录 BER 统计171 mods {‘2ASK’, ‘2PSK’, ‘2FSK’};172 vars {‘ber_log_ask’, ‘ber_log_psk’, ‘ber_log_fsk’};173174 for i 1:3175 blk_path [model_name ‘/ToWS_BER_’ mods{i}];176 try177 get_param(blk_path, ‘BlockType’);178 catch179 add_block(‘simulink/Sinks/To Workspace’, blk_path, …180 ‘VariableName’, vars{i}, ‘SaveFormat’, ‘Array’, …181 ‘Decimation’, ‘1’, ‘LimitDataPoints’, ‘off’, …182 ‘Position’, [700 200(i-1)*150 730 230(i-1)*150]);183 add_line(model_name, [‘BER_Calc_’ mods{i} ‘/1’], blk_path);184 end185 end186end187188function val get_param_from_base(varname)189 evalin(‘base’, [val ’ varname ‘;’]);190end