matlab显示未定义与uint8类型输入参数对应的函数sqrt

时间: 2024-02-05 12:13:24 AIGC 浏览: 262
这个错误通常是因为你试图将一个uint8类型的变量作为sqrt函数的输入参数,而sqrt函数不能处理这种类型。这是因为sqrt函数只能处理双精度浮点数或单精度浮点数。要解决这个问题,你需要将输入参数转换为double类型。你可以使用double()函数来将uint8类型的变量转换为double类型,例如: ``` a = uint8(100); b = double(a); c = sqrt(b); ``` 在上面的代码中,我们首先将a定义为一个uint8类型的变量,然后使用double()函数将其转换为double类型的变量b。最后,我们将b作为sqrt函数的输入参数,得到了正确的结果。
相关问题

MATLAB中出现未定义与 'uint8' 类型的输入参数相对应的函数 'sqrt'这个问题,如何解决?

这个问题通常是由于输入的数据类型不正确导致的。sqrt函数只能接受浮点数或复数类型的输入,不能接受 uint8 类型的输入。要解决这个问题,可以将输入数据类型转换为浮点数或复数类型。 例如,如果要对 uint8 类型的图像进行平方根运算,可以先将图像转换为 double 类型: ```matlab % 假设 im 是 uint8 类型的图像 im_double = im2double(im); im_sqrt = sqrt(im_double); ``` 这样就可以避免出现未定义与 'uint8' 类型的输入参数相对应的函数 'sqrt'的问题了。

未定义与 'uint8' 类型的输入参数相对应的函数 'sqrt'。 出错 Untitled3 (line 17) SXY = sqrt(GX*GX + GY*GY); %某一点的梯度值

这个错误是因为您在使用MATLAB中的sqrt函数时,输入了一个uint8类型的参数。sqrt函数的输入参数应该是一个实数。 您可以通过将输入参数转换为double类型来解决这个问题。例如,您可以使用以下代码: ``` SXY = sqrt(double(GX) * double(GX) + double(GY) * double(GY)); ``` 这将把GX和GY转换为double类型,然后再进行平方和开方运算。
阅读全文

相关推荐

帮我修改msrcr的函数,修改的时候要注意整个代码和函数之间的配合 clear,clc,close all % 加载测试图像 low_light = imread('D:\SVD\实验素材\ExDark数据库\Table\2015_06907.jpg'); reference = imread('D:\SVD\实验素材\ExDark数据库\Table\2015_06907.jpg'); % 正常光照参考图像 % 初始化结果表 methods = {'HE', 'BIMEF', 'LIME', 'MSRCR', 'HSV-SVD-CLAHE'}; results = zeros(5, 4); % 5种方法 x 4个指标 % 评估每种方法 enhanced_he = he_method(low_light); [results(1,1), results(1,2), results(1,3), results(1,4)] = evaluate_image(enhanced_he, reference); enhanced_bimef = bimef(low_light); [results(2,1), results(2,2), results(2,3), results(2,4)] = evaluate_image(enhanced_bimef, reference); enhanced_lime = lime_method(low_light); [results(3,1), results(3,2), results(3,3), results(3,4)] = evaluate_image(enhanced_lime, reference); enhanced_msrcr = msrcr_method(low_light); [results(4,1), results(4,2), results(4,3), results(4,4)] = evaluate_image(enhanced_msrcr, reference); enhanced_proposed = hsv_svd_clahe(low_light); [results(5,1), results(5,2), results(5,3), results(5,4)] = evaluate_image(enhanced_proposed, reference); % 显示结果 fprintf('%-25s %8s %8s %12s %10s\n', 'Method', 'PSNR', 'SSIM', 'Avg Gradient', 'Entropy'); fprintf('-------------------------------------------------------------\n'); for i = 1:5 fprintf('%-25s %8.2f %8.4f %12.4f %10.4f\n', ... methods{i}, results(i,1), results(i,2), results(i,3), results(i,4)); end % 可视化结果 figure('Position', [100, 100, 1200, 800]); subplot(2,3,1); imshow(low_light); title('原始低照度图像'); subplot(2,3,2); imshow(enhanced_he); title('HE'); subplot(2,3,3); imshow(enhanced_bimef); title('BIMEF'); subplot(2,3,4); imshow(enhanced_lime); title('LIME'); subplot(2,3,5); imshow(enhanced_msrcr); title('MSRCR'); subplot(2,3,6); imshow(enhanced_proposed); title('HSV-SVD-CLAHE'); % 本文方法 hsv_svd_clahe function enhanced_img = hsv_svd_clahe(img, beta, gamma) % HSV_SVD_CLAHE 低照度图像增强算法(双系数调节) % 输入: % img - 原始低照度图像 (uint8格式) % beta - 主成分增强系数 (可选,默认1.8) % gamma - 次成分抑制系数 (可选,默认0.9) % 输出: % enhanced_img - 增强后的图像 (uint8格式) % 参数默认值设置 if nargin < 2, beta = 1.8; end % 主成分增强系数 if nargin < 3, gamma = 0.9; end % 次成分抑制系数 % 转换为double类型并归一化 img = im2double(img); % RGB转HSV hsv_img = rgb2hsv(img); V = hsv_img(:,:,3); % 提取亮度分量 % 奇异值分解 [U, S, V_svd] = svd(V, 'econ'); sigma = diag(S); total_energy = sum(sigma.^2); % 计算总能量 % 计算累积能量比 cum_energy_ratio = cumsum(sigma.^2) / total_energy; % 确定主次成分分界点(90%能量处) tau = 0.999; % 90%能量阈值 idx = find(cum_energy_ratio >= tau, 1); if isempty(idx) idx = numel(sigma); end % ============================== % 核心修改:双系数调节方案 % ============================== sigma_enhanced = zeros(size(sigma)); % 主成分增强(前90%能量) main_idx = 1:idx; sigma_enhanced(main_idx) = sigma(main_idx) * beta; % 次成分抑制(后10%能量) secondary_idx = (idx+1):numel(sigma); sigma_enhanced(secondary_idx) = sigma(secondary_idx) * gamma; % 重构亮度通道 S_enhanced = diag(sigma_enhanced); V_enhanced = U * S_enhanced * V_svd'; V_enhanced = min(max(V_enhanced, 0), 1); % 限制在[0,1]范围 % 重组HSV图像 hsv_enhanced = hsv_img; hsv_enhanced(:,:,3) = V_enhanced; % 转回RGB空间 rgb_enhanced = hsv2rgb(hsv_enhanced); % CLAHE增强 (在Lab空间进行) lab_img = rgb2lab(rgb_enhanced); L = lab_img(:,:,1) / 100; % 归一化到[0,1] % 应用CLAHE L_clahe = adapthisteq(L, 'ClipLimit', 0.01, 'NumTiles', [8,8]); % 反归一化并重组Lab图像 lab_img(:,:,1) = L_clahe * 100; enhanced_img = lab2rgb(lab_img, 'OutputType', 'double'); % 转换为uint8 enhanced_img = im2uint8(enhanced_img); end % 其他增强方法 % 直方图均衡化 (HE) function enhanced = he_method(img) enhanced = histeq(img); end % BIMEF方法 function enhanced = bimef(img) % 读取彩色图像 img_double = im2double(img); % 将图像转换为 double 类型 % 将图像转换为灰度图像 gray_img = rgb2gray(img_double); % 将灰度图像转换为对数域 log_img = log(1 + gray_img); % BIMEF 算法参数 filter_size = 5; % 滤波器大小 step = 1; % 步长 % 初始化输出图像 enhanced_img = zeros(size(log_img)); % 应用 BIMEF 算法 for i = step:step:size(log_img, 1)-filter_size+1 for j = step:step:size(log_img, 2)-filter_size+1 % 定义滤波器 h = ones(filter_size, filter_size) / (filter_size^2); % 滤波操作 enhanced_img(i:i+filter_size-1, j:j+filter_size-1) = ... exp(h * log_img(i:i+filter_size-1, j:j+filter_size-1)); end end % 将输出图像转换回线性域并归一化 enhanced_img = max(enhanced_img, 0); % 防止负值出现 enhanced_img = (enhanced_img - min(enhanced_img(:))) / ... (max(enhanced_img(:)) - min(enhanced_img(:))); % 归一化处理 enhanced_img = uint8(255 * enhanced_img); % 转换为 8 位无符号整数 % 将增强后的灰度图像转换回彩色图像 hsv_img = rgb2hsv(img_double); hsv_img(:, :, 3) = mat2gray(enhanced_img); % 替换亮度分量 enhanced = hsv2rgb(hsv_img); % 转换为uint8 enhanced = im2uint8(enhanced); end % LIME方法 (简化实现) function enhanced = lime_method(img) img = im2double(img); % 估计光照图 T = max(img, [], 3); % 优化光照图 (导向滤波) r = 16; eps = 0.01; L = imguidedfilter(T, img, 'NeighborhoodSize', [r r], 'DegreeOfSmoothing', eps); % 调整光照图 L = min(L, 1); % 将大于 1 的数值值设置为 1 L_adjusted = imadjust(L, [min(L(:)) max(L(:))], [0.2 1]); % 增强图像 enhanced = zeros(size(img)); for ch = 1:3 enhanced(:,:,ch) = img(:,:,ch) ./ max(L_adjusted, 0.01); end enhanced = min(max(enhanced, 0), 1); enhanced = im2uint8(enhanced); end % MSRCR方法 function output = msrcr_method(img, scales, beta, C, w) % 1. 多尺度Retinex计算 (保留原有逻辑) R_msr = MultiScaleRetinex(img, scales); % 2. 颜色恢复修正:添加beta项 weighted_input = w(1)*img(:,:,1) + w(2)*img(:,:,2) + w(3)*img(:,:,3); % 加权输入 log_term = log(weighted_input + 1e-6); % 避免log(0) % 3. 应用完整公式 R_msrcr = C .* ( log(R_msr + 1e-6) - beta * log_term ); % beta在此生效 % 4. 归一化输出 output = mat2gray(R_msrcr); end % 图像质量评估指标:PSNR、SSIM、平均梯度、信息熵 function [psnr_val, ssim_val, avg_grad, entropy_val] = evaluate_image(enhanced, reference) % 图像质量评估 % 输入: % enhanced - 增强后的图像 % reference - 参考图像 (正常光照图像) % 输出: % psnr_val - 峰值信噪比 % ssim_val - 结构相似性 % avg_grad - 平均梯度 % entropy_val - 信息熵 % PSNR计算 if exist('reference', 'var') && ~isempty(reference) psnr_val = psnr(enhanced, reference); else psnr_val = NaN; end % SSIM计算 if exist('reference', 'var') && ~isempty(reference) ssim_val = ssim(enhanced, reference); else ssim_val = NaN; end % 平均梯度 (清晰度) [Gx, Gy] = imgradientxy(rgb2gray(enhanced)); G_mag = sqrt(Gx.^2 + Gy.^2); avg_grad = mean(G_mag(:)); % 信息熵 (信息量) gray_img = rgb2gray(enhanced); entropy_val = entropy(gray_img); end

