☰
基于Simulink的直流电机速度控制与PI参数整定仿真
2026/10/28 20:39:34 网站建设 项目流程

简介:一份面向自动化专业学生、机器人研发工程师及Simulink仿真学习者的技术文档,围绕直流电机速度控制系统的建模、控制与验证展开,适合需要掌握PID参数整定和仿真流程的初中级读者。内容按系统建模、控制器设计、传感器建模、仿真验证与性能优化五个阶段组织,既给出直流电机动力学方程和速度传感器噪声模型,也包含PID控制器实现、Simulink模型搭建及负载扰动下的响应分析,并附代码示例、图形界面和调优思路,便于对照复现与排查问题。压缩包共1个docx文件,约24KB,篇幅集中,适合作为课程设计或工程入门的参考材料。目前已有271人学习,可帮助读者理解速度闭环的搭建方法、参数调节对稳定性和响应速度的影响,并积累从模型到仿真的完整实践路径。

1. 从一台抖动的电机说起:Simulink 仿真是怎么把 PI 参数"算"出来的

某实验室的一台 24V 小功率直流电机,空载时转速挺稳,一带上惯量负载,转速就在设定值附近来回摆,PID 参数凭手感调了三天,换一批电机又全废。后来把整套回路搬进 Simulink 里,先让模型和实测对上,再在模型里批量扫参,上机只微调两轮就收敛了。基于 Simulink 的直流电机速度控制系统设计与仿真,核心不是"画个模型跑个波形",而是把调参从试错变成可复现的计算:电机模型对不对、闭环拓扑选哪种、PI 参数按什么规则算、仿真结果凭什么可信。适合做电机控制入门、课程设计、产品预研的人,也适合已经会拖模块但总调不好参数的人。

2. 把电机拆成三个方程:直流电机模型怎么建才不会和实物对不上

2.1 电气方程与机械方程的耦合:为什么不能只写一个一阶惯性环节

很多入门教程把直流电机写成一个一阶惯性环节 K/(Ts+1),能跑出"像那么回事"的曲线,但一旦你接的是电流环加转速环的双闭环,或者要看启动瞬间的电流冲击,一阶模型立刻露馅。原因很简单:一阶模型把电气动态和机械动态压成了一个时间常数,而真实电机里这两个过程差着几十倍。

老老实实写三个方程。电枢回路:u = Ra·i + La·di/dt + e,其中反电动势 e = Ke·ω;电磁转矩 Te = Kt·i;机械运动方程 Te − TL = J·dω/dt + B·ω。消去中间量 i,得到电压到转速的传递函数:

ω(s)/U(s) = Kt / [La·J·s² + (Ra·J + La·B)·s + (Ra·B + Kt·Ke)]

这个二阶环节有两个极点,一个由电气时间常数 La/Ra 决定,落在几百 rad/s;另一个由机械时间常数近似等于 Ra·J/(Kt·Ke) 决定,落在十几到几十 rad/s。拿一组典型参数算一下:电气极点约 −460 rad/s,机械极点约 −19.6 rad/s,差了 23 倍。这个数量级差就是双闭环能分层整定的物理基础,也是后面"内环带宽必须远高于外环"这条规则的来源。

还有一处容易忽略:在 SI 单位制下 Kt 和 Ke 的数值相等。由功率守恒 Te·ω = e·i 可直接推出 Kt = Ke,所以只需辨识一个量。但工程样本上反电动势常数常写成 V/1000rpm,和 V·s/rad 之间差 10.47 倍(1000 rpm 折合 104.72 rad/s),这是最常见的量纲翻车点之一。

2.2 从铭牌数据反推 Ra、La、J、Ke:一套可复现的辨识流程

参数不准,后面所有整定都是空中楼阁。我一般按下面这张表逐项拿数据,能测的绝不用猜。

参数符号获取方法示例值
电枢电阻Ra堵转下用毫欧计测两端,转三个角度取平均1.2 Ω
电枢电感LaLCR 表在不同转子位置测,取平均2.5 mH
反电动势常数Ke外力拖动,测多组转速下的开路电压,过原点最小二乘0.075 V·s/rad
转动惯量J已知附加惯量的两次惰转对比,或厂家数据2.5e-4 kg·m²
粘滞系数B空载惰转曲线尾部拟合8e-6 N·m·s/rad

