news 2026/9/9 23:35:56

基于51单片机的酒精气体检测仪设计:AD原理图、PCB与程序实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于51单片机的酒精气体检测仪设计:AD原理图、PCB与程序实现

简介:本资源是一套面向嵌入式初学者与课程设计者的51单片机酒精气体检测仪完整开发资料,聚焦气体传感系统从硬件搭建到软件实现的全流程实践。资料包含AD转换原理图、双层PCB设计文件(.schdoc与.pcbdoc)、Keil工程源码(含3个C主程序、3个头文件及hex可执行文件),以及编译中间文件和预览资源,共29个文件,总大小743KB,结构清晰、即拿即用。已有2091人学习下载,印证其在教学实践与毕业设计中的高实用性。用户可直接基于该方案完成传感器信号采集、ADC数据处理、浓度数值显示等核心功能,快速掌握模拟前端设计、PCB布局要点、C语言驱动编写及软硬协同调试方法,特别适合作为单片机课程设计、电子创新实训或小型安防设备原型开发的参考范例。 做课程设计或毕业设计选酒精检测仪这类题目的人,大概率都经历过这样的场景:网上搜资料,下载下一堆压缩包,解压一看要么只有程序没有电路图,要么原理图和PCB对不上,要么干脆是拿别人的毕业设计改个名就发出来。标题里这套“基于51单片机酒精气体检测仪设计资料(包含AD原理图、PCB及程序)”算是把三个最核心的东西都覆盖了。我这篇就围绕这套资料的完整落地过程,把硬件方案、原理图设计、PCB布局布线、程序框架和实际标定从头到尾捋一遍,重点说清楚那些资料里不会写、但你在实验室真正动手时一定会撞上的问题。

这项目非常适合三类人来参考:一是电子相关专业要做课程设计或毕设的学生,二是想拿一个完整小项目练手嵌入式设计的初学者,三是需要快速产出样机给领导或客户演示的工程师。它的技术含量不算高,但覆盖的环节非常全——传感器模拟信号采集、模数转换、单片机控制、显示与报警、PCB设计,一条信号链走完,基本就把一个最小电子系统该有的东西都摸了一遍。

1. 方案选型:为什么是51单片机配MQ-3,以及AD采集链路怎么定

1.1 酒精检测的核心原理:气敏电阻怎么变成可读电压

酒精检测仪的核心检测元件是MQ-3型气敏传感器,这玩意儿属于半导体气敏电阻家族。简单说,它的内部有一个加热丝和一层二氧化锡(SnO2)敏感材料。洁净空气中,敏感材料的表面吸附氧分子,载流子浓度低,电阻值很高;一旦接触到酒精蒸气,酒精分子会和表面吸附氧发生反应,释放出电子,导致敏感材料电阻明显下降。

MQ-3模块出来的信号不是直接可用的数字量,它内部是一个分压电路——传感器电阻R_s和一个负载电阻R_L串联,从中间抽头输出模拟电压。酒精浓度越高,R_s越低,AOUT引脚上的电压就越高。所以整个系统的第一条主线就清楚了:酒精浓度→电阻变化→电压变化→ADC采集→单片机换算→显示与报警。

这里有个容易被忽略的点:MQ-3上电后必须经历预热过程,敏感材料需要达到工作温度才能稳定响应,至少要预热3到5分钟,想达到指标里的最佳状态需要预热24小时以上。这就是为什么你在实验室刚上电就测浓度,数据会一直飘——不是程序写错了,是传感器根本没进入稳定工作区。

1.2 51单片机为什么还要外挂ADC,而不是直接采

很多初学者会问:既然传感器输出的是模拟电压,51单片机直接接个ADC不就行了?这个问题的答案承载了这个方案的一个关键选型逻辑。标准8051内核的单片机内部没有集成模数转换器,STC89C52也不例外,所以必须外扩一个ADC芯片来完成模拟量到数字量的变换。

外扩ADC的选型有两条路线:一是经典的并行接口ADC0809,转换速度快、时序直观、教科书级存在,适合课程设计场景,能讲清楚并行总线和时序的概念;二是串行接口的ADC0832(SPI)或PCF8591(I2C),接线少、代码简单,但对初学者来说时序协议的理解门槛反而更高。