根据下面两段代码优化解决优化后的“TDMFeedbackController”的模块代码“无法识别的字段名称 "priorities"。”的问题,给我优化后完整的代码第一段:classdef TDMApp8888 < matlab.apps.AppBase properties (Access = public) UIFigure matlab.ui.Figure % 左侧控制面板 ControlPanel matlab.ui.container.Panel SignalConfigPanel matlab.ui.container.Panel NumSignalsEditField matlab.ui.control.NumericEditField NumSignalsLabel matlab.ui.control.Label SignalTypeDropDown matlab.ui.control.DropDown SignalTypeLabel matlab.ui.control.Label FrequencyEditField matlab.ui.control.NumericEditField FrequencyLabel matlab.ui.control.Label AddSignalButton matlab.ui.control.Button RemoveSignalButton matlab.ui.control.Button SignalsListBox matlab.ui.control.ListBox SignalsListLabel matlab.ui.control.Label % 新增载波频率控件 CarrierFrequencyLabel matlab.ui.control.Label CarrierFrequencyEditField matlab.ui.control.NumericEditField StrategyPanel matlab.ui.container.Panel FixedRadioButton matlab.ui.control.RadioButton PriorityRadioButton matlab.ui.control.RadioButton StrategyButtonGroup matlab.ui.container.ButtonGroup TotalSlotsEditField matlab.ui.control.NumericEditField TotalSlotsLabel matlab.ui.control.Label % 编码配置控件 EncodingPanel matlab.ui.container.Panel EncodingTypeDropDown matlab.ui.control.DropDown EncodingTypeLabel matlab.ui.control.Label QuantBitsEditField matlab.ui.control.NumericEditField QuantBitsLabel matlab.ui.control.Label StepSizeEditField matlab.ui.control.NumericEditField StepSizeLabel matlab.ui.control.Label % 调制配置控件 ModulationPanel matlab.ui.container.Panel ModulationTypeDropDown matlab.ui.control.DropDown ModulationTypeLabel matlab.ui.control.Label % 帧配置控件 FrameConfigPanel matlab.ui.container.Panel FrameHeaderEditField matlab.ui.control.EditField FrameHeaderLabel matlab.ui.control.Label CRCCheckBox matlab.ui.control.CheckBox % 右侧控制面板 SimulationPanel matlab.ui.container.Panel RunSimulationButton matlab.ui.control.Button RunFeedbackButton matlab.ui.control.Button RunAnalysisButton matlab.ui.control.Button SNREditField matlab.ui.control.NumericEditField SNRLabel matlab.ui.control.Label IterationsEditField matlab.ui.control.NumericEditField IterationsLabel matlab.ui.control.Label DurationEditField matlab.ui.control.NumericEditField DurationLabel matlab.ui.control.Label SamplingRateEditField matlab.ui.control.NumericEditField SamplingRateLabel matlab.ui.control.Label StatusLabel matlab.ui.control.Label ProgressBar matlab.ui.control.Lamp % 结果显示区域 ResultsTabGroup matlab.ui.container.TabGroup SignalsTab matlab.ui.container.Tab OriginalAxes matlab.ui.control.UIAxes TDMAxes matlab.ui.control.UIAxes DemuxAxes matlab.ui.control.UIAxes SyncedAxes matlab.ui.control.UIAxes PerformanceTab matlab.ui.container.Tab BERAxes matlab.ui.control.UIAxes ParametersTab matlab.ui.container.Tab ParametersTextArea matlab.ui.control.TextArea end properties (Access = private) signals % 存储信号配置的cell数组 params % 系统参数结构体 tdmSystem % TDMSystem实例 controller % TDMFeedbackController实例 analyzer % TDMPerformanceAnalyzer实例 end methods (Access = private) function updateParams(app) % 更新系统参数 app.params = struct(); % 确保所有UI组件都存在且有效 try app.params.fs = app.SamplingRateEditField.Value; app.params.duration = app.DurationEditField.Value; app.params.numSignals = numel(app.signals); app.params.snrDb = app.SNREditField.Value; app.params.iterations = app.IterationsEditField.Value; app.params.totalSlots = app.TotalSlotsEditField.Value; % 编码参数 if isvalid(app.EncodingTypeDropDown) app.params.encodingType = app.EncodingTypeDropDown.Value; else app.params.encodingType = 'PCM'; % 默认值 end app.params.quantBits = app.QuantBitsEditField.Value; app.params.stepSize = app.StepSizeEditField.Value; % 调制参数 if isvalid(app.ModulationTypeDropDown) app.params.modulationType = app.ModulationTypeDropDown.Value; else app.params.modulationType = 'BPSK'; % 默认值 end % 帧配置 if isvalid(app.FrameHeaderEditField) app.params.frameHeader = app.FrameHeaderEditField.Value; else app.params.frameHeader = 'A5A5'; % 默认值 end if isvalid(app.CRCCheckBox) app.params.useCRC = app.CRCCheckBox.Value; else app.params.useCRC = true; % 默认值 end % 时隙分配策略 if isvalid(app.FixedRadioButton) && isvalid(app.PriorityRadioButton) if app.FixedRadioButton.Value app.params.strategy = 'fixed'; else app.params.strategy = 'priority'; end else app.params.strategy = 'priority'; % 默认值 end % 设置信号调制方式和时钟漂移 app.params.signalModulations = cell(1, app.params.numSignals); app.params.clockDrift = zeros(1, app.params.numSignals); for i = 1:app.params.numSignals if i <= numel(app.signals) app.params.signalModulations{i} = app.signals{i}.modulation; else app.params.signalModulations{i} = 'BPSK'; % 默认值 end % 设置时钟漂移 (确保长度与信号数量匹配) if i == 1 app.params.clockDrift(i) = 0.001; elseif i == 2 app.params.clockDrift(i) = 0.002; else app.params.clockDrift(i) = -0.001; end end catch ME % 错误处理:记录错误并恢复默认值 disp('更新参数时出错:'); disp(ME.message); app.params = struct('fs', 1000, 'duration', 1, 'numSignals', 0); end end function generateSignals(app) % 生成信号数据 (使用linspace确保精确采样点) if isempty(app.params) || ~isfield(app.params, 'fs') || ~isfield(app.params, 'duration') return; % 参数无效,跳过 end t = linspace(0, app.params.duration, app.params.fs * app.params.duration); app.tdmSystem.originalSignals = zeros(app.params.numSignals, length(t)); app.tdmSystem.signalInfo = cell(app.params.numSignals, 1); for i = 1:app.params.numSignals if i <= numel(app.signals) sigConfig = app.signals{i}; else % 默认值包含载波频率 sigConfig = struct('type', '正弦波', 'frequency', 50, ... 'modulation', 'BPSK', 'carrierFrequency', 1000); end baseSignal = []; % 存储基带信号 switch sigConfig.type case '正弦波' freq = sigConfig.frequency; baseSignal = sin(2*pi*freq*t); baseInfo = sprintf('正弦波 (%dHz)', freq); case '方波' freq = sigConfig.frequency; baseSignal = square(2*pi*freq*t); baseInfo = sprintf('方波 (%dHz)', freq); case '随机噪声' baseSignal = randn(1, length(t)); baseInfo = '随机噪声'; case '锯齿波' freq = sigConfig.frequency; baseSignal = sawtooth(2*pi*freq*t); baseInfo = sprintf('锯齿波 (%dHz)', freq); case '脉冲信号' freq = sigConfig.frequency; duty = 0.3; % 占空比 pulseTrain = pulstran(t, 0:1/freq:app.params.duration, ... 'rectpuls', duty/freq); % 确保长度匹配 if length(pulseTrain) > length(t) baseSignal = pulseTrain(1:length(t)); else baseSignal = zeros(1, length(t)); baseSignal(1:length(pulseTrain)) = pulseTrain; end baseInfo = sprintf('脉冲信号 (%dHz)', freq); end % ========== 应用载波调制 ========== carrierFreq = sigConfig.carrierFrequency; switch sigConfig.modulation case 'AM' % 幅度调制: (1 + m(t)) * cos(2πf_c t) modulatedSignal = (1 + 0.5*baseSignal) .* cos(2*pi*carrierFreq*t); modInfo = sprintf('AM调制 (%dHz载波)', carrierFreq); case 'FM' % 频率调制: cos(2πf_c t + 2πΔf ∫m(t)dt) kf = 0.1; % 调制指数 integral_m = cumsum(baseSignal) / app.params.fs; modulatedSignal = cos(2*pi*carrierFreq*t + 2*pi*kf*integral_m); modInfo = sprintf('FM调制 (%dHz载波)', carrierFreq); case 'PM' % 相位调制: cos(2πf_c t + k_p m(t)) kp = 1; % 相位偏移常数 modulatedSignal = cos(2*pi*carrierFreq*t + kp*baseSignal); modInfo = sprintf('PM调制 (%dHz载波)', carrierFreq); otherwise % 无调制或未知调制类型 modulatedSignal = baseSignal; modInfo = '无调制'; end app.tdmSystem.originalSignals(i, :) = modulatedSignal; app.tdmSystem.signalInfo{i} = [baseInfo ', ' modInfo]; end % 设置编码参数 if isfield(app.params, 'encodingType') && isfield(app.params, 'quantBits') && isfield(app.params, 'stepSize') app.tdmSystem.encodingParams = struct(... 'type', app.params.encodingType, ... 'quantBits', app.params.quantBits, ... 'stepSize', app.params.stepSize); else app.tdmSystem.encodingParams = struct('type', 'PCM', 'quantBits', 8, 'stepSize', 0.05); % 默认值 end % 设置调制参数 if isfield(app.params, 'modulationType') && isfield(app.params, 'signalModulations') app.tdmSystem.modulationParams = struct(... 'type', app.params.modulationType, ... 'signalModulations', {app.params.signalModulations}); else app.tdmSystem.modulationParams = struct('type', 'BPSK', 'signalModulations', {{'BPSK', 'BPSK'}}); % 默认值 end % 设置帧配置 if isfield(app.params, 'frameHeader') && isfield(app.params, 'useCRC') app.tdmSystem.frameConfig = struct(... 'header', app.params.frameHeader, ... 'useCRC', app.params.useCRC); else app.tdmSystem.frameConfig = struct('header', 'A5A5', 'useCRC', true); % 默认值 end end function updateParametersDisplay(app) % 更新参数显示 try paramText = sprintf('系统参数:\n'); if isfield(app.params, 'fs') paramText = [paramText sprintf('采样频率: %d Hz\n', app.params.fs)]; end if isfield(app.params, 'duration') paramText = [paramText sprintf('信号持续时间: %.2f 秒\n', app.params.duration)]; end if isfield(app.params, 'numSignals') paramText = [paramText sprintf('信号源数量: %d\n', app.params.numSignals)]; end if isfield(app.params, 'snrDb') paramText = [paramText sprintf('信噪比: %d dB\n', app.params.snrDb)]; end if isfield(app.params, 'strategy') paramText = [paramText sprintf('时隙分配策略: %s\n', app.params.strategy)]; end if isfield(app.params, 'totalSlots') paramText = [paramText sprintf('总时隙数量: %d\n', app.params.totalSlots)]; end if isfield(app.params, 'iterations') paramText = [paramText sprintf('仿真迭代次数: %d\n', app.params.iterations)]; end % 编码参数 paramText = [paramText sprintf('\n编码配置:\n')]; if isfield(app.params, 'encodingType') paramText = [paramText sprintf(' 编码类型: %s\n', app.params.encodingType)]; end if isfield(app.params, 'quantBits') paramText = [paramText sprintf(' 量化位数: %d bits\n', app.params.quantBits)]; end if isfield(app.params, 'stepSize') paramText = [paramText sprintf(' 步长: %.4f\n', app.params.stepSize)]; end % 调制参数 paramText = [paramText sprintf('\n调制配置:\n')]; if isfield(app.params, 'modulationType') paramText = [paramText sprintf(' 系统调制类型: %s\n', app.params.modulationType)]; end % 帧配置 paramText = [paramText sprintf('\n帧配置:\n')]; if isfield(app.params, 'frameHeader') paramText = [paramText sprintf(' 帧头: %s\n', app.params.frameHeader)]; end if isfield(app.params, 'useCRC') paramText = [paramText sprintf(' CRC校验: %s\n', ifelse(app.params.useCRC, '启用', '禁用'))]; end % 信号信息 - 包含载波频率 paramText = [paramText sprintf('\n信号配置:\n')]; for i = 1:min(app.params.numSignals, numel(app.signals)) sig = app.signals{i}; paramText = [paramText sprintf('信号 %d: %s (基带频率: %d Hz, 调制: %s, 载波频率: %d Hz)\n', ... i, sig.type, sig.frequency, sig.modulation, sig.carrierFrequency)]; end app.ParametersTextArea.Value = paramText; catch ME disp('更新参数显示时出错:'); disp(ME.message); app.ParametersTextArea.Value = '系统参数显示错误'; end end function plotSignals(app) % 绘制原始信号 try t = linspace(0, app.params.duration, app.params.fs * app.params.duration); cla(app.OriginalAxes); hold(app.OriginalAxes, 'on'); colors = lines(app.params.numSignals); for i = 1:min(app.params.numSignals, size(app.tdmSystem.originalSignals, 1)) plot(app.OriginalAxes, t, app.tdmSystem.originalSignals(i, 1:length(t)), ... 'Color', colors(i, :), 'DisplayName', app.tdmSystem.signalInfo{i}); end hold(app.OriginalAxes, 'off'); legend(app.OriginalAxes, 'Location', 'best'); title(app.OriginalAxes, '原始信号'); xlabel(app.OriginalAxes, '时间 (s)'); ylabel(app.OriginalAxes, '幅度'); grid(app.OriginalAxes, 'on'); % 绘制TDM信号(支持复数信号) cla(app.TDMAxes); if ~isempty(app.tdmSystem.tdmSignal) && isfield(app.params, 'duration') t_tdm = linspace(0, app.params.duration, length(app.tdmSystem.tdmSignal)); plot(app.TDMAxes, t_tdm, real(app.tdmSystem.tdmSignal)); hold(app.TDMAxes, 'on'); plot(app.TDMAxes, t_tdm, imag(app.tdmSystem.tdmSignal)); hold(app.TDMAxes, 'off'); legend(app.TDMAxes, {'实部', '虚部'}, 'Location', 'best'); end title(app.TDMAxes, ['TDM复用信号 (' app.params.strategy '策略)']); xlabel(app.TDMAxes, '时间 (s)'); ylabel(app.TDMAxes, '幅度'); grid(app.TDMAxes, 'on'); % 绘制解复用信号 cla(app.DemuxAxes); hold(app.DemuxAxes, 'on'); for i = 1:min(app.params.numSignals, size(app.tdmSystem.demuxSignals, 1)) if size(app.tdmSystem.demuxSignals, 2) >= length(t) plot(app.DemuxAxes, t,app.tdmSystem.demuxSignals(i, 1:length(t)), ... 'Color', colors(i, :), 'DisplayName', ['信号 ' num2str(i)]); end end hold(app.DemuxAxes, 'off'); legend(app.DemuxAxes, 'Location', 'best'); title(app.DemuxAxes, '解复用信号'); xlabel(app.DemuxAxes, '时间 (s)'); ylabel(app.DemuxAxes, '幅度'); grid(app.DemuxAxes, 'on'); % 绘制同步后信号 cla(app.SyncedAxes); hold(app.SyncedAxes, 'on'); for i = 1:min(app.params.numSignals, size(app.tdmSystem.syncedSignals, 1)) if size(app.tdmSystem.syncedSignals, 2) >= length(t) plot(app.SyncedAxes, t, app.tdmSystem.syncedSignals(i, 1:length(t)), ... 'Color', colors(i, :), 'DisplayName', app.tdmSystem.signalInfo{i}); end end hold(app.SyncedAxes, 'off'); legend(app.SyncedAxes, 'Location', 'best'); title(app.SyncedAxes, '同步后信号'); xlabel(app.SyncedAxes, '时间 (s)'); ylabel(app.SyncedAxes, '幅度'); grid(app.SyncedAxes, 'on'); % 绘制误码率和信噪比 cla(app.BERAxes); if ~isempty(app.tdmSystem.performance) && isfield(app.tdmSystem.performance, 'ber') && isfield(app.tdmSystem.performance, 'snr') yyaxis(app.BERAxes, 'left'); bar(app.BERAxes, 1:app.params.numSignals, app.tdmSystem.performance.ber, 0.6, 'FaceColor', [0.2 0.6 0.8]); ylabel(app.BERAxes, '误码率 (BER)'); yyaxis(app.BERAxes, 'right'); plot(app.BERAxes, 1:app.params.numSignals, app.tdmSystem.performance.snr, 'o-', 'LineWidth', 2, 'MarkerSize', 8); ylabel(app.BERAxes, 'SNR (dB)'); title(app.BERAxes, '信号质量分析'); xlabel(app.BERAxes, '信号编号'); grid(app.BERAxes, 'on'); xticks(app.BERAxes, 1:app.params.numSignals); legend(app.BERAxes, {'BER', 'SNR'}, 'Location', 'best'); end catch ME disp('绘图时出错:'); disp(ME.message); end end end % Callbacks that handle component events methods (Access = private) % Code that executes after component creation function startupFcn(app) % 初始化参数 app.signals = {}; app.params = struct(); app.StatusLabel.Text = '准备就绪'; app.ProgressBar.Color = 'green'; % 设置默认参数 app.SamplingRateEditField.Value = 1000; app.DurationEditField.Value = 1; app.SNREditField.Value = 20; app.IterationsEditField.Value = 5; app.TotalSlotsEditField.Value = 50; app.NumSignalsEditField.Value = 0; app.PriorityRadioButton.Value = true; % 编码参数默认值 app.EncodingTypeDropDown.Value = 'PCM'; app.QuantBitsEditField.Value = 8; app.StepSizeEditField.Value = 0.05; % 调制参数默认值 app.ModulationTypeDropDown.Value = 'BPSK'; % 帧配置默认值 app.FrameHeaderEditField.Value = 'A5A5'; app.CRCCheckBox.Value = true; % 载波频率默认值 app.CarrierFrequencyEditField.Value = 1000; % 更新参数显示 updateParams(app); updateParametersDisplay(app); end % Button pushed function: AddSignalButton function AddSignalButtonPushed(app, ~) % 添加新信号(包含载波频率) try signalType = app.SignalTypeDropDown.Value; frequency = app.FrequencyEditField.Value; modulationType = app.ModulationTypeDropDown.Value; % 获取调制类型 carrierFrequency = app.CarrierFrequencyEditField.Value; % 获取载波频率 if frequency <= 0 uialert(app.UIFigure, '基带频率必须大于0', '无效参数'); return; end if carrierFrequency <= 0 uialert(app.UIFigure, '载波频率必须大于0', '无效参数'); return; end newSignal = struct(... 'type', signalType, ... 'frequency', frequency, ... 'modulation', modulationType, ... 'carrierFrequency', carrierFrequency); % 添加载波频率 app.signals{end+1} = newSignal; app.NumSignalsEditField.Value = numel(app.signals); % 更新信号列表(包含载波频率) signalList = cell(1, numel(app.signals)); for i = 1:numel(app.signals) sig = app.signals{i}; signalList{i} = sprintf('信号 %d: %s (%d Hz基带, %s调制, %d Hz载波)', ... i, sig.type, sig.frequency, sig.modulation, sig.carrierFrequency); end app.SignalsListBox.Items = signalList; % 更新参数 updateParams(app); updateParametersDisplay(app); app.StatusLabel.Text = sprintf('已添加信号: %s (%d Hz基带, %s调制, %d Hz载波)', ... signalType, frequency, modulationType, carrierFrequency); catch ME app.StatusLabel.Text = ['添加信号错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Button pushed function: RemoveSignalButton function RemoveSignalButtonPushed(app, ~) % 移除选中的信号(包含载波频率) try selectedIdx = app.SignalsListBox.Value; if isempty(selectedIdx) || selectedIdx > numel(app.signals) uialert(app.UIFigure, '请选择要删除的信号', '无选择'); return; end % 移除信号 removedSig = app.signals{selectedIdx}; app.signals(selectedIdx) = []; % 更新信号列表(包含载波频率) app.NumSignalsEditField.Value = numel(app.signals); signalList = cell(1, numel(app.signals)); for i = 1:numel(app.signals) sig = app.signals{i}; signalList{i} = sprintf('信号 %d: %s (%d Hz基带, %s调制, %d Hz载波)', ... i, sig.type, sig.frequency, sig.modulation, sig.carrierFrequency); end app.SignalsListBox.Items = signalList; % 如果没有信号,清除选择 if isempty(app.signals) app.SignalsListBox.Value = []; else app.SignalsListBox.Value = min(selectedIdx, numel(app.signals)); end % 更新参数 updateParams(app); updateParametersDisplay(app); app.StatusLabel.Text = sprintf('已移除信号: %s (%d Hz基带, %s调制, %d Hz载波)', ... removedSig.type, removedSig.frequency, removedSig.modulation, removedSig.carrierFrequency); catch ME app.StatusLabel.Text = ['移除信号错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: NumSignalsEditField function NumSignalsEditFieldValueChanged(app, ~) % 信号数量变化时更新 try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新信号数量错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: SamplingRateEditField function SamplingRateEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新采样率错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: DurationEditField function DurationEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新持续时间错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: SNREditField function SNREditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新信噪比错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: IterationsEditField function IterationsEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新迭代次数错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Value changed function: TotalSlotsEditField function TotalSlotsEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新总时隙数错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Selection changed function: StrategyButtonGroup function StrategyButtonGroupSelectionChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新策略错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % 编码参数变化回调 function EncodingTypeDropDownValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新编码类型错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function QuantBitsEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新量化位数错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function StepSizeEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新步长错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % 调制参数变化回调 function ModulationTypeDropDownValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新调制方式错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function FrameHeaderEditFieldValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新帧头错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end function CRCCheckBoxValueChanged(app, ~) try updateParams(app); updateParametersDisplay(app); catch ME app.StatusLabel.Text = ['更新CRC设置错误: ' ME.message]; app.ProgressBar.Color = 'red'; end end % Button pushed function: RunSimulationButton function RunSimulationButtonPushed(app, ~) % 运行基础仿真 app.StatusLabel.Text = '运行基础仿真...'; app.ProgressBar.Color = 'yellow'; drawnow; try % 更新参数 updateParams(app); % 检查信号配置 if app.params.numSignals == 0 uialert(app.UIFigure, '请至少添加一个信号', '无信号'); app.ProgressBar.Color = 'red'; return; end % 创建TDM系统 app.tdmSystem = TDMSystem(app.params); % 生成信号 generateSignals(app); % 运行仿真 app.tdmSystem = app.tdmSystem.runSimulation(); % 显示结果 plotSignals(app); updateParametersDisplay(app); app.StatusLabel.Text = '基础仿真完成!'; app.ProgressBar.Color = 'green'; catch ME app.StatusLabel.Text = ['基础仿真错误: ' ME.message]; app.ProgressBar.Color = 'red'; uialert(app.UIFigure, ME.message, '仿真错误'); end end % Button pushed function: RunFeedbackButton function RunFeedbackButtonPushed(app, ~) % 运行反馈控制仿真 app.StatusLabel.Text = '运行反馈控制仿真...'; app.ProgressBar.Color = 'yellow'; drawnow; try % 更新参数 updateParams(app); % 检查信号配置 if app.params.numSignals == 0 uialert(app.UIFigure, '请至少添加一个信号', '无信号'); app.ProgressBar.Color = 'red'; return; end % 创建反馈控制器 app.controller = TDMFeedbackController(app.params); % 生成信号 generateSignals(app); % 将生成的信号复制到控制器 app.controller.originalSignals = app.tdmSystem.originalSignals; app.controller.signalInfo = app.tdmSystem.signalInfo; app.controller.encodingParams = app.tdmSystem.encodingParams; app.controller.modulationParams = app.tdmSystem.modulationParams; app.controller.frameConfig = app.tdmSystem.frameConfig; % 运行反馈仿真 app.controller = app.controller.runSimulation(); % 显示结果 app.tdmSystem = app.controller; % 用于显示基本结果 plotSignals(app); updateParametersDisplay(app); app.StatusLabel.Text = '反馈控制仿真完成!'; app.ProgressBar.Color = 'green'; catch ME app.StatusLabel.Text = ['反馈控制错误: ' ME.message]; app.ProgressBar.Color = 'red'; uialert(app.UIFigure, ME.message, '仿真错误'); end end % Button pushed function: RunAnalysisButton function RunAnalysisButtonPushed(app, ~) % 运行性能分析 app.StatusLabel.Text = '运行性能分析...'; app.ProgressBar.Color = 'yellow'; drawnow; try % 更新参数 updateParams(app); % 检查信号配置 if app.params.numSignals == 0 uialert(app.UIFigure, '请至少添加一个信号', '无信号'); app.ProgressBar.Color = 'red'; return; end % 创建性能分析器 app.analyzer = TDMPerformanceAnalyzer(app.params); % 生成信号 generateSignals(app); % 将生成的信号复制到分析器 app.analyzer.originalSignals = app.tdmSystem.originalSignals; app.analyzer.signalInfo = app.tdmSystem.signalInfo; app.analyzer.encodingParams = app.tdmSystem.encodingParams; app.analyzer.modulationParams = app.tdmSystem.modulationParams; app.analyzer.frameConfig = app.tdmSystem.frameConfig; % 运行性能分析 app.analyzer = app.analyzer.runPerformanceAnalysis(); % 显示结果 app.tdmSystem = app.analyzer; % 用于显示基本结果 plotSignals(app); updateParametersDisplay(app); app.StatusLabel.Text = '性能分析完成!'; app.ProgressBar.Color = 'green'; catch ME app.StatusLabel.Text = ['性能分析错误: ' ME.message]; app.ProgressBar.Color = 'red'; uialert(app.UIFigure, ME.message, '仿真错误'); end end end % App initialization and construction methods (Access = private) % Create UIFigure and components function createComponents(app) % 创建主窗口 app.UIFigure = uifigure; app.UIFigure.Position = [100 100 1400 900]; app.UIFigure.Name = 'TDM通信系统仿真'; app.UIFigure.Scrollable = 'on'; % 创建控制面板容器 app.ControlPanel = uipanel(app.UIFigure); app.ControlPanel.Title = '控制面板'; app.ControlPanel.Position = [20 20 450 850]; % ==== 信号配置面板 ==== app.SignalConfigPanel = uipanel(app.ControlPanel); app.SignalConfigPanel.Title = '信号配置'; app.SignalConfigPanel.Position = [20 585 410 240]; % 增加高度以容纳载波频率控件 % 信号数量控件 app.NumSignalsLabel = uilabel(app.SignalConfigPanel); app.NumSignalsLabel.Position = [20 190 80 22]; app.NumSignalsLabel.Text = '信号数量:'; app.NumSignalsEditField = uieditfield(app.SignalConfigPanel, 'numeric'); app.NumSignalsEditField.Position = [110 190 60 22]; app.NumSignalsEditField.Value = 0; app.NumSignalsEditField.ValueChangedFcn = createCallbackFcn(app, @NumSignalsEditFieldValueChanged, true); % 信号类型控件 app.SignalTypeLabel = uilabel(app.SignalConfigPanel); app.SignalTypeLabel.Position = [20 160 80 22]; app.SignalTypeLabel.Text = '信号类型:'; app.SignalTypeDropDown = uidropdown(app.SignalConfigPanel); app.SignalTypeDropDown.Position = [110 160 80 22]; app.SignalTypeDropDown.Items = {'正弦波', '方波', '随机噪声', '锯齿波', '脉冲信号'}; % 基带频率控件 app.FrequencyLabel = uilabel(app.SignalConfigPanel); app.FrequencyLabel.Position = [20 130 80 22]; app.FrequencyLabel.Text = '基带频率 (Hz):'; app.FrequencyEditField = uieditfield(app.SignalConfigPanel, 'numeric'); app.FrequencyEditField.Position = [110 130 60 22]; app.FrequencyEditField.Value = 50; % 载波频率控件 app.CarrierFrequencyLabel = uilabel(app.SignalConfigPanel); app.CarrierFrequencyLabel.Position = [210 130 100 22]; app.CarrierFrequencyLabel.Text = '载波频率 (Hz):'; app.CarrierFrequencyEditField = uieditfield(app.SignalConfigPanel, 'numeric'); app.CarrierFrequencyEditField.Position = [300 130 60 22]; app.CarrierFrequencyEditField.Value = 1000; % 默认值 % 添加/移除按钮 app.AddSignalButton = uibutton(app.SignalConfigPanel, 'push'); app.AddSignalButton.ButtonPushedFcn = createCallbackFcn(app, @AddSignalButtonPushed, true); app.AddSignalButton.Position = [210 160 80 22]; app.AddSignalButton.Text = '添加信号'; app.RemoveSignalButton = uibutton(app.SignalConfigPanel, 'push'); app.RemoveSignalButton.ButtonPushedFcn = createCallbackFcn(app, @RemoveSignalButtonPushed, true); app.RemoveSignalButton.Position = [300 160 80 22]; app.RemoveSignalButton.Text = '移除信号'; % 信号列表 app.SignalsListLabel = uilabel(app.SignalConfigPanel); app.SignalsListLabel.Position = [20 100 80 22]; app.SignalsListLabel.Text = '信号列表:'; app.SignalsListBox = uilistbox(app.SignalConfigPanel); app.SignalsListBox.Position = [20 5 370 90]; app.SignalsListBox.Items = {}; % ==== 策略配置面板 ==== app.StrategyPanel = uipanel(app.ControlPanel); app.StrategyPanel.Title = '时隙分配策略'; app.StrategyPanel.Position = [20 425 410 150]; % 策略按钮组 app.StrategyButtonGroup = uibuttongroup(app.StrategyPanel); app.StrategyButtonGroup.SelectionChangedFcn = createCallbackFcn(app, @StrategyButtonGroupSelectionChanged, true); app.StrategyButtonGroup.Position = [20 40 200 80]; app.StrategyButtonGroup.Title = '选择策略'; % 单选按钮 app.FixedRadioButton = uiradiobutton(app.StrategyButtonGroup); app.FixedRadioButton.Text = '固定分配'; app.FixedRadioButton.Position = [11 35 75 22]; app.PriorityRadioButton = uiradiobutton(app.StrategyButtonGroup); app.PriorityRadioButton.Text = '优先级分配'; app.PriorityRadioButton.Position = [11 10 100 22]; app.PriorityRadioButton.Value = true; % 总时隙数 app.TotalSlotsLabel = uilabel(app.StrategyPanel); app.TotalSlotsLabel.Position = [240 30 80 22]; app.TotalSlotsLabel.Text = '总时隙数:'; app.TotalSlotsEditField = uieditfield(app.StrategyPanel, 'numeric'); app.TotalSlotsEditField.ValueChangedFcn = createCallbackFcn(app, @TotalSlotsEditFieldValueChanged, true); app.TotalSlotsEditField.Position = [300 30 60 22]; app.TotalSlotsEditField.Value = 50; % ==== 编码配置面板 ==== app.EncodingPanel = uipanel(app.ControlPanel); app.EncodingPanel.Title = '编码配置'; app.EncodingPanel.Position = [20 300 410 120]; app.EncodingTypeLabel = uilabel(app.EncodingPanel); app.EncodingTypeLabel.Position = [20 75 80 22]; app.EncodingTypeLabel.Text = '编码类型:'; app.EncodingTypeDropDown = uidropdown(app.EncodingPanel); app.EncodingTypeDropDown.Position = [110 75 100 22]; app.EncodingTypeDropDown.Items = {'PCM', 'DPCM', 'DM'}; app.EncodingTypeDropDown.Value = 'PCM'; app.EncodingTypeDropDown.ValueChangedFcn = createCallbackFcn(app, @EncodingTypeDropDownValueChanged, true); app.QuantBitsLabel = uilabel(app.EncodingPanel); app.QuantBitsLabel.Position = [20 45 80 22]; app.QuantBitsLabel.Text = '量化位数:'; app.QuantBitsEditField = uieditfield(app.EncodingPanel, 'numeric'); app.QuantBitsEditField.Position = [110 45 60 22]; app.QuantBitsEditField.Value = 8; app.QuantBitsEditField.ValueChangedFcn = createCallbackFcn(app, @QuantBitsEditFieldValueChanged, true); app.StepSizeLabel = uilabel(app.EncodingPanel); app.StepSizeLabel.Position = [20 15 80 22]; app.StepSizeLabel.Text = '步长:'; app.StepSizeEditField = uieditfield(app.EncodingPanel, 'numeric'); app.StepSizeEditField.Position = [110 15 60 22]; app.StepSizeEditField.Value = 0.05; app.StepSizeEditField.ValueChangedFcn = createCallbackFcn(app, @StepSizeEditFieldValueChanged, true); % ==== 调制配置面板 ==== app.ModulationPanel = uipanel(app.ControlPanel); app.ModulationPanel.Title = '调制配置'; app.ModulationPanel.Position = [20 225 410 70]; app.ModulationTypeLabel = uilabel(app.ModulationPanel); app.ModulationTypeLabel.Position = [20 15 80 22]; app.ModulationTypeLabel.Text = '调制方式:'; app.ModulationTypeDropDown = uidropdown(app.ModulationPanel); app.ModulationTypeDropDown.Position = [110 15 100 22]; app.ModulationTypeDropDown.Items = {'None', 'BPSK', 'QPSK', '16QAM'}; app.ModulationTypeDropDown.Value = 'BPSK'; app.ModulationTypeDropDown.ValueChangedFcn = createCallbackFcn(app, @ModulationTypeDropDownValueChanged, true); % ==== 帧配置面板 ==== app.FrameConfigPanel = uipanel(app.ControlPanel); app.FrameConfigPanel.Title = '帧配置'; app.FrameConfigPanel.Position = [20 150 410 70]; app.FrameHeaderLabel = uilabel(app.FrameConfigPanel); app.FrameHeaderLabel.Position = [20 15 80 22]; app.FrameHeaderLabel.Text = '帧头:'; app.FrameHeaderEditField = uieditfield(app.FrameConfigPanel, 'text'); app.FrameHeaderEditField.Position = [110 15 100 22]; app.FrameHeaderEditField.Value = 'A5A5'; app.FrameHeaderEditField.ValueChangedFcn = createCallbackFcn(app, @FrameHeaderEditFieldValueChanged, true); app.CRCCheckBox = uicheckbox(app.FrameConfigPanel); app.CRCCheckBox.Text = '启用CRC校验'; app.CRCCheckBox.Position = [220 15 120 22]; app.CRCCheckBox.Value = true; app.CRCCheckBox.ValueChangedFcn = createCallbackFcn(app, @CRCCheckBoxValueChanged, true); % ==== 仿真控制面板 ==== app.SimulationPanel = uipanel(app.ControlPanel); app.SimulationPanel.Title = '仿真控制'; app.SimulationPanel.Position = [20 5 410 140]; % 参数输入 app.SamplingRateLabel = uilabel(app.SimulationPanel); app.SamplingRateLabel.Position = [20 95 80 22]; app.SamplingRateLabel.Text = '采样率 (Hz):'; app.SamplingRateEditField = uieditfield(app.SimulationPanel, 'numeric'); app.SamplingRateEditField.ValueChangedFcn = createCallbackFcn(app, @SamplingRateEditFieldValueChanged, true); app.SamplingRateEditField.Position = [110 95 60 22]; app.SamplingRateEditField.Value = 1000; app.DurationLabel = uilabel(app.SimulationPanel); app.DurationLabel.Position = [20 65 80 22]; app.DurationLabel.Text = '持续时间 (s):'; app.DurationEditField = uieditfield(app.SimulationPanel, 'numeric'); app.DurationEditField.ValueChangedFcn = createCallbackFcn(app, @DurationEditFieldValueChanged, true); app.DurationEditField.Position = [110 65 60 22]; app.DurationEditField.Value = 1; app.SNRLabel = uilabel(app.SimulationPanel); app.SNRLabel.Position = [20 35 80 22]; app.SNRLabel.Text = '信噪比 (dB):'; app.SNREditField = uieditfield(app.SimulationPanel, 'numeric'); app.SNREditField.ValueChangedFcn = createCallbackFcn(app, @SNREditFieldValueChanged, true); app.SNREditField.Position = [110 35 60 22]; app.SNREditField.Value = 20; app.IterationsLabel = uilabel(app.SimulationPanel); app.IterationsLabel.Position = [200 95 80 22]; app.IterationsLabel.Text = '迭代次数:'; app.IterationsEditField = uieditfield(app.SimulationPanel, 'numeric'); app.IterationsEditField.ValueChangedFcn = createCallbackFcn(app, @IterationsEditFieldValueChanged, true); app.IterationsEditField.Position = [290 95 60 22]; app.IterationsEditField.Value = 5; % 状态显示 app.StatusLabel = uilabel(app.SimulationPanel); app.StatusLabel.HorizontalAlignment = 'center'; app.StatusLabel.Position = [20 5 100 22]; app.StatusLabel.Text = '准备就绪'; app.ProgressBar = uilamp(app.SimulationPanel); app.ProgressBar.Position = [150 5 110 20]; app.ProgressBar.Color = [0.47 0.67 0.19]; % 仿真按钮 app.RunSimulationButton = uibutton(app.SimulationPanel, 'push'); app.RunSimulationButton.ButtonPushedFcn = createCallbackFcn(app, @RunSimulationButtonPushed, true); app.RunSimulationButton.Position = [200 20 80 30]; app.RunSimulationButton.Text = '基础仿真'; app.RunFeedbackButton = uibutton(app.SimulationPanel, 'push'); app.RunFeedbackButton.ButtonPushedFcn = createCallbackFcn(app, @RunFeedbackButtonPushed, true); app.RunFeedbackButton.Position = [290 20 80 30]; app.RunFeedbackButton.Text = '反馈控制'; app.RunAnalysisButton = uibutton(app.SimulationPanel, 'push'); app.RunAnalysisButton.ButtonPushedFcn = createCallbackFcn(app, @RunAnalysisButtonPushed, true); app.RunAnalysisButton.Position = [200 60 170 30]; app.RunAnalysisButton.Text = '性能分析'; % ==== 结果显示区域 ==== app.ResultsTabGroup = uitabgroup(app.UIFigure); app.ResultsTabGroup.Position = [480 20 900 850]; % 信号可视化标签页 app.SignalsTab = uitab(app.ResultsTabGroup); app.SignalsTab.Title = '信号可视化'; % 创建2x2网格布局 grid = uigridlayout(app.SignalsTab); grid.RowHeight = {'1x', '1x'}; grid.ColumnWidth = {'1x', '1x'}; grid.Padding = [10 10 10 10]; grid.RowSpacing = 10; grid.ColumnSpacing = 10; % 原始信号坐标轴 app.OriginalAxes = uiaxes(grid); title(app.OriginalAxes, '原始信号'); xlabel(app.OriginalAxes, '时间 (s)'); ylabel(app.OriginalAxes, '幅度'); app.OriginalAxes.Layout.Row = 1; app.OriginalAxes.Layout.Column = 1; % TDM信号坐标轴 app.TDMAxes = uiaxes(grid); title(app.TDMAxes, 'TDM复用信号'); xlabel(app.TDMAxes, '时间 (s)'); ylabel(app.TDMAxes, '幅度'); app.TDMAxes.Layout.Row = 1; app.TDMAxes.Layout.Column = 2; % 解复用信号坐标轴 app.DemuxAxes = uiaxes(grid); title(app.DemuxAxes, '解复用信号'); xlabel(app.DemuxAxes, '时间 (s)'); ylabel(app.DemuxAxes, '幅度'); app.DemuxAxes.Layout.Row = 2; app.DemuxAxes.Layout.Column = 1; % 同步后信号坐标轴 app.SyncedAxes = uiaxes(grid); title(app.SyncedAxes, '同步后信号'); xlabel(app.SyncedAxes, '时间 (s)'); ylabel(app.SyncedAxes, '幅度'); app.SyncedAxes.Layout.Row = 2; app.SyncedAxes.Layout.Column = 2; % 性能分析标签页 app.PerformanceTab = uitab(app.ResultsTabGroup); app.PerformanceTab.Title = '性能分析'; % BER坐标轴 app.BERAxes = uiaxes(app.PerformanceTab); title(app.BERAxes, '信号质量分析'); xlabel(app.BERAxes, '信号编号'); app.BERAxes.Position = [100 200 700 500]; yyaxis(app.BERAxes, 'left'); ylabel(app.BERAxes, 'BER'); yyaxis(app.BERAxes, 'right'); ylabel(app.BERAxes, 'SNR (dB)'); % 系统参数标签页 app.ParametersTab = uitab(app.ResultsTabGroup); app.ParametersTab.Title = '系统参数'; % 参数文本区域 app.ParametersTextArea = uitextarea(app.ParametersTab); app.ParametersTextArea.Position = [20 20 860 800]; app.ParametersTextArea.Value = {'系统参数将在此显示'}; end end methods (Access = public) % Construct app function app = TDMApp8888 % Create and configure components createComponents(app) % Register the app with App Designer registerApp(app, app.UIFigure) % Execute the startup function runStartupFcn(app, @startupFcn) if nargout == 0 clear app end end % Code that executes before app deletion function delete(app) % Delete UIFigure when app is deleted delete(app.UIFigure) end end end % 辅助函数 function out = ifelse(condition, true_val, false_val) if condition out = true_val; else out = false_val; end end 第二段:classdef TDMSystem properties params % 系统参数 originalSignals % 原始信号 encodedSignals % 编码后信号(二进制位流) modulatedSignals % 调制后信号 demodulatedSignals % 解调后信号 decodedSignals % 解码后信号 tdmSignal % TDM复用信号 receivedSignal % 接收信号 demuxSignals % 解复用信号 syncedSignals % 同步后信号 signalInfo % 信号信息 allocatedSlots % 分配的时隙 slotAssignment % 时隙分配矩阵 performance % 性能指标 encodingParams % 编码参数 modulationParams % 调制参数 frameConfig % 帧配置 quantizationError % 量化误差 frameHeaders % 帧头位置 crcErrors % CRC错误统计 paddingInfo % 填充信息 debugInfo % 调试信息 end methods function obj = TDMSystem(params) % 参数验证和默认值设置 if ~isstruct(params) error('输入参数必须是结构体'); end % 必需参数检查 requiredFields = {'fs', 'duration', 'numSignals', 'snrDb', ... 'totalSlots', 'strategy', 'signalModulations'}; for i = 1:length(requiredFields) if ~isfield(params, requiredFields{i}) error('缺少必需的参数字段: %s', requiredFields{i}); end end % 设置默认值 if ~isfield(params, 'clockDrift') params.clockDrift = zeros(1, params.numSignals); end if ~isfield(params, 'priorities') params.priorities = ones(1, params.numSignals); end if ~isfield(params, 'frameHeader') params.frameHeader = 'A5A5'; end if ~isfield(params, 'useCRC') params.useCRC = true; end if ~isfield(params, 'encodingType') params.encodingType = 'PCM'; end if ~isfield(params, 'quantBits') && strcmp(params.encodingType, 'PCM') params.quantBits = 8; end if ~isfield(params, 'stepSize') && contains(params.encodingType, {'DPCM', 'DM'}) params.stepSize = 0.05; end % 归一化优先级权重 params.priorities = params.priorities / sum(params.priorities); obj.params = params; % 计算关键参数 totalSamples = params.fs * params.duration; obj.params.slotSamples = floor(totalSamples / params.totalSlots); % 初始化性能指标 obj.performance = struct(); obj.quantizationError = zeros(params.numSignals, 1); obj.crcErrors = struct('total', 0, 'perSignal', zeros(1, params.numSignals)); obj.paddingInfo = struct('encoded', zeros(1, params.numSignals)); obj.debugInfo = struct('signalLengths', []); % 初始化编码参数 obj.encodingParams = struct(... 'type', params.encodingType, ... 'quantBits', ifelse(isfield(params, 'quantBits'), params.quantBits, 8), ... 'stepSize', ifelse(isfield(params, 'stepSize'), params.stepSize, 0.05)); % 初始化调制参数 obj.modulationParams = struct(... 'type', ifelse(isfield(params, 'modulationType'), params.modulationType, 'BPSK'), ... 'signalModulations', {params.signalModulations}); % 初始化帧配置 obj.frameConfig = struct(... 'header', params.frameHeader, ... 'useCRC', params.useCRC); end function obj = runSimulation(obj) try % 处理流程 obj = obj.encodeSignals(); % 信号量化与编码 obj = obj.modulateSignals(); % 信号调制 obj = obj.allocateSlots(); % 时隙分配 obj = obj.multiplex(); % TDM复用 obj = obj.transmit(); % 信道传输 obj = obj.frameSynchronization(); % 帧同步 obj = obj.demultiplex(); % 解复用 obj = obj.demodulateSignals(); % 信号解调 obj = obj.decodeSignals(); % 信号解码 obj = obj.synchronize(); % 信号同步 obj = obj.evaluatePerformance(); % 性能评估 catch ME rethrow(ME); end end function obj = encodeSignals(obj) obj.encodedSignals = cell(1, obj.params.numSignals); for i = 1:obj.params.numSignals signal = obj.originalSignals(i, :); % 独立量化与编码处理 switch obj.encodingParams.type case 'PCM' [quantized, quantErr] = obj.pcm_encode(signal, obj.encodingParams.quantBits); [binStream, ~] = obj.int_to_bin(quantized, obj.encodingParams.quantBits); obj.quantizationError(i) = mean(quantErr.^2); case 'DPCM' [quantized, quantErr] = obj.dpcm_encode(signal, obj.encodingParams.quantBits, obj.encodingParams.stepSize); [binStream, ~] = obj.int_to_bin(quantized, obj.encodingParams.quantBits); obj.quantizationError(i) = mean(quantErr.^2); case 'DM' binStream = obj.dm_encode(signal, obj.encodingParams.stepSize); otherwise error('未知编码类型: %s', obj.encodingParams.type); end % 根据调制方式预填充位流 modType = obj.modulationParams.signalModulations{i}; bitsPerSymbol = obj.getBitsPerSymbol(modType); % 计算填充位数 paddingBits = mod(length(binStream), bitsPerSymbol); if paddingBits > 0 padding = bitsPerSymbol - paddingBits; binStream = [binStream, false(1, padding)]; % 填充0 else padding = 0; end obj.paddingInfo.encoded(i) = padding; % 统一转换为逻辑数组 if ~islogical(binStream) binStream = logical(binStream); end obj.encodedSignals{i} = binStream; end end function obj = modulateSignals(obj) obj.modulatedSignals = cell(obj.params.numSignals, 1); for i = 1:obj.params.numSignals binStream = obj.encodedSignals{i}; modulationType = obj.modulationParams.signalModulations{i}; % 独立调制处理 switch modulationType case 'None' obj.modulatedSignals{i} = binStream; case 'BPSK' obj.modulatedSignals{i} = 2*double(binStream) - 1; case 'QPSK' % 确保长度是2的倍数 if mod(length(binStream), 2) ~= 0 binStream = [binStream, false]; % 填充1位 end symbols = reshape(binStream, 2, [])'; I = 2*double(symbols(:,1)) - 1; Q = 2*double(symbols(:,2)) - 1; obj.modulatedSignals{i} = (I + 1i*Q)/sqrt(2); case '16QAM' % 确保长度是4的倍数 if mod(length(binStream), 4) ~= 0 padding = 4 - mod(length(binStream), 4); binStream = [binStream, false(1, padding)]; end symbols = reshape(binStream, 4, [])'; I = 2*double(symbols(:,1)) + double(symbols(:,2)); Q = 2*double(symbols(:,3)) + double(symbols(:,4)); % 映射到星座点 I(I==0) = -3; I(I==1) = -1; I(I==2) = 1; I(I==3) = 3; Q(Q==0) = -3; Q(Q==1) = -1; Q(Q==2) = 1; Q(Q==3) = 3; obj.modulatedSignals{i} = (I + 1i*Q)/sqrt(10); end end end function obj = allocateSlots(obj) if obj.params.totalSlots < obj.params.numSignals error('总时隙数(%d)小于信号数(%d)', ... obj.params.totalSlots, obj.params.numSignals); end obj.allocatedSlots = zeros(1, obj.params.numSignals); obj.slotAssignment = zeros(obj.params.numSignals, obj.params.totalSlots); % 时隙分配策略 switch obj.params.strategy case 'fixed' baseSlots = floor(obj.params.totalSlots / obj.params.numSignals); obj.allocatedSlots = baseSlots * ones(1, obj.params.numSignals); remainder = obj.params.totalSlots - sum(obj.allocatedSlots); [~, sortedIdx] = sort(obj.params.priorities, 'descend'); for i = 1:remainder if i <= obj.params.numSignals obj.allocatedSlots(sortedIdx(i)) = obj.allocatedSlots(sortedIdx(i)) + 1; end end case 'priority' minSlots = ones(1, obj.params.numSignals); availableSlots = obj.params.totalSlots - sum(minSlots); if availableSlots < 0 error('总时隙数(%d)不足以分配', obj.params.totalSlots); end weights = obj.params.priorities / sum(obj.params.priorities); extraSlots = floor(availableSlots * weights); obj.allocatedSlots = minSlots + extraSlots; remainder = availableSlots - sum(extraSlots); [~, idx] = sort(obj.params.priorities, 'descend'); for i = 1:remainder obj.allocatedSlots(idx(i)) = obj.allocatedSlots(idx(i)) + 1; end end % 构建时隙分配矩阵 current_slot = 1; for i = 1:obj.params.numSignals slotsToAssign = obj.allocatedSlots(i); for j = 1:slotsToAssign if current_slot > obj.params.totalSlots break; end obj.slotAssignment(i, current_slot) = 1; current_slot = current_slot + 1; end end end function obj = multiplex(obj) totalSamples = obj.params.fs * obj.params.duration; headerBin = obj.str2bin(obj.frameConfig.header); headerLen = length(headerBin); slotSamples = obj.params.slotSamples; dataSizePerFrame = slotSamples * obj.params.totalSlots; frameSizeTotal = dataSizePerFrame + headerLen; numFrames = ceil(totalSamples / dataSizePerFrame); % 初始化TDM信号 obj.tdmSignal = complex(zeros(1, numFrames * frameSizeTotal)); obj.frameHeaders = zeros(1, numFrames); for frameIdx = 1:numFrames frameStartTotal = (frameIdx-1) * frameSizeTotal + 1; headerEnd = frameStartTotal + headerLen - 1; % 添加帧头 obj.tdmSignal(frameStartTotal:headerEnd) = complex(headerBin, 0); obj.frameHeaders(frameIdx) = frameStartTotal; dataStart = headerEnd + 1; % 时隙分配与信号插入 for slot = 1:obj.params.totalSlots slotStart = dataStart + (slot-1) * slotSamples; slotEnd = slotStart + slotSamples - 1; if slotEnd > length(obj.tdmSignal) break; end % 获取当前时隙对应的信号索引 signalIdx = find(obj.slotAssignment(:, slot) == 1, 1); if ~isempty(signalIdx) % 计算信号位置 signalStart = (frameIdx-1) * dataSizePerFrame + (slot-1) * slotSamples + 1; signalEnd = min(signalStart + slotSamples - 1, length(obj.modulatedSignals{signalIdx})); % 获取信号片段 signalSegment = obj.modulatedSignals{signalIdx}(signalStart:signalEnd); % 长度匹配处理 if length(signalSegment) < slotSamples padding = complex(zeros(1, slotSamples - length(signalSegment))); signalSegment = [signalSegment, padding]; elseif length(signalSegment) > slotSamples signalSegment = signalSegment(1:slotSamples); end % 插入时隙 obj.tdmSignal(slotStart:slotEnd) = signalSegment; else obj.tdmSignal(slotStart:slotEnd) = complex(zeros(1, slotSamples)); end end end end function obj = transmit(obj) signal_power = mean(abs(obj.tdmSignal).^2); if signal_power == 0 signal_power = 1e-10; end linear_snr = 10^(obj.params.snrDb/10); noise_power = signal_power / linear_snr; if ~isreal(obj.tdmSignal) noise = sqrt(noise_power/2) * (randn(size(obj.tdmSignal)) + 1i*randn(size(obj.tdmSignal))); else noise = sqrt(noise_power) * randn(size(obj.tdmSignal)); end obj.receivedSignal = obj.tdmSignal + noise; end function obj = frameSynchronization(obj) headerBin = obj.str2bin(obj.frameConfig.header); headerLen = length(headerBin); slotSamples = obj.params.slotSamples; dataSizePerFrame = slotSamples * obj.params.totalSlots; frameSizeTotal = dataSizePerFrame + headerLen; if isreal(obj.receivedSignal) headerRef = complex(headerBin, 0); else headerRef = complex(headerBin, zeros(size(headerBin))); end correlation = conv(obj.receivedSignal, conj(fliplr(headerRef)), 'same'); correlationMag = abs(correlation); [~, locs] = findpeaks(correlationMag, 'MinPeakHeight', 0.7*max(correlationMag), ... 'MinPeakDistance', round(frameSizeTotal*0.8)); detectedHeaders = []; for i = 1:length(locs) if i == 1 || (locs(i) - locs(i-1)) > 0.8 * frameSizeTotal detectedHeaders = [detectedHeaders, locs(i)]; end end obj.frameHeaders = detectedHeaders; end function obj = demultiplex(obj) totalSamples = obj.params.fs * obj.params.duration; headerBin = obj.str2bin(obj.frameConfig.header); headerLen = length(headerBin); slotSamples = obj.params.slotSamples; dataSizePerFrame = slotSamples * obj.params.totalSlots; obj.demuxSignals = cell(1, obj.params.numSignals); for i = 1:obj.params.numSignals obj.demuxSignals{i} = complex(zeros(1, totalSamples)); end for frameIdx = 1:length(obj.frameHeaders) headerStart = obj.frameHeaders(frameIdx); if headerStart + headerLen + dataSizePerFrame - 1 > length(obj.receivedSignal) continue; end frameData = obj.receivedSignal(headerStart+headerLen:headerStart+headerLen+dataSizePerFrame-1); for slot = 1:obj.params.totalSlots slotStart = (slot-1)*slotSamples + 1; slotEnd = slotStart + slotSamples - 1; if slotEnd > length(frameData) continue; end slotData = frameData(slotStart:slotEnd); signalIdx = find(obj.slotAssignment(:, slot) == 1, 1); if ~isempty(signalIdx) % 计算信号位置 signalStart = (frameIdx-1)*dataSizePerFrame + (slot-1)*slotSamples + 1; signalEnd = signalStart + length(slotData) - 1; % 确保不越界 if signalEnd > totalSamples signalEnd = totalSamples; slotData = slotData(1:(signalEnd - signalStart + 1)); end % 存储解复用数据 obj.demuxSignals{signalIdx}(signalStart:signalEnd) = slotData; end end end end function obj = demodulateSignals(obj) totalSamples = size(obj.demuxSignals{1}, 2); obj.demodulatedSignals = false(obj.params.numSignals, totalSamples); for i = 1:obj.params.numSignals modSignal = obj.demuxSignals{i}; modulationType = obj.modulationParams.signalModulations{i}; switch modulationType case 'None' bits = real(modSignal) > 0.5; case 'BPSK' bits = real(modSignal) > 0; case 'QPSK' I = real(modSignal) > 0; Q = imag(modSignal) > 0; bits = [I, Q]'; bits = bits(:)'; case '16QAM' symbols = modSignal * sqrt(10); I = real(symbols); Q = imag(symbols); bitsI1 = I > 0; bitsI2 = abs(I) > 2; bitsQ1 = Q > 0; bitsQ2 = abs(Q) > 2; bits = [bitsI1, bitsI2, bitsQ1, bitsQ2]'; bits = bits(:)'; end % 移除填充位 padding = obj.paddingInfo.encoded(i); if padding > 0 bits = bits(1:end-padding); end % 确保输出长度匹配 endIdx = min(length(bits), totalSamples); obj.demodulatedSignals(i, 1:endIdx) = bits(1:endIdx); end end function obj = decodeSignals(obj) totalSamples = size(obj.demodulatedSignals, 2); obj.decodedSignals = zeros(obj.params.numSignals, totalSamples); for i = 1:obj.params.numSignals binStream = obj.demodulatedSignals(i, :); switch obj.encodingParams.type case 'PCM' quantized = obj.bin_to_int(binStream, obj.encodingParams.quantBits); decoded = obj.pcm_decode(quantized, obj.encodingParams.quantBits); obj.decodedSignals(i, 1:length(decoded)) = decoded; case 'DPCM' quantized = obj.bin_to_int(binStream, obj.encodingParams.quantBits); decoded = obj.dpcm_decode(quantized, obj.encodingParams.quantBits, obj.encodingParams.stepSize); obj.decodedSignals(i, 1:length(decoded)) = decoded; case 'DM' decoded = obj.dm_decode(binStream, obj.encodingParams.stepSize); obj.decodedSignals(i, 1:length(decoded)) = decoded; end end end function obj = synchronize(obj) totalSamples = obj.params.fs * obj.params.duration; t = linspace(0, obj.params.duration, totalSamples); obj.syncedSignals = zeros(obj.params.numSignals, totalSamples); for i = 1:obj.params.numSignals decodedSignal = obj.decodedSignals(i, :); validIdx = find(~isnan(decodedSignal) & ~isinf(decodedSignal)); if isempty(validIdx) obj.syncedSignals(i, :) = 0; continue; end drift = obj.params.clockDrift(i); shifted_t = t * (1 + drift); % 确保时间向量不超出范围 max_time = max(shifted_t); if max_time > obj.params.duration shifted_t = shifted_t(shifted_t <= obj.params.duration); if numel(shifted_t) < totalSamples shifted_t = [shifted_t, linspace(shifted_t(end), obj.params.duration, ... totalSamples - numel(shifted_t))]; end end obj.syncedSignals(i, :) = interp1(... t(validIdx), decodedSignal(validIdx), shifted_t, 'pchip', 0); end end function obj = evaluatePerformance(obj) obj.performance = struct(... 'snr', zeros(1, obj.params.numSignals), ... 'ber', zeros(1, obj.params.numSignals), ... 'mse', zeros(1, obj.params.numSignals)); for i = 1:obj.params.numSignals orig_signal = obj.originalSignals(i, :); synced_signal = obj.syncedSignals(i, :); minLen = min(length(orig_signal), length(synced_signal)); if minLen == 0 continue; end orig_segment = orig_signal(1:minLen); synced_segment = synced_signal(1:minLen); % 计算MSE mse = mean((orig_segment - synced_segment).^2); obj.performance.mse(i) = mse; % 计算SNR signal_power = mean(orig_segment.^2); if mse > 0 obj.performance.snr(i) = 10 * log10(signal_power / mse); end % 计算BER modType = obj.modulationParams.signalModulations{i}; if any(strcmp(modType, {'BPSK', 'QPSK', '16QAM'})) orig_bits = obj.encodedSignals{i}; demod_bits = obj.demodulatedSignals(i, :); minLenBits = min(length(orig_bits), length(demod_bits)); if minLenBits > 0 orig_seg = orig_bits(1:minLenBits); demod_seg = demod_bits(1:minLenBits); bit_errors = sum(orig_seg ~= demod_seg); obj.performance.ber(i) = bit_errors / minLenBits; end end end end % ====== 辅助方法 ====== function [binStream, padding] = int_to_bin(~, values, numBits) numValues = numel(values); totalBits = numValues * numBits; binStream = false(1, totalBits); for i = 1:numValues val = uint32(values(i)); startIdx = (i-1)*numBits + 1; for bitPos = 1:numBits bit = bitget(val, bitPos, 'uint32'); binStream(startIdx + numBits - bitPos) = (bit == 1); end end padding = 0; end function values = bin_to_int(~, binStream, numBits) numValues = floor(length(binStream) / numBits); padding = length(binStream) - numValues * numBits; if padding > 0 binStream = binStream(1:end-padding); end values = zeros(1, numValues); for i = 1:numValues startIdx = (i-1)*numBits + 1; endIdx = startIdx + numBits - 1; segment = binStream(startIdx:endIdx); val = 0; for j = 1:numBits val = val * 2 + segment(j); end values(i) = val; end end function bin = str2bin(~, str) dec = uint8(str); binStr = dec2bin(dec, 8)'; bin = double(binStr(:)') - 48; end function bits = getBitsPerSymbol(~, modType) switch modType case {'BPSK', 'None'} bits = 1; case 'QPSK' bits = 2; case '16QAM' bits = 4; otherwise bits = 1; end end % ====== 编码核心方法 ====== function [quantized, quantErr] = pcm_encode(~, signal, quantBits) maxVal = max(abs(signal)); quantLevels = 2^quantBits; quantStep = 2*maxVal/(quantLevels-1); minVal = -maxVal; quantized = round((signal - minVal)/quantStep); quantized = max(0, min(quantized, quantLevels-1)); quantErr = signal - (quantized*quantStep + minVal); end function decoded = pcm_decode(~, quantized, quantBits) maxVal = max(quantized) * (2^quantBits-1)/2^quantBits; minVal = -maxVal; quantStep = 2*maxVal/(2^quantBits-1); decoded = quantized*quantStep + minVal; end function [encoded, quantErr] = dpcm_encode(obj, signal, quantBits, stepSize) n = length(signal); encoded = zeros(1, n); quantErr = zeros(1, n); predictor = 0; for i = 1:n error = signal(i) - predictor; quantizedError = obj.quantize(error, quantBits, stepSize); encoded(i) = quantizedError; predictor = predictor + quantizedError; quantErr(i) = error - quantizedError; end end function decoded = dpcm_decode(~, encoded, ~, ~) n = length(encoded); decoded = zeros(1, n); predictor = 0; for i = 1:n decoded(i) = predictor + encoded(i); predictor = decoded(i); end end function encoded = dm_encode(~, signal, stepSize) n = length(signal); encoded = false(1, n); integrator = 0; for i = 1:n if signal(i) > integrator encoded(i) = true; integrator = integrator + stepSize; else encoded(i) = false; integrator = integrator - stepSize; end end end function decoded = dm_decode(~, encoded, stepSize) n = length(encoded); decoded = zeros(1, n); integrator = 0; for i = 1:n if encoded(i) integrator = integrator + stepSize; else integrator = integrator - stepSize; end decoded(i) = integrator; end end function quantized = quantize(~, value, quantBits, stepSize) levels = 2^quantBits; maxVal = (levels-1) * stepSize / 2; clipped = max(min(value, maxVal), -maxVal); quantized = round(clipped/stepSize) * stepSize; end end end % 辅助函数 function out = ifelse(condition, true_val, false_val) if condition out = true_val; else out = false_val; end end