把测量数据丢进脚本,别手算:

% identify_dcmotor.m —— 由实验数据反推 Ke、J、B rpm = [500 1000 1500 2000 2500 3000]'; % 拖动转速,r/min emf = [0.65 1.29 1.94 2.59 3.23 3.88]'; % 对应开路电压,V w = rpm * 2*pi/60; % 统一换算成 rad/s Ke = w \ emf; % 过原点最小二乘 fprintf('Ke = %.4f V·s/rad, 折合 %.3f V/1000rpm\n', Ke, Ke*104.72); % 惰转:断电后 w(t) = w0*exp(-t/tau),只能定出 J/B 的比值 tau1 = 0.0495; % 空载惰转拟合出的时间常数,s tau2 = 0.0880; % 加装 J_add 后的时间常数,s J_add = 2.0e-4; % 附加惯量,kg·m^2 J = J_add * tau1 / (tau2 - tau1); B = J / tau1; fprintf('J = %.3e kg·m^2, B = %.3e N·m·s/rad\n', J, B);

第一段用左除做过原点最小二乘,因为 e = Ke·ω 理论上无截距;如果拟合出来截距明显不为零,说明低速点被轴承摩擦污染了,把那几个点剔掉再拟。第二段是这里的关键:单次惰转只能得到 J/B 的比值,J 和 B 无法分开,所以必须做两次——先空载跑一次,再在轴上装一个已知惯量的圆盘跑一次,两个方程解两个未知数。参数说明:tau 取对数拟合的斜率倒数,别用肉眼读第一个过零点,误差能差 10%;J_add 用称重加尺寸算,比标称值靠谱。

2.3 用一段脚本验证模型:传递函数、直流增益和阶跃响应对不对得上

参数齐了先别打开 Simulink,在命令行把传递函数跑一遍,做三个便宜的合理性检查:极点位置、直流增益、不同实现方式的一致性。

% check_model.m —— 建模前的自检 Ra = 1.2; La = 2.5e-3; Ke = 0.075; Kt = 0.075; J = 2.5e-4; B = 8e-6; num = Kt; den = [La*J, Ra*J + La*B, Ra*B + Kt*Ke]; G = tf(num, den); p = pole(G); fprintf('极点: %.1f rad/s (tau=%.1f ms), %.1f rad/s (tau=%.2f ms)\n', ... p(1), 1000/(-p(1)), p(2), 1000/(-p(2))); w_ss = dcgain(G) * 24; % 24V 阶跃下的空载稳态转速 fprintf('空载稳态: %.1f rad/s = %.0f r/min\n', w_ss, w_ss*60/(2*pi)); sys_ss = ss(G); % 换成状态空间实现再算一遍 [y1, t] = step(G, 0.5); y2 = step(sys_ss, t); fprintf('两种实现最大偏差: %.2e\n', max(abs(y1 - y2)));

逻辑说明:第一段读极点,机械极点落在 −19.6 rad/s、电气极点落在 −460 rad/s,说明参数自洽;如果两个极点挤在同一个数量级,八成是 La 或 J 少写了一个数量级。第二段用 dcgain 乘 24V 得空载转速,算出来 3050 r/min 左右符合直觉,算出来 300 或 30000 就得回去查单位。第三段把传递函数转成状态空间再阶跃一次,是为了排除高阶传递函数在 La 很小时的数值病态——两条曲线偏差应该小到可以忽略,出现明显偏离说明系数矩阵已经病态了。参数说明:step 的第二个参数 0.5 s 取六倍机械时间常数,够看到稳态;dcgain 的单位是 rad/(s·V),乘电压得转速。

进 Simulink 建模时,我建议用积分器按物理方程搭,而不是直接拖一个 Transfer Fcn。理由有三个:能直接观察电流和转矩这两个中间量,排查限幅和饱和问题时不用反推;加摩擦非线性、死区、电压跌落这些环节时只需在方程上补一项;参数改动能立刻反映到每个积分器的增益上。模块清单大致是:电枢回路一个 Integrator(增益 1/La)加一个 Sum 减反电动势,机械方程一个 Integrator(增益 1/J)加一个 Sum 减负载转矩和粘滞项,反电动势和转矩各一个 Gain。全部参数用工作区变量,别写死数字,否则第 4 章批量扫参时你只能一个个手改。