硬件方案定下来之后,整个系统的框架就清晰了:传感器感知气体浓度→调理电路把电阻变化变成0到5V的电压信号→ADC0809完成模拟量到数字量的转换→51单片机读取数据、滤波、换算浓度→LCD1602显示当前值→超过阈值时蜂鸣器报警。每个模块各司其职,分工明确,这也是这个项目很适合作为入门项目的原因。如果硬件选型时犹豫不决,建议还是跟着主流走用ADC0809,一方面是资料多、参考代码多,另一方面答辩时老师对这套方案更熟悉,提问也基本在预期范围内。

1.3 整体信号链与模块分工:别把系统想复杂

这套系统的数据流其实非常简单:传感器是信号的源头,ADC负责翻译,单片机是大脑,显示和报警是输出,按键是交互入口。把这五块拆开看,每个模块单独拿出来都是很基础的东西。做这类项目最忌讳的就是一上来想着把代码写得多花哨、电路做得多复杂,其实把这个最朴素的信号链跑通,项目就已经完成了一大半。

2. 硬件电路逐个拆解:从传感器到报警器,每个模块的设计理由

2.1 MQ-3传感器接口电路与预热坑

MQ-3模块分为两种形态:一种是裸传感器,需要自己在板子上设计加热和分压电路;另一种是已经集成好的模块,板载了比较器电路和电位器,直接输出TTL电平和模拟电压。如果自己设计PCB,强烈建议直接用成品模块,用排针焊在主板上,这样既省去加热电路的设计麻烦,又方便后期单独更换传感器。

如果用裸传感器,设计时要注意加热回路的功耗。MQ-3内部加热电阻大约在31欧姆左右,5V供电时加热电流接近150毫安,这个电流不能走信号地,要单独走电源地回到电源输入端,否则会在信号地上产生压降,直接影响ADC采样精度。加热电源建议用5V稳压后再供给,避免USB口电压波动导致传感器输出漂移。这个细节在原理图阶段不处理好,后续PCB布线和实测都会很难受。

2.2 ADC0809采样电路:时钟信号是第一个拦路虎

ADC0809是8位逐次逼近型ADC,8路模拟输入通过地址线选择,转换结果通过并行数据总线输出。它有几个关键引脚必须接对:IN0到IN7是模拟输入通道,这里用IN0;ADDA、ADDB、ADDC是通道选择地址;ALE是地址锁存使能;START是转换启动信号;EOC是转换结束信号;OE是输出使能;CLK是时钟输入。

CLK引脚是最容易出问题的地方。ADC0809的工作时钟范围是10kHz到1280kHz,典型值640kHz,转换时间约为100微秒。51单片机12MHz晶振时,一个机器周期是1微秒,ALE引脚输出频率是晶振时钟的1/6,也就是2MHz,远超ADC0809上限。直接接上去,ADC要么不工作,要么数据完全不对。

解决办法有两种:一是用一个D触发器(比如74LS74)把ALE频率二分频到1MHz,仍然略高,最好再分一级;二是用单片机的定时器产生一个500kHz左右的方波给CLK,这也是最省事的做法。第三种思路更干净——干脆换掉ADC0809,用ADC0832或PCF8591这类自带串行时钟接口的芯片,直接从源头上绕开时钟频率匹配的问题。

我在实际看同学做这个项目时,遇到最多的就是CLK信号没处理导致ADC读数恒为0xFF或随机跳变。如果你选的参考设计和这个不一样,一定要先确认核心转换电路的时钟方案再画板,不要在画完板子后发现这个引脚没接对,改板子的成本远比改程序高。

2.3 LCD1602显示、按键阈值与蜂鸣器报警

显示方案首选LCD1602,16列2行,显示“ALC:xxx ppm”加上报警状态绰绰有余。接线用标准的8位数据接口,RS、RW、EN三个控制引脚接单片机IO口,数据引脚接P0口并加上拉电阻——这一点非常容易遗漏,STC89C52的P0口是开漏输出,不加上拉电阻LCM1602的D0-D7电平根本拉不起来,屏幕要么花屏要么白屏。