function [uq, ud_comp] = SpeedCurrent_MPC_Simulink(omega, iq, omega_ref) % 带速度和电流约束的非级联MPC(PMSM专用),兼容Simulink代码生成 % 输入: omega(当前速度, rad/s), iq(当前q轴电流, A), omega_ref(速度参考, rad/s) % 输出: uq(q轴电压指令, V), ud_comp(d轴电压补偿, V,此处设为0,可扩展) %% 1. 关键参数定义(预定义所有变量,避免未定义错误) % 采样与硬件参数 Tms = 0.001; % 采样时间 (s) u_max = 310; % 最大相电压(默认380V电网下的直流母线电压√2*220≈310V) id = 0; % d轴电流指令(弱磁前设为0) % 电机参数(根据实际电机调整) J = 0.020; % 转动惯量 (kg·m²) B = 0.008; % 粘性阻尼系数 (N·m/(rad/s)) P = 4; % 极对数 Kt = 1; % 转矩系数 (N·m/A) R = 0.4; % 定子电阻 (Ω) Lq = 6e-3; % q轴电感 (H) Ld = 6e-3; % d轴电感 (H)(表贴式电机Ld=Lq) Psi_f = 0.186; % 永磁磁链 (Wb) % MPC核心参数 Np = 20; % 预测时域(步数) Nc = 12; % 控制时域(步数) % 权重矩阵(根据调试调整,速度权重>电流权重) Q_omega = 0.1; % 速度误差权重 Q_iq = 10; % q轴电流误差权重 R_uq = 0.1; % q轴电压增量权重 % 物理约束(避免超调或硬件损坏) omega_max = 3000; % 最大速度 (rad/s) iq_max = 40; % 最大q轴电流 (A) delta_uq_max = 50; % 电压增量约束(避免电压跳变,V) %% 2. 状态空间模型(PMSM dq轴数学模型,3阶状态:id, iq, omega) % 状态矩阵 Am (3×3):[id_dot; iq_dot; omega_dot] = Am*[id; iq; omega] + Bm*[ud; uq] Am = [ -R/Ld, omega*(Lq/Ld), -Psi_f/(Ld); -omega*(Ld/Lq), -R/Lq, 0; 0, (3*P*Kt)/(2*J), -B/J ]; % 输入矩阵 Bm (3×2):ud控制id,uq控制iq和omega Bm = [1/Ld, 0; 0, 1/Lq; 0, 0 ]; % 输出矩阵 Cm (2×3):关注iq和omega(非级联控制目标) Cm = [0, 1, 0; % 输出1:iq 0, 0, 1]; % 输出2:omega %% 3. 模型离散化(零阶保持ZOH,适配数字控制) % 构造增广矩阵用于离散化:[Am Bm; 0 0] (5×5) aug_mat = [Am, Bm; zeros(2, 3), zeros(2, 2)]; % 离散化矩阵(expm实现ZOH离散化,预定义尺寸避免Simulink推断错误) M = expm(aug_mat * Tms); Ad = M(1:3, 1:3); % 离散状态矩阵 (3×3) Bd = M(1:3, 4:5); % 离散输入矩阵 (3×2) %% 4. MPC增广模型(状态+前一时刻输入,解决增量控制) % 增广状态:[id; iq; omega; uq_prev] (4×1),仅控制uq(ud=0) nx_aug = 4; % 增广状态维度 nu_aug = 1; % 控制输入维度(仅uq) ny_aug = 2; % 输出维度(iq, omega) % 增广状态矩阵 A_aug (4×4) A_aug = [Ad, Bd(:, 2); % Bd(:,2)是uq对原状态的影响 zeros(1, 3), 1];% 前一时刻uq的传递(u_prev(k+1)=u(k)) % 增广输入矩阵 B_aug (4×1) B_aug = [Bd(:, 2); 1]; % 输入是uq增量Δuq,u(k)=u(k-1)+Δuq % 增广输出矩阵 C_aug (2×4):输出iq和omega C_aug = [0, 1, 0, 0; % 输出iq(与增广状态第2维对应) 0, 0, 1, 0]; % 输出omega(与增广状态第3维对应) %% 5. 预测矩阵构建(预定义尺寸,适配Simulink代码生成) % phi: 状态预测矩阵 (Np*ny_aug × nx_aug) = [C_aug*A_aug^1; C_aug*A_aug^2; ...; C_aug*A_aug^Np] phi = zeros(Np*ny_aug, nx_aug); % F: 控制预测矩阵 (Np*ny_aug × Nc*nu_aug) = [C_aug*B_aug, 0,...0; C_aug*A_aug*B_aug, C_aug*B_aug,...0; ...] F = zeros(Np*ny_aug, Nc*nu_aug); for i = 1:Np % 填充phi:第i步状态预测 phi((i-1)*ny_aug+1:i*ny_aug, :) = C_aug * (A_aug^i); % 填充F:第i步控制影响(仅控制时域内的输入) for j = 1:min(i, Nc) col_idx = (j-1)*nu_aug + 1; F((i-1)*ny_aug+1:i*ny_aug, col_idx) = C_aug * (A_aug^(i-j)) * B_aug; end end %% 6. 权重矩阵与参考轨迹(预定义尺寸,避免动态维度) % 输出权重矩阵 Q_bar (Np*ny_aug × Np*ny_aug):对角矩阵,按输出维度分配权重 Q_bar = zeros(Np*ny_aug, Np*ny_aug); for i = 1:Np % 第i步的iq权重(Q_iq)和omega权重(Q_omega) Q_bar((i-1)*ny_aug+1, (i-1)*ny_aug+1) = Q_iq; % iq权重 Q_bar((i-1)*ny_aug+2, (i-1)*ny_aug+2) = Q_omega; % omega权重 end % 控制权重矩阵 R_bar (Nc*nu_aug × Nc*nu_aug):电压增量权重 R_bar = kron(eye(Nc), R_uq); % 参考轨迹 r_seq (Np*ny_aug × 1):未来Np步跟踪iq_ref和omega_ref(iq_ref由速度计算) % 简化:iq_ref = (J*(omega_ref - omega) + B*omega)/(3*P*Kt/2)(基于转矩平衡) iq_ref = min( (J*(omega_ref - omega) + B*omega) / (3*P*Kt/2), iq_max ); r_seq = repmat([iq_ref; omega_ref], Np, 1); % 每步参考都是[iq_ref; omega_ref] %% 7. 增广状态向量(当前状态+前一时刻输入,预定义尺寸) % 初始化前一时刻uq(persistent变量,首次运行设为0,适配Simulink) persistent uq_prev; if isempty(uq_prev) uq_prev = 0; % 初始电压为0,避免首次运行错误 end % 当前增广状态:[id; iq; omega; uq_prev] (4×1) x_aug_current = [id; iq; omega; uq_prev]; %% 8. 二次规划问题构建(带约束,适配quadprog) % 目标函数:min_ΔU (0.5*ΔU'*H*ΔU + ΔU'*E) H = F' * Q_bar * F + R_bar; % 二次项矩阵 (Nc×Nc) E = F' * Q_bar * (phi * x_aug_current - r_seq); % 线性项向量 (Nc×1) % 约束条件:ΔU ∈ [lb, ub](电压增量约束) lb = -delta_uq_max * ones(Nc, 1); % 最小增量 ub = delta_uq_max * ones(Nc, 1); % 最大增量 % 使用quadprog求解优化问题(支持代码生成) % 注意:Simulink代码生成要求指定优化选项,且算法必须支持代码生成(如'interior-point-convex') % 初始化Delta_U Delta_U = zeros(Nc,1); % 尝试使用内点法 options = optimoptions('quadprog','Algorithm','active-set'); % 提供初始点 x0 = zeros(Nc, 1); Delta_U = quadprog(H, E, [], [], [], [], lb, ub, x0, options); % 提取第一个控制增量 Delta_uq = Delta_U(1); % 第一个控制增量 uq_current = uq_prev + Delta_uq; % 电压限幅(确保在[-u_max, u_max]范围内) uq_current = max(min(uq_current, u_max), -u_max); % 更新前一时刻控制量(用于下一次) uq_prev = uq_current; % 输出当前控制量(q轴电压) uq = uq_current; % d轴补偿设为0 ud_comp = 0; end电流调节次数太慢了