3. 单闭环还是双闭环:速度控制系统的结构选型与拓扑搭建

3.1 单闭环 PI 够用的场景与它的天花板

只有转速环、PI 输出直接当电枢电压指令,这是最省事的结构,风机、小水泵这类对启动电流不敏感、负载变化慢的场合完全够用。但它的天花板非常明确:限流靠电压限幅间接实现,等于没有限流。

算一笔账就清楚了。这台电机 Ra = 1.2 Ω,24V 全额加在电枢上,启动瞬间反电动势为零,堵转电流就是 20 A。额定电流按 3 A 算,等于 6.7 倍过载,真实电机的换向器和绕组撑不了几次。单闭环里 PI 输出饱和在 24V,电流就一直是 20 A,直到转速爬上来反电动势把它顶下去。仿真里看着曲线挺顺,实物上第一次启动就可能冒烟。

除此之外还有两个隐性代价。一是扰动恢复慢:负载转矩阶跃时,转速必须先掉下去,误差积累起来,PI 才把电压抬上去,整个过程受机械时间常数约束。二是电源利用率低:为了让转速环有调节余量,稳态工作点必须留出电压裕量,等于牺牲了调速范围。所以只要涉及频繁启停、堵转风险、或者要求带载转速跌落小,就该上双闭环。

3.2 电流内环加转速外环:双闭环的搭建顺序与带宽分离

双闭环的结构不复杂:转速环 PI 的输出不再是电压,而是电流给定;电流环 PI 的输出才是电压指令;两个环各自带限幅,电流环的限幅就是硬件保护的软对应。关键是搭建顺序和带宽分配。

带宽分离是硬规则:电流环穿越频率取开关频率的 1/10 到 1/20,转速环穿越频率再取电流环的 1/10 左右。按 20 kHz 开关频率算,电流环带宽 1000 Hz(6283 rad/s),转速环带宽 15 Hz(94 rad/s),中间差 60 多倍。这样整定的好处是,转速环设计时可以把闭合的电流环当成增益为 1 的比例环节,对象退化成 Kt/(J·s + B),一阶,手算都能出参数。如果两个带宽拉不开,两个环会互相打架,你在转速环上做的任何调整都会通过电流环反馈回来,变成玄学。

搭建顺序我一般这么走:先把电流环单独闭合,给定一个阶跃电流,看实际电流跟踪;跟踪上了再把电流环封装成子系统,外面套转速环;最后加负载转矩阶跃和给定阶跃两组测试。命令行能省掉大量拖拽工作:

% build_speed_loop.m —— 命令行搭骨架,其余模块按上表手动补 model = 'dcm_speed_2loop'; if bdIsLoaded(model), close_system(model, 0); end new_system(model); open_system(model); % 1) 转速给定:0.05 s 阶跃到 3000 r/min,折合 314.16 rad/s add_block('simulink/Sources/Step', [model '/n_ref'], ... 'Position', [30 100 60 130], ... 'Time', '0.05', 'Before', '0', 'After', '314.16'); % 2) 转速环 PI,输出为电流给定,限幅对应最大允许电流 add_block('simulink/Continuous/PID Controller', [model '/pi_n'], ... 'Position', [130 95 190 145], ... 'Controller', 'PI', 'P', 'Kp_n', 'I', 'Ki_n', ... 'LimitOutput', 'on', 'UpperSaturationLimit', '3', ... 'LowerSaturationLimit', '-3'); % 3) 被控对象先用平均模型占位,后续替换为双闭环子系统 add_block('simulink/Continuous/Transfer Fcn', [model '/motor'], ... 'Position', [420 95 500 145], ... 'Numerator', 'Kt', ... 'Denominator', '[La*J, Ra*J+La*B, Ra*B+Kt*Ke]'); add_line(model, 'n_ref/1', 'pi_n/1', 'autorouting', 'on'); add_line(model, 'pi_n/1', 'motor/1', 'autorouting', 'on'); add_line(model, 'motor/1', 'pi_n/2', 'autorouting', 'on');