蜂鸣器报警电路要用三极管驱动,不要直接把蜂鸣器接在单片机IO口和地之间。无源蜂鸣器工作电流在20到30毫安,51单片机IO口最大灌电流大约20毫安(实际datasheet上低电平灌电流可达20mA),直接驱动会非常吃力,长时间工作还可能烧引脚。建议用S8050三极管,基极串一个1k电阻接单片机IO口,发射极接地,集电极接蜂鸣器负极,蜂鸣器正极接VCC。这样IO输出高电平时三极管导通,蜂鸣器发声。

按键部分做两个:一个“设置”键,一个“加减”键,用来调整报警阈值。硬件上按键接IO口到地,内部上拉,按下为低电平。机械按键有抖动,程序里要处理消抖,这个后面讲。

2.4 电源设计:别把小系统供电想得太简单

整个系统的供电看似简单——USB的5V直接给单片机、传感器模块、LCD供电就行,但实际做下来有几个问题需要提前考虑。USB口的5V电压实际在4.4V到5.25V之间波动,如果直接用USB供电又同时驱动传感器加热和蜂鸣器,电源纹波会很感人,反映到ADC读数上就是末位数字乱跳。建议给系统加一个100uF电解电容和一个104瓷片电容给电源去耦,电解电容放在电源入口,瓷片电容尽量靠近单片机电源引脚。

如果课程设计要求用9V或12V直流电源供电,就需要加7805稳压芯片。7805输入输出差分电压大时发热比较明显,戴散热片会更稳妥。这里的要点是:7805的输出电容不要省,否则稳压反馈环路容易自激,输出端带上负载后电压会抖动,直接影响传感器和ADC的参考电平。

3. AD原理图设计与PCB布局布线实战

这个项目既然以“AD原理图PCB及程序”作为配件包,说明画图用的是Altium Designer。下面这些实操中踩过的问题,比单纯看教程有用得多。

3.1 原理图绘制:图纸设置、总线设计、封装匹配

新建工程后,第一件事是在原理图文档里设置图纸大小。默认的A4图纸通常够用,但如果画完发现器件太多摆不开,可以在“Design→Document Options”里改图纸尺寸,标准A3或A4都行。不要为省事把所有器件堆在一起,后面检查网络连接会疯掉。

AD画原理图时,很多初学者喜欢用方向不同的导线连接每一个引脚,结果就是像蜘蛛网一样乱成一团。规范做法是用“总线+网络标签”:相同信号的引脚添加相同的网络标签(比如D0到D7、ADDA、ALE、EOC这些),总线只表示一组信号的集合关系,物理连接关系靠的网络标签匹配。这也是热搜词里“AD原理图总线及总线分支设计”对应的内容。具体操作是:先给各个引脚放网络标签,再画一条总线,通过总线分支(Bus Entry)把引脚引线接入总线。总线本身不参与电气连接,实际连接的还是网络标签,理解这一点就不会整糊涂。

封装匹配是在原理图阶段就要检查的重点。MQ-3模块用排针封装,注意排针间距2.54mm;LCD1602一般用16Pin直插排针或焊盘封装;ADC0809用DIP20封装;电解电容要注意极性方向和引脚间距。推荐在放置元器件时就逐个确认封装,而不是等到画PCB时发现封装对不上再返工。

3.2 从原理图生成PCB的流程与规则设置

画完原理图,编译通过后,从“Design→Update PCB Document”一键生成PCB,但这个过程不是无脑点确定。生成前要把“Project Options”里的错误检查项打开,确保网络连接没有悬空引脚、没有重复的网络标号。元件导入PCB后,飞线会显示各网络的实际连接关系——这时候先不要急着布线,先把元件分区摆好。

布线规则建议这样设置:电源和地线线宽20到30mil,信号线10到12mil,安全间距默认6到8mil足够。如果你做的是双层板,顶层走信号线,底层做完整地平面,回流通路会非常干净。规则设置在“Design→Rules”里,把“Width”规则按网络分别设置优先级——电源网络30mil,地网络30mil,信号线12mil。不设规则直接默认12mil走电源线,发热和压降在这个小系统里虽然不明显,但总归不够专业。

3.3 布局布线的关键逻辑:传感器放板边、模拟数字分区