我运行刚才发给你的那段代码时候加载视频那没问题,处理视频报错,内容是:classdef CarMotionDetectorApp < matlab.apps.AppBase % 主应用程序类 - 基于光流场的汽车运动检测系统 properties (Access = public) % UI组件 UIFigure matlab.ui.Figure UIAxes matlab.ui.control.UIAxes LoadVideoButton matlab.ui.control.Button ProcessButton matlab.ui.control.Button ThresholdSlider matlab.ui.control.Slider ThresholdLabel matlab.ui.control.Label StatusLabel matlab.ui.control.Label FrameRateEdit matlab.ui.control.NumericEditField FrameRateLabel matlab.ui.control.Label SaveResultsButton matlab.ui.control.Button % 数据处理相关 VideoReader % 视频读取对象 VideoPath char = '' % 视频路径 PrevGray uint8 % 前一帧灰度图像 FlowThreshold double = 0.2 % 光流幅值阈值 IsProcessing logical = false % 处理状态标志 OutputVideoWriter % 输出视频写入对象 end methods (Access = private) % 加载视频按钮回调 function onLoadVideoButtonPushed(app, ~) [file, path] = uigetfile({'*.mp4;*.avi;*.mov','视频文件 (*.mp4, *.avi, *.mov)'}, '选择视频文件'); if isequal(file,0) return; % 用户取消选择 end app.VideoPath = fullfile(path, file); try app.VideoReader = VideoReader(app.VideoPath); app.PrevGray = []; % 重置前一帧 % 显示第一帧 if hasFrame(app.VideoReader) frame = readFrame(app.VideoReader); imshow(frame, 'Parent', app.UIAxes); title(app.UIAxes, '视频第一帧'); app.StatusLabel.Text = '视频加载完成,点击"开始处理"'; % 重置视频读取器 app.VideoReader = VideoReader(app.VideoPath); end catch ME uialert(app.UIFigure, sprintf('视频加载失败: %s', ME.message), '错误'); end end % 处理按钮回调 function onProcessButtonPushed(app, ~) if isempty(app.VideoReader) || isempty(app.VideoPath) uialert(app.UIFigure, '请先加载视频文件', '未选择视频'); return; end % 切换处理状态 if ~app.IsProcessing app.IsProcessing = true; app.ProcessButton.Text = '停止处理'; app.LoadVideoButton.Enable = 'off'; app.SaveResultsButton.Enable = 'off'; processVideo(app); else app.IsProcessing = false; app.ProcessButton.Text = '开始处理'; app.LoadVideoButton.Enable = 'on'; app.SaveResultsButton.Enable = 'on'; app.StatusLabel.Text = '处理已停止'; end end % 保存结果按钮回调 function onSaveResultsButtonPushed(app, ~) if isempty(app.VideoReader) || isempty(app.VideoPath) uialert(app.UIFigure, '请先加载并处理视频', '无处理结果'); return; end [file, path] = uiputfile({'*.avi','AVI 视频文件 (*.avi)'}, '保存结果视频'); if isequal(file,0) return; % 用户取消保存 end outputPath = fullfile(path, file); try % 创建输出视频写入器 app.OutputVideoWriter = VideoWriter(outputPath, 'Motion JPEG AVI'); app.OutputVideoWriter.FrameRate = app.VideoReader.FrameRate; open(app.OutputVideoWriter); % 重置视频读取器 app.VideoReader = VideoReader(app.VideoPath); app.PrevGray = []; app.IsProcessing = true; app.ProcessButton.Enable = 'off'; app.LoadVideoButton.Enable = 'off'; app.SaveResultsButton.Enable = 'off'; app.StatusLabel.Text = '正在保存结果...'; % 处理并保存每一帧 while hasFrame(app.VideoReader) && app.IsProcessing frame = readFrame(app.VideoReader); currentGray = im2gray(frame); if isempty(app.PrevGray) app.PrevGray = currentGray; continue; end % 创建光流对象并计算光流 flow = opticalFlowFarneback('PyramidScale', 0.5, ... 'NumLevels', 3, ... 'WindowSize', 15, ... 'NumIterations', 3, ... 'PolyN', 5, ... 'PolySigma', 1.2); flowVectors = estimateFlow(flow, app.PrevGray, currentGray); Vx = flowVectors.Vx; Vy = flowVectors.Vy; magnitude = sqrt(Vx.^2 + Vy.^2); motionMask = magnitude > app.FlowThreshold; % 可视化 outputFrame = frame; redMask = cat(3, ones(size(motionMask)), zeros(size(motionMask)), zeros(size(motionMask))); h = imshow(redMask, 'Parent', app.UIAxes); set(h, 'AlphaData', 0.3 * motionMask); % 绘制光流向量 [h, w] = size(magnitude); [X, Y] = meshgrid(1:10:w, 1:10:h); U = Vx(1:10:h, 1:10:w); V = Vy(1:10:h, 1:10:w); hold(app.UIAxes, 'on'); quiver(app.UIAxes, X(:), Y(:), U(:), V(:), 2, 'Color', 'g', 'LineWidth', 1); hold(app.UIAxes, 'off'); title(app.UIAxes, '汽车运动检测(红色区域为运动区域)'); % 获取当前帧图像并写入视频 frameWithOverlay = getframe(app.UIAxes); writeVideo(app.OutputVideoWriter, frameWithOverlay.cdata); app.PrevGray = currentGray; app.StatusLabel.Text = sprintf('保存中... 帧: %d', app.VideoReader.CurrentTime * app.VideoReader.FrameRate); drawnow; end close(app.OutputVideoWriter); app.IsProcessing = false; app.ProcessButton.Enable = 'on'; app.LoadVideoButton.Enable = 'on'; app.SaveResultsButton.Enable = 'on'; app.StatusLabel.Text = sprintf('结果已保存至: %s', outputPath); catch ME uialert(app.UIFigure, sprintf('保存失败: %s', ME.message), '错误'); app.IsProcessing = false; app.ProcessButton.Enable = 'on'; app.LoadVideoButton.Enable = 'on'; app.SaveResultsButton.Enable = 'on'; end end % 视频处理主函数 function processVideo(app) % 重置视频读取器 app.VideoReader = VideoReader(app.VideoPath); app.PrevGray = []; % 获取帧率控制值 frameRate = app.FrameRateEdit.Value; if frameRate <= 0 frameRate = app.VideoReader.FrameRate; end pauseTime = 1/frameRate; % 循环处理每一帧 while hasFrame(app.VideoReader) && app.IsProcessing % 读取当前帧 frame = readFrame(app.VideoReader); % 转换为灰度图像 currentGray = im2gray(frame); % 如果是第一帧,则存储并跳过 if isempty(app.PrevGray) app.PrevGray = currentGray; continue; end % 创建光流对象并计算光流(使用R2023a兼容的Name=Value语法) flow = opticalFlowFarneback('PyramidScale', 0.5, ... 'NumLevels', 3, ... 'WindowSize', 15, ... 'NumIterations', 3, ... 'PolyN', 5, ... 'PolySigma', 1.2); % 计算光流场(使用两帧图像) flowVectors = estimateFlow(flow, app.PrevGray, currentGray); % 获取光流向量 Vx = flowVectors.Vx; Vy = flowVectors.Vy; magnitude = sqrt(Vx.^2 + Vy.^2); % 光流幅值 % 更新前一帧 app.PrevGray = currentGray; % 检测运动区域(超过阈值的区域) motionMask = magnitude > app.FlowThreshold; % 可视化:在原始帧上绘制光流向量和运动区域 imshow(frame, 'Parent', app.UIAxes); hold(app.UIAxes, 'on'); % 绘制运动区域(用红色半透明区域表示) redMask = cat(3, ones(size(motionMask)), zeros(size(motionMask)), zeros(size(motionMask))); h = imshow(redMask, 'Parent', app.UIAxes); set(h, 'AlphaData', 0.3 * motionMask); % 只显示运动区域 % 绘制光流向量(采样绘制,避免过于密集) [h, w] = size(magnitude); [X, Y] = meshgrid(1:10:w, 1:10:h); U = Vx(1:10:h, 1:10:w); V = Vy(1:10:h, 1:10:w); quiver(app.UIAxes, X(:), Y(:), U(:), V(:), 2, 'Color', 'g', 'LineWidth', 1); hold(app.UIAxes, 'off'); title(app.UIAxes, '汽车运动检测(红色区域为运动区域)'); % 更新状态 app.StatusLabel.Text = sprintf('处理中... 当前帧: %d', app.VideoReader.CurrentTime * app.VideoReader.FrameRate); % 刷新界面 drawnow; % 控制处理速度 pause(pauseTime); end % 处理完成或停止 if app.IsProcessing app.IsProcessing = false; app.ProcessButton.Text = '开始处理'; app.LoadVideoButton.Enable = 'on'; app.SaveResultsButton.Enable = 'on'; app.StatusLabel.Text = '处理完成!'; end end % 阈值滑动条回调 function onThresholdSliderValueChanged(app, ~) app.FlowThreshold = app.ThresholdSlider.Value; app.ThresholdLabel.Text = sprintf('运动阈值: %.2f', app.FlowThreshold); end % 帧率编辑框回调 function onFrameRateEditValueChanged(app, ~) frameRate = app.FrameRateEdit.Value; if frameRate <= 0 app.FrameRateEdit.Value = app.VideoReader.FrameRate; end end end methods (Access = private) % 创建UI组件 function createComponents(app) % 创建主窗口 app.UIFigure = uifigure('Name', '基于光流场的汽车运动检测系统', ... 'Position', [100 100 900 650]); % 创建坐标轴 app.UIAxes = uiaxes(app.UIFigure); app.UIAxes.Position = [50, 180, 800, 450]; app.UIAxes.XTick = []; app.UIAxes.YTick = []; title(app.UIAxes, '视频显示'); % 创建加载视频按钮 app.LoadVideoButton = uibutton(app.UIFigure, 'push', ... 'Position', [50, 130, 100, 30], ... 'Text', '加载视频', ... 'ButtonPushedFcn', @(src, event) onLoadVideoButtonPushed(app, event)); % 创建处理按钮 app.ProcessButton = uibutton(app.UIFigure, 'push', ... 'Position', [170, 130, 100, 30], ... 'Text', '开始处理', ... 'ButtonPushedFcn', @(src, event) onProcessButtonPushed(app, event)); % 创建保存结果按钮 app.SaveResultsButton = uibutton(app.UIFigure, 'push', ... 'Position', [290, 130, 100, 30], ... 'Text', '保存结果', ... 'Enable', 'off', ... 'ButtonPushedFcn', @(src, event) onSaveResultsButtonPushed(app, event)); % 创建阈值滑动条 app.ThresholdSlider = uislider(app.UIFigure, ... 'Position', [420, 150, 200, 3], ... 'Limits', [0.05, 1], ... 'Value', app.FlowThreshold, ... 'ValueChangedFcn', @(src, event) onThresholdSliderValueChanged(app, event)); % 创建阈值标签 app.ThresholdLabel = uilabel(app.UIFigure, ... 'Position', [420, 120, 200, 22], ... 'Text', sprintf('运动阈值: %.2f', app.FlowThreshold)); % 创建帧率标签 app.FrameRateLabel = uilabel(app.UIFigure, ... 'Position', [650, 120, 80, 22], ... 'Text', '处理帧率:'); % 创建帧率编辑框 app.FrameRateEdit = uieditfield(app.UIFigure, 'numeric', ... 'Position', [730, 120, 60, 22], ... 'Value', 10, ... 'Limits', [1, 60], ... 'ValueChangedFcn', @(src, event) onFrameRateEditValueChanged(app, event)); % 创建状态标签 app.StatusLabel = uilabel(app.UIFigure, ... 'Position', [50, 80, 800, 22], ... 'Text', '请加载视频文件'); end end methods (Access = public) % 构造函数 function app = CarMotionDetectorApp % 创建UI组件 createComponents(app); end end end