逻辑说明:P 和 I 两个参数直接写变量名 Kp_n、Ki_n,而不是具体数字,Simulink 在每次仿真开始时会去基础工作区取值——这是第 4 章批量扫参能跑起来的前提,参数写死了就只能手改。转速环输出限幅设成 ±3,正好对应额定电流,物理含义是"最多给到额定转矩",这个限幅值不是随便填的,它决定了启动加速能力和堵转保护阈值。连线用 autorouting 避免手工坐标算错。

参数说明:add_block 的第一个参数是库路径,不同版本里 PID Controller 的位置可能有细微差别,找不到就用 add_block('simulink/Continuous/PID Controller') 先试,报错再在库浏览器里搜索模块名。Step 模块的 After 值必须和你的转速单位一致,这里用的是 rad/s,和模型内部单位统一,避免在反馈回路上再乘换算系数。

3.3 PWM 与 H 桥:平均模型和开关模型该选哪个

这是新手最容易纠结的地方,我的答案是两个都要,但用在不同阶段。

平均模型把占空比 d 当成连续量,电枢平均电压等于 d·Vdc,没有开关纹波、没有死区、没有电流断续。它的好处是仿真快、波形干净、PI 参数整定友好,扫 25 组参数几分钟就跑完。缺点是它会系统性地高估系统的相位裕度,因为忽略了 PWM 的采样保持效应和死区畸变。

开关模型要加三角波载波、比较器、H 桥桥臂,能看到电流纹波、死区造成的过零畸变、轻载时的电流断续。它的代价是步长必须压到微秒级,仿真时间成倍增长,而且参数整定阶段波形毛刺会让你根本看不清趋势。

我的用法是:整定全部在平均模型上做,拿到参数后用开关模型验证一遍,如果开关模型的超调比平均模型大 10 个百分点以上,说明相位裕度不够,把电流环带宽往下压 20% 再验证。这个"平均模型整定、开关模型验收"的两段式流程,比直接在开关模型上一点点试要快得多,也更接近实际调试里先低频后高频的思路。

4. PI 参数整定:从工程公式出初值,再到 Simulink 里批量扫参

4.1 内环先整、外环后整:一组能直接抄的初值公式

电流环的对象是 1/(La·s + Ra),用 PI 做零极点对消,取积分时间 Ti = La/Ra,开环传函退化成 Kp/(La·s),穿越频率 ω_ci = Kp/La。反解出两个参数:

Kp_i = ω_ci · La,Ki_i = ω_ci · Ra

代入数值,ω_ci 取 2π×1000 = 6283 rad/s:Kp_i = 2.5e-3 × 6283 ≈ 15.7,Ki_i = 1.2 × 6283 ≈ 7540。

转速环把闭合的电流环近似为 1,对象变成 Kt/(J·s + B),用 PI 把穿越频率放在 ω_cn = 2π×15 = 94.2 rad/s:Kp_n = J·ω_cn/Kt ≈ 0.314,积分零点放在穿越频率的 1/4 处,Ki_n = Kp_n·ω_cn/4 ≈ 7.4。

这组数不用迷信,它只是把搜索范围从"整个实数域"缩到"初值上下 50%"。不同开关频率下的推荐初值可以按下面这张表取:

开关频率电流环带宽Kp_iKi_i转速环带宽Kp_nKi_n
10 kHz500 Hz7.9377010 Hz0.2093.3
20 kHz1000 Hz15.7754015 Hz0.3147.4
40 kHz2000 Hz31.41508025 Hz0.52420.6

表里最右两列的转速环参数随开关频率变化,是因为电流环带宽提高后外环才有条件做得更快——如果电流环跟不上,把转速环调快只会得到一堆振荡。这也是为什么整定必须内环先行:外环的可用带宽是内环"让"出来的。

4.2 用 for 循环批量扫参:把阶跃响应族画在一张图上

手算初值之后,剩下的工作交给脚本。思路是把 Kp、Ki 各扫五档,每次仿真记录超调和调节时间,最后画成响应族或热力图。

