news 2026/9/9 19:14:17

基于CODESYS的汇川中大型PLC开发实战:环境搭建、ST编程与通讯故障排查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于CODESYS的汇川中大型PLC开发实战:环境搭建、ST编程与通讯故障排查

在工业自动化这行摸爬滚打多年,从日系PLC到国产PLC都碰过,但真正让我觉得“编程体验”上了一个台阶的,是第一次用CODESYS开发汇川AC801运动控制项目。汇川不只是做变频器和小型PLC,它的中大型PLC产品线——AC801实时运动控制器、AM400/AM600系列中型PLC——底层全部跑在CODESYS V3平台上。这意味着什么?意味着你用汇川AM600做过程控制,和用AC801做多轴运动控制,用的是同一套CODESYS开发环境,只是设备描述文件和许可证不同。这篇文章就是想把这条“奇妙之旅”上的实践细节、踩坑教训和选型思路完整记录下来,适合刚接触汇川中大型PLC、或者正打算从InoProShop切换到CODESYS平台的工程师参考。

1. 为什么汇川中大型PLC会站在CODESYS这条赛道上

1.1 从InoProShop到CODESYS:一次开发环境的“换挡”

很多人第一次打开汇川AM600的编程软件时会发现,界面似曾相识。没错,汇川的InoProShop本质上就是基于CODESYS V3定制出来的,只是换了一套品牌壳、汉化了菜单、内置了汇川的硬件库。所以当你用InoProShop写AM400/AM600时,你已经默默在使用CODESYS了;而当你直接用CODESYS V3.5连接AC801、AM400、AM600时,反而会看到更“原汁原味”的IEC 61131-3编程环境。

从工程角度来说,CODESYS真正值钱的地方不只是“标准编程语言”,而是它把控制器开发需要的东西全揉在了一起:IEC 61131-3六种编程语言、PLCopen运动控制库、现场总线配置(EtherCAT/CANopen/Modbus)、可视化界面、在线调试、库管理。这套生态对设备厂家特别友好,所以你会发现不光是汇川,很多国产中高端PLC、运动控制器都在CODESYS上做二次开发。对工程师来说,这是一个“学一次,多个品牌通用”的赛道。

1.2 AC801、AM400、AM600三兄弟的定位差异

汇川这三款产品虽然都跑在CODESYS平台上,但定位完全不同,项目选型时先要拎清楚。

型号产品定位主要接口与总线运动控制能力典型应用
AC801运动控制器EtherCAT、以太网、CANopen、RS485最多支持几十轴,EtherCAT同步锂电设备、3C贴装、包装机械、飞剪/追剪
AM400中型PLC以太网、CANopen、RS485、EtherCAT(部分型号)可带少量轴,逻辑为主单机设备、注塑机辅机、小型产线
AM600大型/过程级PLC双以太网、CANopen、Profibus-DP可选、EtherCAT可选偏逻辑与过程控制,运动能力弱于AC801产线级控制、暖通空调、能源管理、大型设备集中控制

我自己的选型经验:只要项目里有超过两三个伺服轴、且有高速同步需求,直接上AC801;如果只是做产线逻辑控制、数据采集、HMI通讯,AM600的双网口和较大程序空间更合适;AM400则刚好卡在两者中间,适合“逻辑为主、轴不超过四五个”的工况。千万不要用AM400硬撸多轴运动控制,到后期扩展轴数和扫周期时你会非常难受。

2. 开发环境准备:从安装到第一次上载程序的完整链路

2.1 CODESYS安装与设备描述文件的“坑”

CODESYS安装本身不算难,去官网下载CODESYS V3.5(建议SP17以上版本,汇川的库对新版本兼容性更好),一路Next装完。但紧接着就会遇到第一个坑:打开CODESYS新建工程时,Device列表里压根找不到AC801、AM400、AM600。这是因为你还没装汇川的设备描述文件,也就是Package包。

正确操作顺序是:

  1. 安装CODESYS V3.5基础环境。
  2. 从汇川官网或随附资料包获取对应的设备包文件(通常是.package或.codesys-package格式)。
  3. 在CODESYS主界面点击“工具 → 包管理器 → 安装”,选择汇川设备包。
  4. 安装完成后重启CODESYS,新建工程时就能在设备列表里看到汇川的控制器型号。