%% 文本到QPSK调制转换 clear all; close all; clc; fprintf('======= 文本到QPSK调制转换 =======\n'); % ===== 1. 读取文本文件 ===== filename = 'input_text.txt'; fid = fopen(filename, 'r', 'n', 'UTF-8'); if fid == -1 error('无法打开文件: %s', filename); end rawData = fread(fid, '*uint8')'; % 读取UTF-8编码字节 fclose(fid); dataLength = length(rawData); fprintf('[1] 文本文件读取成功\n'); fprintf(' ├─文件名: %s\n', filename); fprintf(' ├─文件大小: %d 字节\n', dataLength); fprintf(' └─起始内容: "%s..."\n', native2unicode(rawData(1:min(10,end)))); % ===== 1.1 保存UTF8原始数据 ===== rawOutputFile = 'raw_utf8_data.bin'; fid_raw = fopen(rawOutputFile, 'wb'); if fid_raw == -1 error('无法创建文件: %s', rawOutputFile); end fwrite(fid_raw, rawData, 'uint8'); fclose(fid_raw); fprintf('[1.1] UTF-8原始数据已保存: %s\n', rawOutputFile); % ===== 2. 计算CRC16校验码 ===== function crc = calculateCRC16(data) crc = uint16(65535); % 初始值0xFFFF poly = uint16(40961); % 多项式0xA001 for i = 1:length(data) crc = bitxor(crc, uint16(data(i))); for j = 1:8 if bitand(crc, 1) crc = bitxor(bitshift(crc, -1), poly); else crc = bitshift(crc, -1); end end end end crcValue = calculateCRC16(rawData); crcBytes = [bitand(bitshift(crcValue, -8), 255), bitand(crcValue, 255)]; fprintf('[2] CRC16校验计算完成\n'); fprintf(' ├─校验值: 0x%04X\n', crcValue); fprintf(' └─校验字节: [0x%02X, 0x%02X]\n', crcBytes(1), crcBytes(2)); % ===== 3. FEC卷积编码 (添加6比特尾零) ===== trellis = poly2trellis(7, [133 171]); % 约束长度7 inputBits = de2bi(rawData, 8, 'left-msb')'; inputBits = inputBits(:)'; % 展平为行向量 originalBits = length(inputBits); % === 关键修改:添加6比特尾零 === inputBitsWithTail = [inputBits, zeros(1, 6)]; % 添加6比特尾零 tailBits = 6; % 记录尾比特数 % 卷积编码(原始数据+尾零) encodedData = convenc(inputBitsWithTail, trellis); encodedBits = length(encodedData); fprintf('[3] FEC卷积编码完成(添加尾比特)\n'); fprintf(' ├─原始比特数: %d bits\n', originalBits); fprintf(' ├─尾比特数: %d bits\n', tailBits); fprintf(' ├─编码输入比特数: %d bits\n', length(inputBitsWithTail)); fprintf(' ├─编码输出比特数: %d bits (码率1/2)\n', encodedBits); fprintf(' └─编码增益: %.1f%%\n', (encodedBits - originalBits)/originalBits*100); % ===== 4. 构建帧头 ===== syncWord = [hex2dec('55'), hex2dec('AA')]; % 同步字段0x55AA magicHeader = [hex2dec('AB'), hex2dec('CD'), hex2dec('EF'), hex2dec('FE')]; highByte = floor(dataLength / 256); lowByte = mod(dataLength, 256); lengthBytes = [highByte, lowByte]; headerBytes = [syncWord, magicHeader, lengthBytes]; % 共8字节 headerBits = de2bi(headerBytes, 8, 'left-msb')'; headerBits = headerBits(:)'; % 展平为行向量 fprintf('[4] 帧头构建完成\n'); fprintf(' ├─同步字: 0x%02X%02X\n', syncWord(1), syncWord(2)); fprintf(' ├─魔术头: 0x%02X%02X%02X%02X\n', ... magicHeader(1), magicHeader(2), magicHeader(3), magicHeader(4)); fprintf(' └─长度字段: %d bytes [0x%02X 0x%02X]\n', ... dataLength, lengthBytes(1), lengthBytes(2)); % ===== 5. 组装完整帧 ===== crcBits = de2bi(crcBytes, 8, 'left-msb')'; crcBits = crcBits(:)'; fullFrameBits = [headerBits, encodedData, crcBits]; totalBits = length(fullFrameBits); % fprintf('[5] 完整帧组装完成\n'); % fprintf(' ├─帧头比特数: %d bits\n', length(headerBits)); % fprintf(' ├─编码数据比特数: %d bits\n', length(encodedData)); % fprintf(' ├─CRC比特数: %d bits\n', length(crcBits)); % fprintf(' ├─总比特数: %d bits\n', totalBits); % fprintf(' └─数据占比: %.1f%%\n', length(encodedData)/totalBits*100); % === 按字节补齐 === paddingBits = mod(8 - mod(totalBits, 8), 8); % 计算需补齐的比特数 if paddingBits > 0 fullFrameBits = [fullFrameBits, zeros(1, paddingBits)]; % 末尾补零 totalBits = totalBits + paddingBits; fprintf('[5] 完整帧组装完成\n'); fprintf(' ├─帧头比特数: %d bits\n', length(headerBits)); fprintf(' ├─编码数据比特数: %d bits\n', length(encodedData)); fprintf(' ├─CRC比特数: %d bits\n', length(crcBits)); fprintf(' ├─填充比特数: %d bits\n', paddingBits); fprintf(' ├─总比特数: %d bits (%d bytes)\n', totalBits, totalBits/8); fprintf(' └─数据占比: %.1f%%\n', length(encodedData)/totalBits*100); else fprintf('[5] 完整帧组装完成(无需补齐)\n'); fprintf(' ├─帧头比特数: %d bits\n', length(headerBits)); fprintf(' ├─编码数据比特数: %d bits\n', length(encodedData)); fprintf(' ├─CRC比特数: %d bits\n', length(crcBits)); fprintf(' ├─总比特数: %d bits\n', totalBits); fprintf(' └─数据占比: %.1f%%\n', length(encodedData)/totalBits*100); end % ===== 6. QPSK调制 ===== if mod(totalBits, 2) ~= 0 error('逻辑错误:总比特数应为偶数'); end symbols = reshape(fullFrameBits, 2, [])'; symbolCount = size(symbols, 1); fprintf('[6] QPSK调制准备\n'); fprintf(' ├─最终比特数: %d bits\n', totalBits); fprintf(' ├─符号总数: %d symbols\n', symbolCount); scale = 1/sqrt(2); % 归一化因子 I_bits = symbols(:, 1); Q_bits = symbols(:, 2); I = zeros(symbolCount, 1); Q = zeros(symbolCount, 1); for i = 1:symbolCount if I_bits(i) == 0 && Q_bits(i) == 0 I(i) = +1 * scale; Q(i) = +1 * scale; elseif I_bits(i) == 0 && Q_bits(i) == 1 I(i) = -1 * scale; Q(i) = +1 * scale; elseif I_bits(i) == 1 && Q_bits(i) == 1 I(i) = -1 * scale; Q(i) = -1 * scale; else I(i) = +1 * scale; Q(i) = -1 * scale; end end modulatedSignal = complex(I, Q); % ===== 7. 保存IQ数据 ===== outputFile = 'QPSK_newframe.dat'; fid = fopen(outputFile, 'wb'); if fid == -1 error('无法创建文件: %s', outputFile); end fwrite(fid, [real(modulatedSignal), imag(modulatedSignal)]', 'float32'); fclose(fid); numSamples = length(modulatedSignal); fileSizeBytes = numSamples * 8; % 8字节/复数(2×float32) fprintf('\n[7] 处理完成!\n'); fprintf('=======================================\n'); fprintf('输出文件: %s\n', outputFile); fprintf('采样点数: %d\n', numSamples); fprintf('文件大小: %.2f KB\n', fileSizeBytes / 1024); disp('=============='); CRC修改为CRC-16/KERMIT的方式实现

大家在看

recommend-type

信贷管理系统需求规格说明书

目录 第1章 1.1 背景概括 …………………………………………………… 5 1.2 可行性分析……………………………………………………… 7 (1) 经济可行性………………………………………………… 7 (2)操作可行性………………………………………………… 8 (3)技术可行性………………………………………………… (4)系统特点……………………………………………………… 8 第2章 需求分析………………………………………………………… 9 4.1 功能……………………………………………… 11 4.2 目标 4.3 业务流程设计……………………………………………… 11 (1) 存款管理……………………………………………………… 9 (2) 贷款管理…………………………………………………… 10 4.4 业务流程重组 4.5 数据流程图………………………………………………… 13 第3章 总体设计………………………………………………………… 11 第6章 详细设计………………………………………………………… 16 6.1 模块设计 ……………………………………………………… 16 6.2 代码设计……………………………………………………… 20 6.3 输入输出设计 ……………………………………………… 20 结束语 ……………………………………………………………………… 21 致谢 …………………………………………………………………………… 22 参考文献……………………………………………………………………… 23
recommend-type

genetic-algorithms:(python)01背包问题和平衡分配问题的遗传算法

这是遗传算法的python实现,用于对0/1背包问题进行组合优化,并将其与本地搜索(爬坡)进行混合,以解决平衡分配问题。
recommend-type

基于赛灵思的FPGA 支持 10-100Gbit/s 的 TCP/IP、RoCEv2、UDP/IP 的可扩展网络堆栈

赛灵思 Vivado 2019.1 cmake 3.0 或更高版本 支持的板 赛灵思VC709 赛灵思VCU118 阿尔法数据ADM-PCIE-7V3 文件内有详细说明
recommend-type

keras-gp:硬+高斯过程

Keras的高斯过程 KGP通过高斯过程(GP)层扩展了 。 它允许人们使用由Keras构建的网络构造的内核构建灵活的GP模型。 模型的结构化部分(神经网络)在或上运行。 GP层使用基于库的自定义后端,并基于和构建。 可以使用批量或半随机优化方法分阶段或联合训练模型(请参见)。 有关深度内核学习和KISS-GP的其他资源和教程,请参阅 KGP兼容:Python 2.7-3.5 。 特别是,此程序包实现了本文中描述的方法: 学习具有递归结构的可扩展深核Maruan Al-Shedivat,Andrew Gordon Wilson,Yunus Saatchi,Huzhiting Hu,Eric P.Xing ,2017。 入门 KGP允许使用功能性API以与Keras相同的方式构建模型。 例如,只需几行代码即可构建和编译一个简单的GP-RNN模型: from keras . layer
recommend-type

易语言CPU优化

易语言CPU优化,改下进程名字即可。。一起学习,一起进步。

最新推荐

recommend-type

Node.js构建的运动咖啡馆RESTful API介绍

标题《sportscafeold:体育咖啡馆》指出了项目名称为“体育咖啡馆”,这个名字暗示了该项目可能是一个结合了运动和休闲主题的咖啡馆相关的网络服务平台。该项目运用了多种技术栈,核心的开发语言为JavaScript,这从标签中可以得到明确的信息。 从描述中可以提取以下知识点: 1. **Node.js**:体育咖啡馆项目使用了Node.js作为服务器端运行环境。Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它能够使得JavaScript应用于服务器端开发。Node.js的事件驱动、非阻塞I/O模型使其适合处理大量并发连接,这对于RESTFUL API的构建尤为重要。 2. **Express Framework**:项目中使用了Express框架来创建RESTFUL API。Express是基于Node.js平台,快速、灵活且极简的Web应用开发框架。它提供了构建Web和移动应用的强大功能,是目前最流行的Node.js Web应用框架之一。RESTFUL API是一组遵循REST原则的应用架构,其设计宗旨是让Web服务通过HTTP协议进行通信,并且可以使用各种语言和技术实现。 3. **Mongoose ORM**:这个项目利用了Mongoose作为操作MongoDB数据库的接口。Mongoose是一个对象文档映射器(ODM),它为Node.js提供了MongoDB数据库的驱动。通过Mongoose可以定义数据模型,进行数据库操作和查询,从而简化了对MongoDB数据库的操作。 4. **Passport.js**:项目中采用了Passport.js库来实现身份验证系统。Passport是一个灵活的Node.js身份验证中间件,它支持多种验证策略,例如用户名和密码、OAuth等。它提供了标准化的方法来为用户登录提供认证,是用户认证功能的常用解决方案。 5. **版权信息**:项目的版权声明表明了Sportscafe 2015是版权所有者,这表明项目或其相关内容最早发布于2015年或之前。这可能表明该API背后有商业实体的支持或授权使用。 从【压缩包子文件的文件名称列表】中我们可以了解到,该文件的版本控制仓库使用的是“master”分支。在Git版本控制系统中,“master”分支通常用于存放当前可部署的稳定版本代码。在“master”分支上进行的更改通常都是经过测试且准备发布到生产环境的。 综上所述,我们可以知道体育咖啡馆项目是一个利用现代JavaScript技术栈搭建的后端服务。它包含了处理HTTP请求的Express框架、连接MongoDB数据库的Mongoose库和实现用户身份验证的Passport.js中间件。该项目可用于构建提供体育信息、咖啡馆菜单信息、预约服务等的Web应用或API服务,这为体育咖啡馆的营销、用户体验和数据管理提供了可能。 考虑到文档资料的提及,该项目的安装和API文档应该包含在项目资料中,可能在项目的README文件或其他说明文档中。对于项目的使用者或者开发者而言,这部分文档非常重要,因为它们可以提供详细的信息和指导,帮助用户快速部署和使用该API。 总结来说,这是一套针对体育咖啡馆相关业务的后端解决方案,它使用了流行的开源技术栈,可以灵活地应用于体育咖啡馆的网络服务中,如信息发布、在线预约、会员管理等。
recommend-type

【LNR优化与用户体验】:一文看透互操作优化如何提升用户感知

# 摘要 LNR(邻区关系优化)是提升移动通信网络性能与用户体验的关键技术。本文系统阐述了LNR优化的基本概念、理论基础与技术实现路径,构建了包括信道质量评估、干扰建模及关键性能指标分析在内的数学模型,并探讨了参数配置、邻区管理及AI与大数据在LNR优化中的应用。通过量化用户感知指标,分析了LNR优化对视频流畅度、页面加载速度及切换性能的实际改善效果,并结合典型场景验证了其优化成效。本文进一步展望了LNR技术在5G及未来网络中的发展趋势与技术挑战。
recommend-type

Java1.8 的编程语言、使用场景、版本号、厂商、是否开源、发行日期、终止日期、可替代产品、推荐产品是什么

以下是关于 **Java 1.8** 的全面信息汇总,涵盖其编程语言特性、使用场景、版本号、厂商、是否开源、发行日期、终止支持日期、可替代产品和推荐产品。 --- ## ✅ Java 1.8 综合信息表 | 项目 | 内容 | |------|------| | **编程语言** | Java | | **版本号** | Java 1.8(也称为 Java 8) | | **厂商** | Oracle、Adoptium、Amazon(Corretto)、Azul(Zulu)、Red Hat、IBM 等 | | **是否开源** | ✅ 是(OpenJDK 1.8 是开源的,Oracle
recommend-type

Java开发的教区牧民支持系统介绍

根据给定文件信息,下面将详细阐述相关知识点: ### 标题知识点 #### catecumenus-java: 教区牧民支持系统 - **Java技术栈应用**:标题提到的“catecumenus-java”表明这是一个使用Java语言开发的系统。Java是目前最流行的编程语言之一,广泛应用于企业级应用、Web开发、移动应用等,尤其是在需要跨平台运行的应用中。Java被设计为具有尽可能少的实现依赖,所以它可以在多种处理器上运行。 - **教区牧民支持系统**:从标题来看,这个系统可能面向的是教会管理或教区管理,用来支持牧民(教会领导者或牧师)的日常管理工作。具体功能可能包括教友信息管理、教区活动安排、宗教教育资料库、财务管理、教堂资源调配等。 ### 描述知识点 #### 儿茶类 - **儿茶素(Catechin)**:描述中提到的“儿茶类”可能与“catecumenus”(新信徒、教徒)有关联,暗示这个系统可能与教会或宗教教育相关。儿茶素是一类天然的多酚类化合物,常见于茶、巧克力等植物中,具有抗氧化、抗炎等多种生物活性,但在系统标题中可能并无直接关联。 - **系统版本号**:“0.0.1”表示这是一个非常初期的版本,意味着该系统可能刚刚开始开发,功能尚不完善。 ### 标签知识点 #### Java - **Java语言特点**:标签中明确提到了“Java”,这暗示了整个系统都是用Java编程语言开发的。Java的特点包括面向对象、跨平台(即一次编写,到处运行)、安全性、多线程处理能力等。系统使用Java进行开发,可能看重了这些特点,尤其是在构建可扩展、稳定的后台服务。 - **Java应用领域**:Java广泛应用于企业级应用开发中,包括Web应用程序、大型系统后台、桌面应用以及移动应用(Android)。所以,此系统可能也会涉及这些技术层面。 ### 压缩包子文件的文件名称列表知识点 #### catecumenus-java-master - **Git项目结构**:文件名称中的“master”表明了这是Git版本控制系统中的一个主分支。在Git中,“master”分支通常被用作项目的主干,是默认的开发分支,所有开发工作都是基于此分支进行的。 - **项目目录结构**:在Git项目中,“catecumenus-java”文件夹应该包含了系统的源代码、资源文件、构建脚本、文档等。文件夹可能包含各种子文件夹和文件,比如src目录存放Java源代码,lib目录存放相关依赖库,以及可能的build.xml文件用于构建过程(如Ant或Maven构建脚本)。 ### 结合以上信息的知识点整合 综合以上信息,我们可以推断“catecumenus-java: 教区牧民支持系统”是一个使用Java语言开发的系统,可能正处于初级开发阶段。这个系统可能是为了支持教会内部管理,提供信息管理、资源调度等功能。其使用Java语言的目的可能是希望利用Java的多线程处理能力、跨平台特性和强大的企业级应用支持能力,以实现一个稳定和可扩展的系统。项目结构遵循了Git版本控制的规范,并且可能采用了模块化的开发方式,各个功能模块的代码和资源文件都有序地组织在不同的子文件夹内。 该系统可能采取敏捷开发模式,随着版本号的增加,系统功能将逐步完善和丰富。由于是面向教会的内部支持系统,对系统的用户界面友好性、安全性和数据保护可能会有较高的要求。此外,考虑到宗教性质的敏感性,系统的开发和使用可能还需要遵守特定的隐私和法律法规。
recommend-type

LNR切换成功率提升秘籍:参数配置到网络策略的全面指南

# 摘要 LNR(LTE to NR)切换技术是5G网络部署中的关键环节,直接影
recommend-type

How to install watt toolkit in linux ?

安装 Watt Toolkit(原名 Steam++)在 Linux 系统上通常可以通过编译源码或者使用预编译的二进制文件来完成。Watt Toolkit 是一个开源工具,主要用于加速 Steam 平台的下载速度,支持跨平台运行,因此在 Linux 上也能够很好地工作。 ### 安装步骤 #### 方法一:使用预编译的二进制文件 1. 访问 [Watt Toolkit 的 GitHub 仓库](https://github.com/BeyondDimension/SteamTools) 并下载适用于 Linux 的最新版本。 2. 解压下载的压缩包。 3. 给予可执行权限: ```
recommend-type

PHP实现用户墙上帖子与评论的分享功能

根据给定文件信息,我们可以推导出与“userwallposts”相关的知识点。这里涉及的关键概念包括用户墙面墙(User Wall)、帖子(Posts)和评论(Comments),以及它们在编程语言PHP中的实现方式。用户墙是一种允许用户发布信息,并让他们的朋友或跟随者查看并参与讨论的功能,常见于社交网站。 ### 用户墙概念 用户墙类似于现实生活中的一面墙,用户可以在上面贴上“帖子”来分享自己的想法、照片、视频等信息。其他用户可以在这些帖子下面进行“评论”,类似于在墙上留言。这种互动方式构建了一个社区式的交流环境,增加了用户之间的互动性和参与感。 ### 用户墙的实现 在PHP中实现用户墙功能需要处理前端用户界面和后端服务器逻辑。前端负责展示用户墙、帖子和评论的界面,而后端则负责存储、检索和管理这些数据。 1. **前端实现**:前端可以使用HTML、CSS和JavaScript来构建用户墙的界面。使用AJAX技术可以让用户无需刷新页面即可提交和获取新的帖子和评论。此外,可能还会用到模板引擎(如Twig或Smarty)来动态生成页面内容。 2. **后端实现**:后端PHP代码将负责处理前端发送的请求,如帖子和评论的添加、删除和检索。数据库(如MySQL)将用于存储用户信息、帖子内容、评论以及它们之间的关联关系。 3. **数据库设计**: - 用户表(users):存储用户信息,例如用户名、密码(加密存储)、用户状态等。 - 帖子表(posts):存储帖子信息,例如帖子ID、帖子内容、发帖时间、所属用户ID等。 - 评论表(comments):存储评论信息,包括评论ID、评论内容、评论时间、所属帖子ID和用户ID等。 4. **PHP与数据库交互**:使用PDO(PHP Data Objects)或mysqli扩展来执行SQL语句与数据库进行交互。PDO提供了数据库访问的抽象层,可以连接多种数据库系统,而mysqli则针对MySQL进行了优化。 5. **安全性**: - 输入验证:为了防止SQL注入等安全问题,需要对用户输入进行验证和清理。 - 输出编码:在将数据输出到浏览器之前,应将特殊字符转换为HTML实体。 - 用户认证:用户登录系统时,应采取安全措施如使用会话管理(session management)和防止跨站请求伪造(CSRF)。 6. **功能实现细节**: - 发布帖子:用户输入帖子内容并提交,后端接收并存储到帖子表中。 - 显示帖子:从帖子表中检索所有帖子并展示在用户墙上,包括帖子标题、内容、发布时间和发帖人等信息。 - 发布评论:用户对特定帖子发表评论,后端接收评论信息并将其存储到评论表中。 - 显示评论:为每个帖子显示其下的所有评论,包括评论内容、时间、评论者等。 ### 开源项目实践 “userwallposts-master”暗示了可能存在一个与用户墙帖子和评论相关的开源项目或代码库。这个项目可能包含预设的代码和文件结构,允许开发者下载、安装和配置来创建他们自己的用户墙功能。开发人员可以使用这个项目作为起点,根据自己的需求进一步定制和扩展功能。 在实际开发过程中,还需要考虑系统的可扩展性和维护性。例如,可以设计RESTful API让前端和后端分离,或者使用现代的PHP框架(如Laravel、Symfony等)来简化开发流程和提高代码的组织性。 在总结上述内容后,我们可以了解到用户墙是社交平台中常见的一种功能,其核心功能包括发布帖子和评论。在PHP环境下实现这样的功能需要对前端界面和后端逻辑有深入的理解,以及对数据库设计和交互的安全性有一定的认识。开源项目如“userwallposts-master”可能提供了一个基础框架,帮助开发者快速构建和部署一个用户墙系统。
recommend-type

【LNR信令深度解析】:MR-DC双连接建立全过程技术揭秘

# 摘要 本文系统探讨了LNR信令与MR-DC双连接技术的基本原理、架构组成及其关键信令流程。深入分析了MR-DC的网络架构分类、核心网元功能、无线承载管理机制以及双连接建立过程中的关键信令交互路径。同时,文章解析了LNR信令消息的结构特征与关键字段,探讨了MR-DC场景下的性能评估指标与优化策略,包括信令压缩、负载均衡及节能调度机制。最后,文章展望了MR-DC技术在5G
recommend-type

计算机类:得全方位考,不能局限软考这句话的含义

计算机类考试的全面性要求考生不仅要掌握理论知识,还要具备实践能力、分析能力和对行业发展趋势的理解。考试内容通常涵盖计算机基础、核心技术和应用、前沿技术以及行业标准和规范。考生需要全方位掌握知识体系,不能仅限于软考(软件水平考试)的内容,还需结合实际应用场景和新兴技术的发展。 在计算机类考试中,基础知识的掌握是关键。例如IP地址的分类(如引用[1]中提到的A、B、C、D和E类地址),需要理解其划分规则、网络ID和主机ID的表示方式以及如何根据需求选择合适的IP地址类别。这类知识是网络设计和管理的基础,考试中可能会涉及实际案例分析,要求考生能够灵活运用这些知识解决具体问题。 此外,随着信息技术
recommend-type

Shoemaker: 利用React数据绑定优雅创建Web组件

在Web开发领域,Web组件是一种封装可重用的HTML、CSS和JavaScript功能的方法,以便在网页或Web应用程序中使用。Shoemaker是一个使用TypeScript编写的库,它提供了一个优雅的API,允许开发者创建自定义的Web组件。尽管该项目已不再开发或维护,但它代表了Web组件创建领域的一种实验性方法,我们可以从中学习到如何利用面向对象编程思想来构建组件。 标题中提到的“创建Web组件的一种优雅方法”,指的是Shoemaker通过提供的抽象类和一些API来简化Web组件的创建过程。它允许开发者在接近浏览器底层(即“更接近金属”)的同时,仍能享受到声明性模板和React式数据绑定带来的便利。这种方式能够提高开发效率,同时保持代码的清晰和维护性。 描述中详细解释了Shoemaker的核心特性,包括: 1. 声明性模板:这是指使用一种类似于HTML的声明方式来定义组件的结构,开发者只需要关注如何表达内容,而无需深入繁琐的DOM操作。这种方式通常与数据绑定结合,使得数据变化能够自动反映到UI上。 2. 通过道具进行React式数据绑定:Shoemaker采用了类似于React的props概念来实现数据绑定,允许开发者通过属性将数据传递给组件,并在组件内部实现响应式更新。 3. 快速,高效的渲染:这一点强调了Shoemaker在处理组件渲染时的性能,意味着使用Shoemaker创建的组件在每次数据更新时都能迅速重新渲染,并且资源消耗较低。 4. 生命周期挂钩:Web组件同样拥有生命周期,Shoemaker提供了生命周期钩子函数,允许开发者在组件的不同阶段执行特定的逻辑,例如在组件创建时初始化数据,或者在组件销毁之前清理资源。 5. 观察者模式:Shoemaker可能还支持某种形式的观察者模式,它允许组件观察数据源的变化并在变化发生时得到通知,进一步增强了组件的动态性和响应性。 Shoemaker使用TypeScript来编写,这为开发者提供了一种类型安全的编程环境。尽管推荐使用TypeScript,以便获得最佳的开发体验,但这并不是必需的,说明Shoemaker也兼容JavaScript。 在安装Shoemaker的过程中,推荐使用npm(Node.js包管理器)来安装。npm install @shoelace-style/shoemaker命令会将Shoemaker添加到项目依赖中,使其可以被其他脚本文件引用。 最后,描述中还提供了一个创建基础计数器组件的实例,用TypeScript和Shoemaker提供的html标签函数来实现。这个例子演示了如何使用Shoemaker来创建一个功能性的Web组件,这进一步说明了Shoemaker库的实用性和易用性。 总结来说,尽管Shoemaker项目已经不再活跃,但它在Web组件创建领域展示了一种有趣和创新的方法,通过抽象和封装,提供了一种既有深度又富有表现力的方式来创建可重用的Web组件。Shoemaker利用了TypeScript的类型安全和React的数据绑定思想,让Web组件开发更加直观和高效。通过学习Shoemaker的原理和实践,开发者可以加深对Web组件和现代前端开发的理解。