% sweep_pi.m —— 转速环参数扫描,模型需已存在且参数用变量名 Kp0 = 0.314; Ki0 = 7.4; Kp_list = linspace(0.6*Kp0, 1.4*Kp0, 5); Ki_list = linspace(0.5*Ki0, 1.5*Ki0, 5); ref = 314.16; % 给定阶跃幅值,rad/s res = zeros(numel(Kp_list)*numel(Ki_list), 4); row = 0; for a = 1:numel(Kp_list) for b = 1:numel(Ki_list) assignin('base', 'Kp_n', Kp_list(a)); assignin('base', 'Ki_n', Ki_list(b)); out = sim('dcm_speed_2loop', 'StopTime', '0.8', ... 'SaveOutput', 'on', 'OutputSaveName', 'yout'); y = out.yout; % 旧版本用 [t,y] = sim(...) info = stepinfo(y, y.Time, ref); row = row + 1; res(row, :) = [Kp_list(a), Ki_list(b), ... info.Overshoot, info.SettlingTime]; end end disp(array2table(res, 'VariableNames', ... {'Kp_n','Ki_n','Overshoot','SettlingTime'}));

逻辑说明:assignin 每次把新参数推到基础工作区,Simulink 在仿真启动时重新读取,这是不用改模型就能扫参的关键;如果参数是写死在模块对话框里的数字,这个循环跑一百次也是同一组结果。sim 的 StopTime 覆盖模型里的设置,避免为了改仿真时长去动模型。stepinfo 的第三个参数必须显式给稳态值,因为从 0 阶跃到 314.16 的过程中,如果让 stepinfo 自己估稳态,它在欠阻尼情况下会把第一个峰值当稳态,超调量算出来是负的。

参数说明:StopTime 取 0.8 s,约为机械时间常数的 15 倍,保证最慢的一组也能进稳态;OutputSaveName 指定信号记录名,取的时候注意不同版本返回的是 Dataset 还是数组,报错就先 disp(out) 看一眼结构。扫出来的典型关系大致是:Kp 从 0.22 涨到 0.44,调节时间从 0.21 s 缩到 0.10 s,超调从 2% 涨到 19%;Ki 单独加大到 15 时超调冲到 26% 而调节时间反而变长,这是积分过强引起的振荡,属于典型的需要往回退的信号。

4.3 抗积分饱和与给定滤波:两个必须加的补丁

大阶跃下 PI 输出撞上限幅,误差还在,积分项继续累加,等转速追上来了积分项还得慢慢泄放,结果就是超调 40% 加上退饱和拖尾。这个问题在纯线性仿真里看不到,因为线性模型里没有限幅。

两个补丁。第一是抗积分饱和,直接用 PID 模块内置的机制,别自己在外面串 Saturation 然后再把积分器开着——那样限幅只管住了输出,管不住积分器内部状态,等于没做。第二是给定滤波,在阶跃给定后面串一个一阶环节 1/(Tf·s+1),Tf 取 1/ω_cn,代价是上升时间变长一点,收益是超调显著下降。

% 打开抗饱和并设置给定滤波 set_param([model '/pi_n'], 'AntiWindupMode', 'clamping'); Tf = 1/(2*pi*15); % 给定滤波时间常数,约 10.6 ms set_param([model '/n_ref'], 'After', '314.16'); % 在 n_ref 与 pi_n 之间插入一阶滤波,或用 Transfer Fcn 模块: % Numerator = [1], Denominator = [Tf 1]

逻辑说明:AntiWindupMode 选 clamping 是最省事的做法,输出饱和时冻结积分;如果要做无扰切换或者多环串联,用 back-calculation 更平滑,但需要额外设置回算增益 TrackingKi,调不好反而引入新的振荡,入门阶段先用 clamping。给定滤波的时间常数取转速环穿越频率的倒数,是因为这个频率以上的给定变化本来就会被闭环衰减掉,提前滤掉不损失跟踪性能。滤波器插在给定通道上,不要插在反馈通道上——插在反馈上等于给整个闭环加滞后,相位裕度会被吃掉,这是很多人调不好时的错误操作。

5. 踩过的坑:仿真跑通但一上实物就翻车的 5 个排查点

5.1 同一组参数每次跑出来的波形都不一样:变步长求解器撞上开关事件

现象:模型里一加 PWM 比较器,两次仿真的超调量能差 8 个百分点,波形上还有孤立尖刺。

原因:默认的 ode45 是变步长求解器,它会在开关跳变附近自动缩步长,但缩到多少由误差容限决定,不是由你控制。开关时刻落在两个积分步之间时,求解器会"跨过去",等效成一次随机的延时抖动。