这个步骤最大的坑是版本匹配。比如你装了CODESYS V3.5 SP19,但汇川设备包是基于SP17编译的,那么大多数情况下没问题;如果反过来,设备包基于SP20编译,你的环境是SP17,CODESYS会直接拒绝加载或报“未找到依赖的库”。所以我的习惯是:装环境和装设备包前,先看一眼汇川官方发布说明里推荐的CODESYS版本,不要盲目追新。

2.2 连接方式与上载程序:源文件不是你想上就能上

AM400/AM600/AC801都支持以太网连接,部分型号有USB口。以太网连接最简单,把电脑和PLC放进同一个网段,新建工程后在设备树里双击“Device”,设置IP地址,点击“登录”即可。这里有个小坑:如果现场PLC的IP地址忘了,先用汇川的搜索工具或CODESYS的“扫描网络”功能搜一下,有些老固件默认是通过拨码设置IP,改之前记得拍照记录。

再说上载程序。很多工程师第一次用CODESYS上载汇川PLC时都会问同一个问题:“为什么我上载回来的工程没有源代码,只有一堆功能块和变量?”答案是:这取决于下载程序时有没有勾选“包含源代码”选项。CODESYS的工程下载到PLC时,默认状态下可以选择是否把完整源代码一并写入控制器。如果没勾选,PLC里只有编译后的机器码,上载时只能得到代码框架、变量表和库引用,没法还原ST和梯形图。

所以项目管理上要形成一条铁律:下载前主动勾选“允许上载源代码”,或者干脆在每次下载时选“工程 → 创建引导工程”,把源代码打进引导程序里。现场维护人员上载回来后,至少能拿到一份可读、可修改的工程。

2.3 下载程序的三种启动方式

CODESYS下载程序时,会弹出一个对话框让你选择启动方式:热启动(Warm Reset)、冷启动(Cold Reset)、初始化复位(Origin Reset)。这也是新手容易搞混的地方。

  • 热启动:保留保持变量和普通变量,处理器重新开始执行程序。适合程序小改动后快速恢复生产。
  • 冷启动:清除普通变量,保持变量(VAR RETAIN)保留,重新初始化程序。适合需要重新初始化状态、但不想丢失掉电保持数据的场景。
  • 初始化复位(Origin Reset):把所有变量(包括保持变量)全部清零,回到出厂般的初始状态。适合调机阶段或者程序逻辑大规模重构后。

我的建议:生产设备上做在线下载时,默认选“热启动”或“冷启动”,选之前一定要确认设备处于安全状态;调试阶段可以随便点,但不要养成一有问题就“Origin Reset”的习惯,否则掉电保持的配方、累计产量、补偿参数全部清零,现场会很难看。

3. 用ST语言写汇川PLC:从梯形图思维到文本编程的切换

3.1 ST语言为什么在CODESYS项目里是主力

虽然CODESYS支持梯形图、功能块图、顺序功能图、结构化文本等多种编程语言,但我在做汇川AC801/AM400/AM600项目时,主力语言几乎全是ST(结构化文本)。原因很简单:这套设备的项目通常不是“几个点动、互锁”那么简单,而是要处理运动控制、配方管理、数据通信、报警分级、产量统计。这些内容如果用梯形图写,动辄几十个网络页,翻页翻到怀疑人生;用ST写,一段CASE状态机就能把十几步动作描述清楚。

而且CODESYS支持同一个工程里不同POU用不同语言:简单逻辑用梯形图,复杂算法用ST,状态流程用SFC。我会在设备树里明确分工,比如轴控制FB全部用ST,外围气缸逻辑用LD,流程主控用SFC,让不同习惯的维护人员都能上手。

3.2 正弦运动、延时指令、比较中断的ST写法

先说延时。传统PLC里是TON/TOF定时器,CODESYS里也一样,但用ST调用功能块的写法对新手需要适应一下:

VAR fbDelay : TON; bStart : BOOL; bDelayOK : BOOL; END_VAR fbDelay(IN := bStart, PT := T#5S); bDelayOK := fbDelay.Q;

这样一段代码就实现了输入信号保持5秒后输出的效果。注意TON的实例必须声明为VAR,不能每次调用都重新声明,否则定时器计时会被不断清零。

再说“比较中断”。这个词在汇川小型PLC(比如H3U/H5U)里有对应指令,但AM400/AM600/AC801这套CODESYS平台里并没有传统意义上“数值达到某个值就立即中断主程序”的指令。更常规的做法是建立一个高优先级独立循环任务,比如1ms任务,专门做比较逻辑:

IF rActualSpeed >= rSpeedLimit THEN bSpeedAlarm := TRUE; ELSE bSpeedAlarm := FALSE; END_IF

这个任务独立于主程序运行,扫描周期固定1ms,一旦实际速度超过阈值,bSpeedAlarm在1ms内就能翻转,效果上已经非常接近“比较中断”。在AC801上做运动控制时,我常用这种方式做软限位和跟随误差保护,比在默认主任务里比较可靠得多。

最后说正弦运动。如果项目里需要做往复运动、摆动、或者傅里叶式速度规划,CODESYS的运动控制库里不一定有封好的“正弦运动”功能块,通常我会自己写一个速度规划FB,比如实现“速度按正弦曲线变化”。

FUNCTION_BLOCK FB_SineMove VAR_INPUT fAmplitude : REAL; // 最大速度幅值 fFrequency : REAL; // 摆动频率 Hz END_VAR VAR_OUTPUT fVelocityCmd : REAL; // 当前速度指令 END_VAR VAR fbCycle : TON; fTime : LREAL; bFirst : BOOL := TRUE; END_VAR // 每10ms累加一次时间 fbCycle(IN := TRUE, PT := T#10MS); IF fbCycle.Q THEN fbCycle(IN := FALSE); fTime := fTime + 0.01; END_IF fVelocityCmd := fAmplitude * SIN(6.28318 * fFrequency * fTime);

然后在运动控制轴里用MC_MoveVelocity功能块,把fVelocityCmd作为速度输入即可。这样做的好处是运动曲线平滑,对机械冲击小,特别适合涂胶、点胶、往复打磨这类应用。

3.3 文件读写与动态文本的实际用法

CODESYS平台最让我喜欢的点之一,就是它对文件操作的支持。在传统国产小型PLC里,想存一条配方或导出一条报警记录,往往要拼外部HMI去实现;而在CODESYS里,可以直接用CAA File库对U盘或控制器本地文件做读写。

一个很实用的场景是做配方导入导出。把一台设备的几十个工艺参数存成CSV文件,放在U盘里,PLC启动时去读,操作工改配方时直接在触摸屏上选文件,PLC自动加载。核心代码是:

// 打开文件 hFile := FileOpen(sFileName, FILE_MODE_READ OR FILE_MODE_BINARY); // 读取一行 FileRead(hFile, pBuffer, uiSize, uiRead); // 关闭文件 FileClose(hFile);

注意sFileName的路径格式取决于目标设备,Windows控制器用盘符路径,Linux控制器用挂载路径,最好在手册里确认。另外文件读写不要放在1ms或者5ms的快速任务里,会拖慢任务周期,我一般放在普通任务或专门的任务里,由标志位触发执行。

再说动态文本(Dynamic Text)。如果你做CODESYS可视化界面,又不想为了几十个状态变量做一堆文本切换,Dynamic Text控件是最省事的方案。它本质上是一个文本显示控件,绑定一个整型变量或枚举变量,然后配置变量值与显示文本的映射关系。比如设备状态变量bState=0时显示“停止”,=1时显示“运行中”,=2时显示“故障”。现场调试时,我习惯把所有报警码和状态码做成枚举,可视化里配好动态文本,操作工一眼就能看懂,不用总盯着数字猜含义。

4. 通讯实战:多协议选择的底层逻辑与实操配置

4.1 汇川电机通讯协议选型:新手最容易纠结的问题

汇川电机(包括变频器和伺服驱动器)支持的通讯协议很多,新手特别容易纠结。我按使用场景给一个直观的分层建议:

协议类型物理层实时性上手难度推荐场景
Modbus RTURS485变频器启停、低速率参数读写、点位少的场合
Modbus TCP以太网与上位机、MES系统交互
CANopenCAN中高多轴小规模控制、IO扩展、传感器接入
EtherCAT高速以太网中高多伺服轴高同步运动控制
Profinet/EtherNet/IP以太网中高与西门子等第三方PLC对接

如果只是入门,我强烈建议从Modbus RTU开始。原因很简单:RS485接线简单,报文格式公开透明,用串口助手就能调试,出了问题一拍一个准。而EtherCAT虽然性能强,但初次接触要理解主站、从站、DC同步、PDO映射这些概念,学习曲线陡很多。

4.2 RS485控制MD200T变频器:一个最经典的案例

MD200T是汇川很常见的通用变频器,支持Modbus RTU。我举一个用AM400/AM600的RS485口直接控制MD200T的经典例子,协议就是Modbus RTU,从站地址1,波特率9600,8数据位1停止位无校验。

变频器侧需要设置的参数大致如下(具体以对应手册为准):

参数号含义设定值
P00.00运行命令通道2:通讯控制
P00.01频率设定通道2:通讯设定
P97.00通讯地址1
P97.01通讯波特率3:9600
P97.02数据格式0:无校验8N1

写频率时,Modbus地址一般对应频率设定寄存器,单位是0.01Hz,所以设定50.00Hz要写入5000。启动变频器是往控制字寄存器写正转命令,停止是清零或写停止码。

在CODESYS里调用Modbus库,用ModbusMaster功能块,组帧如下:

// 正转启动:功能码06,寄存器地址16#2000,数据16#0001 // 频率50Hz:功能码06,寄存器地址16#2001,数据16#1388

如果不想依赖库,也可以自己用串口功能块组Modbus RTU帧,关键是CRC16算法。下面是我常用的一段CRC16计算ST代码,可以直接抄:

FUNCTION F_CRC16 : WORD VAR_INPUT pData : POINTER TO BYTE; uiLen : UINT; END_VAR VAR i : UINT; j : INT; wCrc : WORD; END_VAR wCrc := 16#FFFF; FOR i := 0 TO uiLen - 1 DO wCrc := wCrc XOR pData[i]; FOR j := 0 TO 7 DO IF (wCrc AND 16#0001) <> 0 THEN wCrc := (wCrc SHR 1) XOR 16#A001; ELSE wCrc := wCrc SHR 1; END_IF END_FOR END_FOR F_CRC16 := wCrc;

网上很多人搜“200smart如何通过RS485控制汇川MD200T变频器实例”,西门子S7-200 Smart走的也是Modbus RTU,逻辑一样:指令库MBUS_CTRL + MBUS_MSG,写控制字和频率寄存器。这个方案在汇川AM400上同样成立,只是把库换成CODESYS的Modbus库。我实际测试下来,用AM600通过RS485控制MD200T的启动频率切换,响应稳定在几十毫秒级,完全够用。

4.3 CAN自由口编程与伺服终端电阻

“汇川CAN自由口编程”是论坛里一个高频词。所谓自由口,就是不使用标准CANopen协议栈,直接用CAN控制器发送和接收自定义报文。这样做的好处是报文格式自己定,跟自定义设备对接非常灵活;坏处是失去了CANopen的标准化对象字典和PDO机制,每台设备都要自己定义ID和数据含义,后期维护全靠注释。

我建议大家评估一下:如果对接的是汇川自家伺服SV660、IS620N,或者第三方标准CANopen设备,优先用CANopen协议,CODESYS里挂一个CANopen Master,直接配置PDO映射,比自由口省事太多。只有对接某些非标设备、对方只提供原始CAN帧协议时,才考虑自由口。真要用自由口,CODESYS里通常需要通过CAN卡驱动或厂家的CAN接口库来实现,先确认目标控制器是否有对应的CAN底层访问接口。

再说终端电阻。无论用CANopen还是CAN自由口,CAN总线两端必须各接一个120欧姆终端电阻。汇川的伺服驱动器和不少控制器都有内置终端电阻,有的通过拨码开关(比如SW1、SW2)开启,有的通过软件参数设置。很多现场通讯偶发报错、跑一段时间就掉线,排查半天最后发现是终端电阻没拨。两个端节点各拨一组,中间节点全部不拨,这是铁律。总线距离长的时候,还要注意使用双绞屏蔽线、屏蔽层单端接地,这些细节往往比协议本身更影响稳定性。

5. 库文件、封装与团队协作:把项目从“能跑”变成“好维护”

5.1 生成库文件的正确姿势

CODESYS最强大的能力之一就是“库化”。如果你写了一组很好用的功能块,比如“设备状态管理”、“配方解析”、“轴回零序列”,完全可以把它们打包成一个库文件,供多个项目复用。操作路径是:在工程里选中要发布的POU,右键“保存为库”,设置库名称、版本号、公司信息,确定对外可见的接口POU,把内部变量和辅助函数隐藏起来。

生成库时有一个关键点:选择与目标控制器匹配的兼容版本。如果你库代码里用了CODESYS V3.5 SP19才出的新语法,而另一个项目还在用SP17环境,那个项目加载库时会直接报错。所以我一般让库版本“向下兼容”,尽量只用基础IEC语法和PLCopen库,避免为了少写两行代码引入高版本特性。

5.2 封装与版本管理的经验

我对项目中的代码封装要求很明确:功能块要“高内聚、低耦合”。比如一个负责EtherCAT伺服轴启停的功能块,输入是轴引用、使能信号,输出是轴状态、报警代号,内部实现里再复杂的逻辑都不影响外部调用。这样即使从AM400换到AC801,甚至换到另一个品牌的CODESYS控制器,只要PLCopen库接口不变,上层逻辑几乎不用改。

版本管理是我强烈建议团队补上的环节。CODESYS的.project工程文件可以用Git或者SVN管理,关键不只是提交代码,还要把库文件、设备包版本、PLC固件版本一起记录在设备台账里。现场出现“程序一样但行为不同”的问题,十有八九是控制器固件版本或CODESYS库版本不一致。我的习惯是在每个项目根目录放一个README.txt,写明:

  • 开发环境版本(CODESYS V3.5 SP19)
  • 固件版本
  • 依赖的库文件及版本
  • 下载选项(是否包含源代码)
  • PLC IP及站点名称

有了这些信息,半年后回头维护项目,或者换人接手,都不会一脸茫然。

6. 实战踩坑排查链:从现象到根因的完整复盘

6.1 案例一:程序下载后设备不动作的排查

现象:用CODESYS给一台AM600下载完程序后,PLC停止运行,即使切到RUN也不动作。排查过程:

  1. 先看PLC状态指示灯,是否运行时马上跳STOP。如果跳STOP,打开CODESYS里的“设备 → 诊断 → 日志”查看异常,常见原因是程序里触发了看门狗故障,或者访问了无效硬件地址。
  2. 切到在线监控模式,观察主任务是否在运行。CODESYS默认任务如果周期设置过短,而程序量又大,可能会导致任务超时,控制器自动进入STOP。把任务周期从1ms改到5ms或10ms,问题往往会消失。
  3. 检查是不是下载时选了“初始化复位”,把保持型变量全部清了。比如轴位置、补偿值、变频器通讯参数,这些数据清零后设备自然不动作。重启设备、重新触发一次初始化流程,问题解决。

这个案例给我的教训是:下载前先看“启动方式”弹窗,选错了别着急怪程序。现场处理时尽量用“热启动”,不要一上来就“Origin Reset”。

6.2 案例二:UDP通讯偶发断线的根因

现象:AC801通过UDP与上位机视觉系统通讯,运行十几个小时后偶发收不到数据,必须重启控制器或上位机程序才恢复。排查链路:

  1. 先用Wireshark在上位机侧抓包,确认UDP报文是否有从PLC发出。抓到表明PLC发出来了,问题出在上位机接收侧;抓不到说明PLC侧没发。
  2. 查看CODESYS里的Socket任务周期。我在项目里最初把UDP收发放在主任务里,主任务周期10ms,而视觉系统的发送周期是5ms,导致UDP缓冲区不断有数据塞进来,PLC来不及读,缓冲区溢出后Socket句柄异常,通讯卡死。
  3. 解决:把UDP收发独立成一个循环任务,周期2~4ms,并每次读取时循环把缓冲区里所有待处理报文取出,直到缓冲区空,而不是只处理最新一条。另外加上心跳序号,若连续N个周期没收到心跳,主动关闭Socket并重新创建。

处理完这个案例后,连续跑了一周没有再断。关键经验:UDP通讯不可靠是常态,工业现场必须在应用层做数据校验和断线重连,不能依靠“发一次就永远通”的侥幸心理。

6.3 案例三:上载程序与源文件不一致的问题

现象:设备维护人员在现场用CODESYS上载了PLC程序,和公司电脑上的工程文件做对比,发现大量功能块内容对不上,怀疑是谁改过程序没同步。排查后确认:原开发工程师在几个月前用在线修改方式改过几个参数,但没有把修改同步到本地工程文件。PLC里跑的是“修改后”的代码,本地工程还是“修改前”的版本,所以上载回来后差异巨大。

处理方式:在CODESYS里登录在线状态时,先点击“在线 → 工程设置 → 比较”,用“在线与此工程比较”功能,逐项对比POU、变量、库版本,确认差异后决定是上载覆盖本地,还是本地覆盖现场。更重要的是建立流程:每次在线修改后,立即同步工程文件并提交版本库,避免“现场最新、电脑不是最新”的两头分叉状态。

我在实际项目里还养成了一个习惯:转产或交付前,从PLC上载一份完整工程,另存为“现场已交付版本”放在项目归档目录里。真出问题时,先拿这份归档文件做基准,而不是拿开发电脑里的“你以为的最新版”做基准。


最后再分享一个实用小技巧:CODESYS底层是连续的在线环境,改程序时不要频繁“Register下载”再“Reset”,尽量用在线修改(Online Change)把小的改动直接投入运行。但前提是你的修改没有增加新变量类型、没有删除POU、没有改变任务配置,否则在线修改会失败,只能走完整下载流程。掌握这个边界,能让你在不停机的状态下安全地迭代程序。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 19:14:03

NDIS小端口驱动开发实战:从初始化到数据收发全解析

简介&#xff1a;这是面向瑞昱&#xff08;Realtek&#xff09;8111、8168、8169、8110等常见PCI千兆以太网控制器编写的NDIS 6.0小端口驱动示例源码&#xff0c;适合需要开发Windows网络驱动却缺少完整参考实例的工程师学习。压缩包采用RAR格式&#xff0c;共69个文件&#xf…

作者头像 李华
网站建设 2026/9/9 19:13:20

STM32驱动ADS1118:SPI接口实现多路ADC与热电偶测温完整教程

简介&#xff1a;基于STM32F103与STM32F407的ADS1118完整驱动方案&#xff0c;主要面向嵌入式开发者、电子竞赛学生以及从事高精度数据采集的工程师。程序覆盖4路单端、2路双差分和片内温度传感器三种采集模式&#xff0c;实现从寄存器初始化、SPI读写时序到多通道数据转换与错…

作者头像 李华
网站建设 2026/9/9 19:12:57

AutoGPT 后端因 JWT_JWKS_URL 为明文 HTTP 拒绝启动怎么解决?

AutoGPT 后端因 JWT_JWKS_URL 为明文 HTTP 拒绝启动怎么解决&#xff1f; 【免费下载链接】AutoGPT AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters. 项目地址…

作者头像 李华
网站建设 2026/9/9 19:12:25

STM32移植FreeModbus主机+FreeRTOS实战:工业数据采集与RS485通讯方案

简介&#xff1a;基于STM32F103ZET6的FreeModbus主机与FreeRTOS移植资源&#xff0c;面向嵌入式通信与物联网开发者&#xff0c;提供一套可对照实践的完整工程。压缩包共1254个文件&#xff0c;约24.23MB&#xff0c;涵盖612个C源文件、289个头文件以及汇编文件、目标文件、静态…

作者头像 李华
网站建设 2026/9/9 19:12:08

Audacity 多轨音频编辑指南:十分钟导入录音、降噪并导出

Audacity 多轨音频编辑指南&#xff1a;十分钟导入录音、降噪并导出 【免费下载链接】audacity Audio Editor 项目地址: https://gitcode.com/GitHub_Trending/au/audacity Audacity 是一款免费开源的多轨音频编辑与录音工具&#xff0c;支持 Windows、macOS 和 Linux。…

作者头像 李华