这个项目的布局有一个非常关键的原则:模拟部分和数字部分要分区放置。模拟部分是MQ-3模块和ADC0809的输入端,数字部分是单片机及外围数字电路。把ADC0809放在模拟区和数字区的交界位置,传感器模块边缘,远离蜂鸣器这种电流变化剧烈的器件。气流方向也很重要,MQ-3传感器尽量放在PCB边缘,保证酒精蒸气能顺畅接触到敏感材料,不要被外壳挡住气孔。

布线顺序上,先布电源和地,再布信号线。顶层走横向信号线,底层走纵向信号线,减少平行走线产生的耦合。ADC0809的模拟输入线(传感器AOUT到IN0)尽量短,避免成为天线拾取噪声。时钟信号线CLK要远离模拟输入线,这也是很多人没注意到的——CLK是方波,高频分量丰富,耦合到模拟输入线上就会导致采样值跳动。蜂鸣器的驱动线不要和信号线平行走太长距离,防止电流突变串扰进信号回路。

定位孔也是PCB设计中常被忽略的一个要素。AD里画定位孔的标准做法:在Keep-Out Layer画一个圆心,再画一个比定位孔略大的圆环,孔的金属化与否决定你要不要叠一个焊盘在上面。如果只是给外壳螺丝用的非金属化定位孔,Keep-Out层的圆就够了,制板时工厂会识别为外形的一部分。

3.4 铺铜与Gerber输出:别让工艺问题毁掉你的设计

PCB设计完成后,顶层和底层建议大面积铺铜接地(通常接GND)。铺铜的作用有两层:一是给信号提供最短的回流通路,减少环路面积;二是让板子的电磁兼容性更好。铺铜后记得在规则设置里把“Polygon Connect Style”设为Direct或Relief,默认的45度连接能兼顾电气和工艺需求。

导出Gerber文件是发给板厂生产的标准格式。在AD里通过“File→Fabrication Outputs→Gerber Files”生成,格式选RS-274X,精度2:5,还要勾选“Keep-Out Layer”。Gerber导出后,一定要用Gerber Viewer打开检查一遍每一层的内容,确认没有缺层、没有把边框层弄丢。我见过不止一次因为导出Gerber时漏选钻孔层,导致板子回来全是焊孔没有孔壁金属化的情况——这种低级错误在项目交付阶段尤其致命。

4. 单片机程序框架与数据处理逻辑

4.1 系统初始化与主循环结构

程序框架上,这个项目用顺序轮询的结构就够了,不必要上操作系统。主循环的逻辑大致是:系统初始化(定时器、LCD、ADC、IO)→主循环里读取ADC值→数据处理→刷新显示→检测按键和报警。

初始化部分有几个细节要处理好:定时器0用作ADC0809的CLK发生器,普通51定时器工作在方式2(8位自动重装)比较简单,计算好初值让定时器溢出频率在500kHz左右;LCD1602初始化要按厂家的时序表执行,先延时等待液晶内部复位,再写入功能设置指令、显示开闭指令、清屏指令,时序不对屏幕就不会亮,很多初学者卡在这一步。

4.2 ADC0809的时序控制与读取

ADC0809的启动时序用文字描述比看代码难懂,实际操作逻辑是:选中通道地址(IN0)→给ALE一个高脉冲锁存地址→给START一个至少100ns宽的高脉冲启动转换→等待EOC变为低电平表示转换完成→给OE高电平使能输出→从P0口读取转换结果。

这里有个实用的代码模式:用一个变量记录当前通道号,转换完当前通道后,如果还想采别的通道,就把通道号加1再去启动下一轮转换。课程设计一般只采IN0一个通道,但保留这个扩展逻辑会让程序看起来更规范。

读取结果时还需要注意一个时序问题:EOC信号变低后,数据还在逐次逼近寄存器里,必须等OE使能后才出现在数据总线上。所以在“等待EOC变低”之后,要加一个短延时再读数据,否则可能读到不稳定的中间态。这个延时在12MHz晶振下有十几个空操作就足够。

4.3 数据滤波与浓度换算:平均值滤波和分段查表

8位ADC的原始读数直接显示出来会非常跳,因为传感器输出本身有波动,加上环境干扰,相邻两次采样相差10到20个LSB都很正常。处理办法是采样10次或20次,去掉最大值和最小值后取平均,这样既能抑制毛刺,又能保留真实变化趋势。滤波后的值才拿去做显示和比较。

