1. 扫频法不是“扫个频就完事”它本质是系统辨识的稳态激励策略在MATLAB里敲bode(sys)看曲线和用扫频法从实测数据里反推sys完全是两回事。前者是已知模型画图后者是在不知道系统内部结构的前提下靠外部输入信号“问”出系统反应再把答案翻译成传递函数——这叫系统辨识System Identification而扫频法Sweep Frequency Method是其中最经典、最物理直观的实验激励方式之一。我带过三届控制工程实训90%的学生第一次做扫频实验时都以为只要把正弦波频率从低到高拉一遍MATLAB自动就能拟合出传递函数。结果跑出来阶跃响应严重超调仿真和实物对不上。问题不在代码而在对扫频法底层逻辑的误读它不是万能钥匙而是有明确适用边界、严格实施条件、且必须配合特定数据处理流程的一整套闭环方法。扫频法的核心思想是利用线性时不变LTI系统的频率响应唯一性定理一个LTI系统对正弦输入的稳态输出必然是同频率的正弦波其幅值衰减和相位偏移完全由系统本身的传递函数决定。也就是说如果你给系统输入一个频率为ω的正弦信号u(t)A·sin(ωt)在足够长时间后等掉暂态响应测得输出y(t)B·sin(ωtφ)那么该频率点的频率响应G(jω)就等于B/A·e^(jφ)。扫频就是系统性地遍历一系列频率ω₁, ω₂, ..., ωₙ逐点测量对应的幅值比|G(jω)|和相位角∠G(jω)最终拼出一条完整的Bode图。这条Bode图就是传递函数在复平面上的“指纹”。但这里立刻出现第一个关键陷阱扫频不是匀速滑动频率而是分段驻留式激励。很多初学者直接用chirp函数生成一个连续扫频信号如0.1Hz到100Hz线性扫频然后喂给被控对象。实测中你会发现低频段输出还没进入稳态频率已经跳到高频了高频段又因系统惯性大响应跟不上测出来的幅值和相位全是“假”的。正确做法是在每个目标频率ωᵢ上施加足够长的纯正弦信号通常持续5~10个周期等输出波形完全稳定用示波器看波形包络不再漂移再截取中间一段稳态数据计算幅值和相位。MATLAB里没有现成的“一键扫频采集”函数你得自己写循环for i 1:length(freq_vec); u A*sin(2*pi*freq_vec(i)*t); % 施加信号; wait_for_steady_state(); % 等待稳态; y_steady acquire_data(); % 采集稳态段; [mag, phase] compute_mag_phase(y_steady, u); % 计算该点响应; end。这个等待稳态的过程才是扫频法精度的命门。第二个常被忽略的要点是激励信号的信噪比SNR控制。扫频法本质是微弱信号测量尤其在系统增益很低或噪声很大的频段比如机械臂关节在谐振频率附近的微小振动如果输入幅值A太小输出y会被噪声淹没A太大又可能使执行器饱和或系统进入非线性区。我的经验是先做一次粗略扫频用较小A观察各频段输出幅值范围然后对低增益频段输出小提高A对高增益频段输出大降低A实现全频段输出幅值基本一致比如都控制在ADC量程的30%~70%。这叫“自适应幅值扫频”能显著提升信噪比。Simulink里可以用Signal Generator模块配合Switch模块动态切换不同幅值的正弦源比硬编码更灵活。第三个深层逻辑是扫频得到的是离散频率点上的G(jω)而传递函数模型是连续的s域有理分式。这意味着后续必须用模型结构如二阶、三阶、带零点的传递函数去拟合这些离散点。拟合不是简单插值而是参数优化问题。MATLAB的tfest或ssest函数背后是在最小化拟合误差通常是加权的幅值/相位误差同时约束模型阶数和稳定性。如果直接用polyfit对log10(ω)和20*log10(|G|)做多项式拟合得到的“传递函数”在s域根本不可实现极点不在左半平面仿真必然发散。所以扫频法的终点从来不是一张Bode图而是经过严格模型结构选择、参数估计、验证的传递函数对象sys tf(num, den)。提示扫频法只适用于LTI系统。若被测对象存在明显非线性如摩擦死区、磁饱和、时变特性如电机绕组温升导致电阻变化或强外部干扰扫频结果会严重失真。此时应改用伪随机二进制序列PRBS或M序列等宽带激励信号它们能一次性激发全频段响应更适合非线性系统辨识。2. MATLAB实战四步法从原始数据到可仿真的传递函数模型扫频法的MATLAB实现绝不是调用一个函数就结束。它是一条清晰的流水线信号生成→数据采集→频响计算→模型拟合。每一步都有易错点和优化空间。下面以一个典型机电系统直流电机带负载为例完整走一遍可复现的流程。所有代码均基于MATLAB R2022b及Control System Toolbox不依赖任何第三方工具箱。2.1 第一步设计扫频信号与采集方案扫频信号的设计核心是平衡频率分辨率、扫频速度、稳态等待时间三者矛盾。假设目标频段为0.1Hz~50Hz我们采用对数扫频logarithmic sweep因为人眼和控制系统对低频变化更敏感对数间隔能保证低频点更密集。频率点向量freq_vec不能简单用linspace而要用logspace% 定义扫频参数 f_min 0.1; % Hz f_max 50; % Hz n_points 64; % 总点数建议32~128太少拟合不准太多耗时 freq_vec logspace(log10(f_min), log10(f_max), n_points); % 每个频率点的驻留时间至少5个周期且不低于0.5秒保证ADC采样稳定 T_settle max(5./freq_vec, 0.5); % 单位秒 % 实际采集时间再加0.5秒用于滤除启动瞬态 T_acquire T_settle 0.5; % 采样率选择根据奈奎斯特准则最高频率50Hz采样率至少100Hz但为准确计算相位建议≥500Hz fs 1000; % Hz关键细节在于如何确保每个频率点都真正进入稳态。不能靠固定延时pause(T_settle)因为不同系统响应时间差异巨大。更可靠的方法是实时监测输出信号的包络稳定性。MATLAB中可用envelope函数提取包络当包络标准差小于阈值时判定稳态% 伪代码稳态判定循环 for i 1:length(freq_vec) f freq_vec(i); T_wait T_settle(i); % 生成该频率正弦信号 t_gen 0:1/fs:T_wait0.5; % 生成时间向量 u A_vec(i) * sin(2*pi*f*t_gen); % A_vec是自适应幅值向量 % 发送信号到硬件如DAQ设备或Simulink模型 % ... (硬件接口代码省略) % 实时监测输出y计算包络标准差 y_buffer []; % 初始化缓冲区 while true y_new acquire_one_sample(); % 从DAQ读取一个样本 y_buffer [y_buffer, y_new]; if length(y_buffer) fs*0.2 % 缓冲200ms数据 [~, ~, env] envelope(y_buffer, peak); % 计算峰值包络 if std(env(end-100:end)) 0.01*max(abs(y_buffer)) % 包络波动1% break; % 稳态达成 end end end % 稳态后再采集T_acquire秒数据用于计算 y_steady acquire_data(fs*T_acquire); % ... 后续计算 end注意envelope函数计算开销较大实际部署时可用更轻量的滑动窗标准差movstd替代。另外A_vec的自适应策略先用固定小幅值如0.1V跑一轮粗扫记录各频点输出幅值y_amp(i)然后设A_vec(i) A_ref / max(y_amp(i), eps)使目标输出幅值恒定。2.2 第二步从时域数据精准提取幅值与相位拿到u和y_steady两个时序数组后不能直接用FFT求频谱——FFT给出的是整个时间段的平均频谱而我们需要的是单频点的精确幅值和相位。最佳方法是同步解调Synchronous Demodulation即用与输入同频的正余弦信号分别与输出相乘再低通滤波取直流分量function [mag, phase] extract_response(u, y, f, fs) % u: 输入正弦信号已知频率f % y: 对应输出稳态信号 % 假设u A*sin(2*pi*f*t)则y B*sin(2*pi*f*t phi) % 利用三角恒等式sin(ab) sin(a)cos(b) cos(a)sin(b) % 所以 y B*cos(phi)*sin(2*pi*f*t) B*sin(phi)*cos(2*pi*f*t) % 因此计算 t (0:length(y)-1)/fs; sin_ref sin(2*pi*f*t); cos_ref cos(2*pi*f*t); % 同步解调乘参考信号并低通滤波 % 使用移动平均滤波器FIR模拟理想低通截止频率约0.1*f N_fir round(fs/(10*f)); % 滤波器长度约10个周期 if N_fir 3, N_fir 3; end b ones(1, N_fir)/N_fir; % 简单均值滤波器 I filter(b, 1, y .* sin_ref); % 正弦通道同相分量 Q filter(b, 1, y .* cos_ref); % 余弦通道正交分量 % 取滤波后信号的最后10%作为稳态值避开滤波器启动瞬态 len_steady floor(length(I)*0.1); I_steady mean(I(end-len_steady:end)); Q_steady mean(Q(end-len_steady:end)); % 幅值和相位计算 mag sqrt(I_steady^2 Q_steady^2) * 2; % *2是因为sin/cos分解后幅度减半 phase atan2(Q_steady, I_steady); % 注意atan2(y,x)返回[-pi, pi] end为什么不用FFT举个反例若y含50Hz工频干扰FFT会在50Hz处出现尖峰污染目标频率点的测量。而同步解调只对f频率敏感其他频率成分经乘法后变成f±f_other再经低通滤波被彻底抑制抗干扰能力极强。实测中即使在强电磁干扰环境下同步解调的相位测量误差也能控制在±0.5°以内。2.3 第三步构建频响数据集并可视化诊断将所有频率点的mag和phase存入结构体形成标准的frdFrequency Response Data对象这是MATLAB频域分析的基石% 初始化FRD对象 mag_db 20*log10(mag_vec); % 转换为dB phase_deg phase_vec*180/pi; % 转换为度 % 创建frd对象注意freq_vec单位必须是rad/s freq_rad 2*pi*freq_vec; % 转换为rad/s sys_frd frd(mag_vec.*exp(1j*phase_vec), freq_rad); % 绘制Bode图进行诊断 figure; bode(sys_frd); grid on; title(实测频响数据 (FRD));这一步的关键是诊断数据质量。Bode图不是用来“看结果”的而是用来“找问题”的。重点关注三个异常特征幅值突变点在某个频率幅值突然跳变如20dB或-20dB大概率是该点未进入稳态或受噪声干扰严重。应剔除该点或重新测量。相位非单调对于物理可实现系统相位应随频率增加而单调下降负斜率。若出现局部上升如-90°→-85°→-95°说明该频段测量严重失真需检查传感器带宽或接地干扰。高频段信噪比崩溃当mag_db接近或低于-60dB时数据已不可信。此时应停止扫频或承认系统在此频段无法辨识。我曾遇到一个案例某液压阀的扫频Bode图在30Hz后相位剧烈抖动。排查发现是压力传感器固有频率仅40Hz高频响应失真。更换传感器后问题解决。因此Bode图的高频截止点往往由测量链中最薄弱环节的带宽决定而非被测系统本身。2.4 第四步模型结构选择与参数估计有了可靠的sys_frd下一步是拟合传递函数。MATLAB提供tfest传递函数估计和ssest状态空间估计两大主力函数。选择依据很明确如果最终目标是Simulink建模或PID控制器设计优先用tfest如果要做现代控制如LQR、观测器设计则用ssest。tfest的核心参数是np分母阶数和nz分子阶数。如何选不能拍脑袋。我的经验法则从物理机理出发直流电机负载典型二阶系统电枢电感L、电阻R、转动惯量J、阻尼B故np2。若带齿轮箱可能引入额外惯性np3。用np1到np5试拟合看AICAkaike Information Criterion指标AIC越小模型越优兼顾拟合精度与复杂度。MATLAB中tfest默认输出AIC值。避免过拟合np5可能拟合得完美但模型含4个极点其中2个可能是高频虚极点无物理意义导致仿真不稳定。宁可欠拟合不可过拟合。% 尝试不同阶数选择AIC最小者 best_sys []; best_aic Inf; for np 1:4 for nz 0:np-1 % 分子阶数通常≤分母阶数-1严格真分式 try sys_tf tfest(sys_frd, np, nz); if isstable(sys_tf) % 必须稳定 aic_val sys_tf.Report.Fit.FitCriterion.Akaike if aic_val best_aic best_aic aic_val; best_sys sys_tf; end end catch ME continue; % 拟合失败跳过 end end end % 验证对比FRD与拟合模型的Bode图 figure; bode(sys_frd, best_sys); legend(实测数据, 拟合模型); title(模型拟合效果验证);提示tfest默认使用加权最小二乘权重在低频更高因低频幅值大误差相对小。若你的系统在高频更关键如振动抑制可手动设置权重opt tfestOptions(WeightingFilter, tf([1 0], [1 100]));让高频误差权重提升。3. Simulink闭环验证为什么“拟合好”不等于“能用好”在MATLAB里bode(best_sys)曲线和实测数据贴合得严丝合缝是不是就万事大吉了绝对不是。我见过太多案例Bode图拟合误差1%但把best_sys放进Simulink做闭环控制一上电就振荡。根源在于扫频法只刻画了开环频响而闭环性能取决于整个回路的动态交互尤其是未建模动态unmodeled dynamics和延迟delay。3.1 未建模动态那个藏在角落里的“幽灵”所有传递函数模型都是近似。best_sys可能完美描述了0.1~50Hz的主动力学但忽略了几个关键“幽灵”执行器带宽限制驱动电机的PWM逆变器其开关频率通常在10kHz但有效控制带宽可能只有1~2kHz。best_sys没包含这个低通特性在Simulink里用理想电压源驱动相当于给了一个无限带宽执行器结果必然超调。传感器相位滞后编码器或电流传感器的采样延迟、滤波器群延迟在best_sys里被平均掉了但在真实闭环中这个几毫秒的延迟足以让相位裕度损失20°以上。结构柔性模态刚性体假设下best_sys是二阶。但实际机械臂连杆有微小弹性可能在200Hz存在一个未激发的谐振峰。扫频没扫到那里模型里就没有但PID控制器在100Hz附近增益一高就激发出这个“幽灵”系统尖叫。验证方法在Simulink中搭建真实硬件在环HIL或高保真仿真模型。例如用Simscape Electrical搭建电机详细模型含电感、电阻、反电势、转动惯量用Simscape Driveline搭建机械负载含柔性轴、齿轮间隙然后用best_sys作为控制器对比其与真实系统响应。若差异大说明未建模动态显著。3.2 延迟补偿一个被严重低估的致命因素数字控制中采样、计算、PWM更新、传感器反馈每个环节都引入延迟。总延迟τ通常在0.5~5ms。这个延迟在频域表现为e^(-jωτ)即相位损失-ωτ弧度。在穿越频率ω_c处相位损失就是-ω_c*τ。若ω_c100 rad/sτ2ms则相位损失已达-0.2 rad ≈ -11.5°。这对相位裕度是致命打击。扫频法测得的sys_frd其相位数据已经包含了实际系统中的所有延迟。但当你用tfest拟合时算法试图用有理分式逼近e^(-jωτ)结果往往是引入一对高频共轭极点这在数学上可行但物理上无意义且在Simulink仿真中容易数值不稳定。正确做法显式建模延迟。在best_sys后串联一个Transport Delay模块Simulink或pade(τ, n)近似MATLABtau 0.002; % 2ms延迟 n_pade 3; % Pade近似阶数 sys_delay pade(tau, n_pade); % 生成n阶Pade近似传递函数 sys_total series(best_sys, sys_delay); % 串联延迟Pade近似阶数n的选择n1一阶只在低频准确n3在中频更准n5高频也准但可能引入不稳定零点。实测推荐n3它在穿越频率附近相位误差5°且数值稳定。3.3 闭环仿真与参数微调从“拟合”到“可用”的最后一公里完成上述补偿后进入最终验证。在Simulink中搭建标准闭环[Reference] -- [Controller] -- [Plant Model (best_sys)] -- [Sum] -- [Output] ↑_______________________________|关键操作设置控制器为实际使用的PID参数不要用理论计算值用现场调试好的参数。因为理论计算基于best_sys而实际系统有未建模动态。加入真实采样与保持用Zero-Order Hold模块模拟ADC采样Rate Transition处理速率转换。注入真实噪声在Plant输出端加Band-Limited White Noise强度匹配实测传感器噪声水平如编码器±1 LSB。运行阶跃响应与正弦跟踪对比Simulink仿真输出和实测数据。重点看上升时间、超调量是否匹配在10Hz正弦指令下跟踪误差幅值、相位是否在可接受范围如5%若不匹配微调不是重拟合best_sys而是调整控制器参数或延迟值。例如若超调大说明相位裕度不足可微调PID的微分时间Td增加相位超前或略微增大tau估计值如从2ms调到2.3ms让模型更“钝”一点匹配真实延迟。经验闭环验证阶段模型best_sys的参数应视为“冻结”。所有调整都在控制器和延迟补偿环节。因为best_sys代表被控对象的“本体”特性而控制器和延迟是“接口”特性后者更容易在线标定。4. 扫频法 vs 其他辨识方法何时该用何时该换扫频法是系统辨识的“瑞士军刀”但并非万能。面对不同场景必须清楚它的优势边界和替代方案。我整理了一张实战决策表基于十年项目经验场景特征扫频法适用性替代方案理由与MATLAB实现要点系统缓慢、稳态易达如化工反应釜温度控制时间常数10min★★★★★无扫频法优势最大。低频点驻留时间充足Bode图信噪比高。用logspace(0,1,32)覆盖0.1~10mHz即可。系统快速、暂态难消如无人机姿态控制时间常数10ms★★☆☆☆PRBS序列扫频驻留时间要求与系统响应矛盾。PRBS是宽带信号一次激励激发全频段用idinput(prbs)生成idfdata封装数据tfest或ssest直接拟合。存在强非线性如带死区的液压阀、磁饱和电机★☆☆☆☆Hammerstein-Wiener模型扫频法假设LTI非线性下Bode图扭曲。用nlhw函数估计Hammerstein-Wiener模型它能分离静态非线性死区、饱和和动态线性部分。在线实时辨识需求如自适应巡航控制需实时更新车辆模型★☆☆☆☆Recursive Least Squares (RLS)扫频需停机实验。RLS算法可在线更新参数。MATLAB中用rls对象step方法递推更新适合嵌入式部署。多输入多输出MIMO系统如四旋翼的4输入-6输出★★★☆☆MIMO FRD拟合扫频法可扩展对每个输入通道单独扫频保持其他输入为零测所有输出通道响应构建MIMO FRD。用idfrd对象存储ssest估计MIMO状态空间模型。特别强调一个常见误区“扫频法精度一定比随机信号高”。这是错的。精度取决于信噪比和模型结构。在强噪声环境下PRBS的功率谱密度PSD是平坦的通过相关分析corrcoef能有效抑制噪声其信噪比反而优于扫频。MATLAB中iddata对象的plot方法可直接显示信噪比估计。另一个关键认知扫频法得到的模型其预测能力Prediction Error通常不如阶跃响应法得到的模型。因为扫频只提供频域信息而阶跃响应包含丰富的时域瞬态信息如上升时间、超调对模型结构更敏感。所以若你手头有高质量的阶跃实验数据优先用tfest(data, Ts, Ts)拟合它比从FRD拟合更鲁棒。最后关于Simulink集成扫频法估计出的sys_tf对象可直接拖入Simulink的Transfer Fcn模块参数自动填入。但要注意Transfer Fcn模块默认使用Direct形式直接型在高阶系统中易受数值误差影响。生产环境强烈建议转为State-Space形式[A,B,C,D] tf2ss(sys_tf.num{1}, sys_tf.den{1});然后用State-Space模块数值稳定性提升一个数量级。5. 那些教科书不会写的坑从实验室到产线的真实教训纸上谈兵和真实世界之间隔着无数个“看似微小却致命”的细节。这些坑只有亲手在电机台架上烧过保险丝、在PLC柜里查过半天接地、在客户现场熬过通宵才能刻进骨子里。以下是我踩过的、也帮别人填过的五个深坑每一个都附带MATLAB/Simulink里的具体解决方案。5.1 坑一接地环路引入的50Hz工频干扰让相位测量全盘作废现象扫频Bode图在50Hz处出现一个尖锐的幅值峰和相位跳变其他频点数据也毛刺严重。无论怎么屏蔽线缆、换电源都无法消除。根因不是电磁干扰而是接地环路Ground Loop。当DAQ设备、被控对象电源、PC机壳都接大地但接地电阻不同50Hz工频电流就在信号线上形成压降。这个压降叠加在微弱的传感器信号上成为强干扰。解决方案单点接地Single-Point Grounding。断开DAQ设备和PC的机壳接地用隔离变压器或电池供电只保留被控对象电源的地。在MATLAB中用硬件触发同步采集避免软件定时带来的相位漂移。更彻底的方案是使用隔离放大器如ADuM系列它在信号路径中加入光耦或电容隔离彻底切断地环路。Simulink中可在传感器信号入口处添加Isolated Analog Input模块需支持的硬件驱动。实操心得在开始扫频前先用示波器探头直接测量传感器输出端对地电压。若看到稳定的50Hz正弦波哪怕只有几mV就是接地环路。此时别急着调参数先搞定接地。5.2 坑二DAQ采样率不足导致高频相位测量系统性偏移现象在20Hz以上实测相位比理论模型预测值系统性偏移-10°~-20°且随频率升高偏移加剧。根因采样定理失效。虽然采样率fs1000Hz满足奈奎斯特100Hz但计算相位需要精确的过零点检测。若一个正弦周期内采样点太少如20Hz信号在1000Hz下只有50点过零点插值误差大。更严重的是ADC的孔径抖动Aperture Jitter在高频下会引入相位噪声。解决方案提高采样率并使用过采样Oversampling。将fs提升至5000Hz然后对采集数据做decimate降采样如降为1000Hz利用过采样平均效应抑制量化噪声和孔径抖动。MATLAB中% 过采样采集 fs_high 5000; y_raw acquire_data(fs_high * T_acquire); % 降采样至目标频率 fs_target 1000; y_decimated decimate(y_raw, fs_high/fs_target, fir);decimate函数默认使用抗混叠FIR滤波器比简单抽取y_raw(1:5:end)更准确。实测表明过采样5倍后20Hz相位测量误差可从±5°降至±0.5°。5.3 坑三执行器饱和未建模导致闭环仿真“看起来很美一上电就炸”现象Simulink闭环仿真完美但连接真实电机后给阶跃指令电机嗡嗡响却不转或直接触发过流保护。根因best_sys是线性模型假设输入电压可无限大。但真实驱动器有最大输出电压如±10V和电流限幅如±5A。当控制器计算出的指令超出此限执行器饱和系统进入非线性区线性模型完全失效。解决方案在Simulink模型中显式加入饱和模块。在Transfer Fcn模块输出后插入Saturation模块上下限设为驱动器实际限幅值。更重要的是在MATLAB辨识时主动激发饱和区在扫频信号上叠加一个缓慢变化的偏置Bias使某些频点的输入接近饱和阈值这样tfest会拟合出饱和前的线性段模型更鲁棒。代码中% 生成带偏置的扫频信号 u_with_bias A_vec(i) * sin(2*pi*f*t_gen) bias_level; % bias_level 根据驱动器规格设定如 0.8 * Vmax教训永远用真实执行器的限幅值去约束仿真模型。一个常见的错误是用“理论最大值”如电源电压代替“实际可用值”如驱动器允许的最大PWM占空比对应电压。5.4 坑四温度漂移让昨天拟合的模型今天就失效现象上午扫频拟合的模型下午在同一台设备上验证Bode图整体下移3dB相位滞后5°。根因电机绕组电阻随温度升高而增大。冷态25°C电阻为R热态70°C电阻为R*(1α*ΔT)其中铜的α≈0.0039/°C。电阻增大电时间常数τL/R减小系统带宽变宽但扭矩常数Kt也变化导致整体增益下降。解决方案建立温度-参数映射关系。在不同温度点用红外测温仪测量电机外壳下重复扫频拟合多个best_sys_T。用MATLAB的griddedInterpolant创建插值器T_vec [25, 40, 60, 75]; % 温度点 (°C) sys_vec {sys_25, sys_40, sys_60, sys_75}; % 对应模型 % 提取各模型的DC增益和主导极点 dc_gain_vec cellfun((x) dcgain(x), sys_vec); pole_vec cellfun((x) pole(x), sys_vec, UniformOutput, false); % 创建插值器 F_gain griddedInterpolant(T_vec, dc_gain_vec); F_pole griddedInterpolant(T_vec, cell2mat(pole_vec)); % 简化处理 % 实时温度T_real下插值得到当前模型参数 current_gain F_gain(T_real); current_pole F_pole(T_real);在Simulink中用MATLAB Function模块实时读取温度传感器数据动态更新Transfer Fcn模块的参数。这才是真正的自适应控制。5.5 坑五Simulink代码生成时传递函数模块报“无法生成代码”现象模型在Simulink中仿真正常但点击Build Model生成C代码时Transfer Fcn模块报错“Code generation for Transfer Fcn block is not supported for continuous-time systems”。根因Transfer Fcn模块默认是连续时间Continuous而嵌入式代码生成如Embedded Coder要求离散时间Discrete模型。直接用c2d离散化会引入额外相位滞后破坏控制性能