解决:换成定步长 ode4 或 ode1,步长取开关周期的 1/20 到 1/50。20 kHz 对应周期 50 μs,步长取 1 μs。代价是仿真变慢,但结果可复现。模型配置里把 Solver 设成 Fixed-step、Discrete 或者定步长连续都行,关键是 Max step size 别留 auto。

5.2 稳态转速差了将近十倍:rpm 和 rad/s 在回路里混用

现象:给定 3000,反馈稳定在 286 或者 31400 附近,怎么调 PI 都对不上。

原因:给定用的是 r/min,模型里的转动惯量和反电动势常数是按 rad/s 标定的,中间少乘或多乘了 2π/60。另一个变体是反电动势常数用了样本上的 V/1000rpm,直接当 V·s/rad 填进去,差 10.47 倍。

解决:全流程统一 SI 单位,只在人机接口处换算一次,并且把换算写成脚本顶部的常量,比如 RPM2RAD = 2*pi/60,所有给定、显示、报表都调这个常量,不在模型里出现裸数字。辨识脚本里打印结果时同时输出两种单位,肉眼扫一眼就能发现量级不对。

5.3 平均模型整定好的参数,换成开关模型就振荡:被忽略的 PWM 延时

现象:平均模型超调 5%、调节时间 0.13 s,换成开关模型后超调 25%,电流环开始持续振荡。

原因:PWM 的采样保持效应等效成半个到一个开关周期的纯延时,20 kHz 下就是 25 到 50 μs。这个延时在频域上贡献相位滞后,频率越高滞后越大,正好落在电流环的穿越频率附近,把相位裕度吃掉了。

解决:整定时就把电流环带宽压到开关频率的 1/20 而不是 1/10,或者在设计阶段用 Pade 近似把延时环节显式加进模型里,让平均模型提前"看到"这部分滞后。验收时以开关模型的相位裕度为准,一般要求不低于 45°。

5.4 限幅加了但退饱和还是很慢:限幅位置放错了

现象:启动时电流给定冲到 3 A 顶住不动,转速到给定值后电流迟迟降不下来,转速冲过头再掉回来。

原因:限幅器串在 PI 输出之后,只截住了输送给下一级的信号,PI 模块内部的积分状态照样在累加。误差持续为正的这段时间里,积分项已经涨到远超限幅值的水平,退饱和要靠负误差慢慢往回积分。

解决:用 PID 模块自带的输出限幅加抗饱和,让限幅动作能反过来冻结或回算积分项。判断方法很直接:把积分项单独引出来看波形,如果它在饱和期间还在单调上升,就说明抗饱和没生效。

5.5 加载之后转速反而往上走:负载转矩的符号或者作用点反了

现象:在 0.3 s 加一个 0.1 N·m 的负载阶跃,转速不降反升,或者先降后升出现一个奇怪的凹坑。

原因:机械方程是 J·dω/dt = Te − TL − B·ω,负载转矩必须以负号进入求和,而且要和 Te 加在同一个求和节点上。把 TL 直接加到转速信号上,或者用 Gain 取绝对值后相加,都会得到反向的结果。

解决:在模型里给转矩求和节点单独命名,接线后打印一次稳态值核对:空载时 Te 应该约等于 B·ω(很小),加载后 Te 应该上升到 TL + B·ω。数值对不上就是符号错了,不用看波形。

6. 从连续域到可移植代码:一份验收清单和一个离散化习惯

仿真跑得漂亮只是及格线,真正决定这套东西有没有用的是两件事:结果可信、参数能落地。

先给验收清单。阶跃给定下看四项:稳态误差是否为 0(有积分就应该为 0,不为 0 说明积分被限幅卡住了)、超调量是否在 10% 以内、调节时间是否在 0.2 s 量级、电流是否始终贴住 3 A 限幅而不过冲。负载阶跃下看一项:转速跌落的最大值和恢复时间,跌落超过 5% 说明转速环积分偏弱。

然后是离散化。Simulink 里跑的是连续域 PI,写进控制器要变成差分方程,这一步不做,参数搬过去必然有偏差。我习惯用后向欧拉,因为它不需要历史误差的额外存储,实现简单:

% 把连续 PI 离散成可移植的差分形式 Ts = 50e-6; % 与 PWM 同频,20 kHz Kp = 0. <p> <a href="https://download.csdn.net/download/xiaoheshang_123/90006663" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询