从ADC值换算到实际酒精浓度,是多数参考程序最不严谨的地方。MQ-3的浓度-电阻特性曲线在双对数坐标下近似线性,但直接用公式拟合在低浓度段误差很大。实操中建议做一个简单的分段线性查表:用酒精计或已知浓度的酒精标准液标定出几个点的ADC值-浓度对应关系,存入数组,实际测量时根据ADC值落在哪个区间做线性插值。类似“ALC: 150 ppm”这种显示,其实是一个估算值,关键在于估算方法要合理,至少趋势上是准的。

4.4 阈值判断、显示刷新与报警联动

阈值判断程序逻辑没有太多难度:定义一个全局变量alert_threshold,默认值比如200ppm,按键“设置”进入调整模式,“加减”键修改当前值,再按“设置”退出并把新阈值写入EEPROM。STC89C52内部没有EEPROM,如果STC系列可以模拟EEPROM,或者直接把这个值定义在变量里,掉电丢失。课程设计演示场景下,变量存储完全够用,没必要为这个加外部存储芯片。

LCD显示刷新要注意一个问题:主循环每次都重新清屏再打印,屏幕会闪,而且很不专业。正确做法是只在数据变化超过一个阈值(比如变化量大于1ppm)时才更新显示,或者用“写入新值前比较旧值”的方式,只有不同才重写对应位置的字符。

报警联动部分,蜂鸣器可以设计成超标后连续鸣响,也可以做成间歇性报警,两者程序差异只是延时参数不同。建议做成间歇响,比如响100ms停200ms循环,这样警示效果好,又不至于让整个实验室都烦躁。

5. 整机调试与酒精浓度标定的实操经验

5.1 上电前的检查顺序:别把板子烧了才后悔

拿到新打样的PCB,或者焊完一块新板子,先不要急着插下载器,更不要直接通传感器模块。我的习惯是:先用万用表蜂鸣档测一遍电源正负极是否短路(这是最便宜也最救命的习惯),再测关键芯片电源引脚的电压值是否在正常范围;确认无短路后,只给单片机上电,用示波器看晶振是否起振;然后再依次接入LCD、传感器模块、蜂鸣器,每加一部分就检查一次工作状态。

上电前还有一个检查容易被新手跳过:检查单片机所有VCC和GND引脚是否都接上了。STC89C52有两组VCC(40脚、31脚——31脚是EA/VPP,通常接到VCC)和两组GND(20脚)。EA引脚必须接高电平才能从内部ROM启动,这个接错或漏接,单片机完全没反应,程序下载进去也不跑,非常容易误判是程序问题。

5.2 酒精浓度标定:从定性到定量的操作路径

酒精检测仪做出来不只是为了好玩,标定是必须走的一步。最简陋但有效的标定方法:取一个密封容器,倒入少量不同浓度的酒精溶液(比如医用酒精稀释成不同百分比),把传感器放进去,记录稳定后的ADC值。这个过程要等一段时间让气体扩散均匀。每个浓度点重复测几次,取平均值,这样就能建立ADC值和对应关系了。

如果你手头有专业的酒精计或已经校准过的呼气式酒精检测仪,可以把本系统的读数跟标准设备做对照,找到各浓度下的偏差系数,修正到程序里。不过对学生项目来说,做到“浓度升高时读数稳定上升、线性度可接受”这个程度,答辩已经完全够用了。

5.3 常见故障排查链路:从现象倒推故障点

调试过程中最怕的是“有问题不知道从哪查起”。根据我做这类项目的经验,列几个高频故障和对应的排查思路:

现象可能原因排查顺序
LCD1602背光亮但无字符对比度电位器没调好先调对比度,再量VCC和GND,再查RS/RW/EN接线
LCD显示乱码或花屏P0口上拉电阻缺失、数据线接反检查上拉,用万用表逐根核对数据线
ADC读数恒为0xFFCLK未接或频率超限、START信号异常用示波器看CLK有无方波,检查START时序
ADC读数随机跳变电源纹波大、CLK耦合到模拟输入加去耦电容,改布线,CLK远离模拟线
浓度显示一直为0AOUT未接、传感器未预热让传感器预热,量AOUT电压是否为0.1到0.3V
按键无反应按键接线错、IO口没使能内部上拉检查接线,用万用表确认按下时电平变化
蜂鸣器不响三极管驱动方向错、限流电阻断开检查三极管B/E/C接法,量基极电压

排查时一个高压性建议:先从电源开始查,再查时钟,最后查数据路径,因为电源和时钟是整个系统的基础,它们错了后面的一切都是空中楼阁,这个顺序能帮你省掉大量无效调试时间。

5.4 这个项目做完之后,还能往哪些方向扩展

等你把这块板子完整做出来,程序跑通了,标定也做了,这个项目的学习价值才真正开始显现。很多人做完整套就丢一边了,其实稍微往前再走几步,就能延伸出更有分量的课题:

一是数据记录功能,加一个串口模块把浓度数据实时发给上位机,用Python脚本画一张浓度变化曲线,这就把一个检测仪变成了环境监测系统的雏形;二是无线化,加一块ESP8266或蓝牙模块,把数据推到手机小程序或云平台,这就直接搭上了物联网的边;三是改进传感器,换成电化学酒精传感器体积更小、精度更高、无需加热,整体功耗能降一个量级,但标定难度也随之上升。

我个人的体会是,这类“小系统集成”项目最值得花时间的反而不是程序本身,而是硬件设计到调试这整个闭环。你从原理图上的一个节点开始,到PCB上的铜皮走线,再到示波器上的一串方波,最后到LCD上的一个数字,每一个环节都在同一个系统里互相印证。这种整体感,是刷多少道题、看多少篇教程都换不来的。

本文还有配套的精品资源,点击获取

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

低功耗TCXO/VCTCXO设计实战:从原理到调试的完整指南

开头 微型低功耗TCXO/VCTCXO,这四个词放在一起,通常意味着PCB上指甲盖四分之一大小的黑色封装、1mA级工作电流,却能保证无线设备在-40℃到85℃范围内把频率始终稳定在1ppm以内。做IoT、GNSS、可穿戴或者NB-IoT方案的工程师,几乎都…

作者头像 李华
网站建设 2026/9/9 23:35:00

YOLOv8与ReID结合的多摄像头人脸追踪系统实践

简介:本资源是一套基于YOLOv8目标检测与ReID行人重识别算法融合实现的多摄像头协同人脸追踪系统,面向计算机科学、人工智能、信息安全等专业的在校学生、教师及工程技术人员,适用于课程设计、毕业设计、项目立项演示及算法二次开发实践。压缩…

作者头像 李华
网站建设 2026/9/9 23:35:38

JavaScript面试八股文:高频考点与手写题全攻略

九、十月份是秋招和跳槽的黄金期,圈子里叫“铜九铁十”。这段时间我身边不少同学都在准备前端面试,问来问去,绕不开的永远是JavaScript。面试官不管考框架多深,最后都会落到语言本身:闭包、this、事件循环、手写题、运…

作者头像 李华
网站建设 2026/9/9 23:35:54

字幕处理实战:从乱码排查到编码转换与时间轴调整

做中文字幕(中字)的小伙伴,应该都有过这种经历:字幕文件在电脑上用记事本打开一切正常,换到播放器里,中文全部变成乱码;或者字幕顺序没问题,但整段时间轴比画面慢了两秒;…

作者头像 李华
网站建设 2026/9/6 4:57:00

Easy IGBT定制化功率模块:从选型到应用的完整指南

1. 从选型困局到定制化破局:Easy IGBT 系列到底解决了什么问题做电力电子这一行,尤其是搞大功率变频、UPS、光伏逆变器或者储能PCS的,多半都经历过这种焦灼:项目方案定好了,拓扑结构画完了,电容、电感、驱动…

作者头像 李华
网站建设 2026/9/6 4:56:58

医院挂号系统PHP源码实战:从环境配置到二次开发避坑指南

简介:本资源是一套轻量级医院挂号系统PHP开源实现,面向Web开发初学者与医疗信息化实践者,聚焦线上预约挂号核心业务场景,助力理解医疗类Web应用的完整开发流程。压缩包共58个文件,含27个PHP后端逻辑文件(如…

作者头像 李华