简介:这是一套围绕51单片机与大功率白光LED的可见光通信(VLC)设计与实践资源,主要面向嵌入式系统、通信工程方向的初学者和课程设计开发者,帮助理解光通信中的发送编码、驱动控制、光电接收与解调流程。压缩包共158个文件,22.25MB,涵盖C/H源码、Keil工程文件(uvproj/uvopt)、原理图(schdoc/pcbdoc)、PCB文件、hex烧录文件、PDF说明及调试日志等,从发送端PWM调制到接收端信号放大与解码均有对应设计。目前已有370人学习下载。资料中51单片机作为核心控制单元,原理图清晰展示了LED驱动电路与光敏传感器前置放大电路,结合源码可掌握UART组网、调制解调等关键实现,适合直接编译烧录后搭建可见光通信实验平台,也可作为毕业设计或电子竞赛的参考资料。 手头正好在折腾一个挺有意思的项目:基于大功率白光 LED 的可见光通信,主控用的是 51 单片机,核心是接收和发送两套原理图。简单说,就是让 LED 不仅发光照明,还能把数据“调制”进光里传出去,对面用一个光敏器件把信号解调出来。这个小系统做完之后,可以实现几米内的音频或低速数据传输,用来做入门级光通信实验、课程设计、甚至一些特殊的无线数据传输场景都挺合适。
这篇文章我打算把整套发送和接收原理图的设计思路、关键器件选型、实际调试中踩过的坑全部摊开来讲。适合手里有 51 单片机基础、想接触光通信但不想一上来就搞 FPGA 或高速运放的朋友。整个过程下来你会发现,光通信的难点不在“光”,而在“电路”和“时序”。
1. 先从整体架构说起:光通信到底在传什么
1.1 可见光通信的基本原理
可见光通信(VLC)的本质,就是用一个高速开关的 LED 作为发射天线,把电信号转换成光信号;接收端用光电二极管或光敏三极管把光信号再变回电信号。整个过程很像红外遥控,但区别在于:白光 LED 的响应速度更快,而且可以同时兼顾照明,所以有“照明即通信”的说法。
在这个项目里,发送端的数据源是一块 51 单片机——它通过串口或 GPIO 输出数字信号,这个信号经过驱动电路控制大功率白光 LED 的亮灭。接收端再用光敏二极管加放大整形电路,把光脉冲还原成数字电平,送进另一块 51 单片机(或者同一块板子的另一个串口)解析。就这么一套链路,原理上不复杂,但工程细节不少。
1.2 为什么选 51 单片机当主控
有人可能会问:都什么年代了,怎么还用 51 单片机?说实话,做这类实验项目,51 有几个不可替代的优势。首先是 I/O 口足够用,发送端只需要一个输出脚控制 LED,接收端只需要一个输入脚读信号,资源完全够。其次是外部中断和定时器非常成熟,可以用定时器产生精确的波特率,用外部中断捕捉接收信号的边沿,这在编写收发时序时特别方便。
另一个重要原因是学习门槛低。51 单片机的寄存器少、时序简单,用 Keil 写几行代码就能实现你要的调制解调逻辑。相比之下,如果用 STM32,虽然性能强很多,但配置定时器、DMA、中断优先级这些就得花不少时间,反而不利于聚焦“光通信”本身的核心原理。
1.3 系统框图与信号流向
整个系统的信号流向是这样的:发送端单片机把要传输的数据(比如一串字符)转换成方波信号,通过驱动电路放大电流后驱动 LED 发光;光信号经过空气传播,接收端的 PIN 光电二极管把光信号转成微弱电流,再经过跨阻放大器和电压比较器整形成 0~5V 的数字方波;最后,这个方波送到接收端单片机的外部中断引脚,用程序解析出原始数据。
这里有一个关键点要提前说清楚:发送端和接收端必须共地。虽然光信号是无线传输的,但接收端的信号整形电路和单片机之间需要参考同一个电位,否则波形会漂移,严重时根本解调不出来。最简单的做法是用一根导线把两块板子的 GND 连在一起,或者直接做在一块 PCB 上。
2. 发送端原理图拆解:驱动大功率白光 LED 的核心电路
2.1 大功率 LED 的驱动方式:恒流 vs 限流
大功率白光 LED 和普通 5mm 指示 LED 完全不是一回事。普通 LED 工作电流 10~20mA,而 1W、3W 甚至更高功率的白光 LED,正常工作电流在 350mA 到 700mA 甚至更高。如果直接用一个限流电阻接 5V,或者通过三极管做开关,电流稍大就会导致 LED 光衰严重,甚至瞬间烧毁。
我实际测过一颗 1W 白光 LED 在 350mA 下的正向压降大约是 3.2V,如果直接接 5V 电源,不加限流的话电流会飙到几安培,LED 立刻烧掉。所以在发送端驱动电路里,即使不做真正的恒流源,也必须有限流电阻,而且电阻的功率不能选小了,否则电阻本身会发热严重。
项目里我用的方案是:三极管开关电路加限流电阻,用 PWM 方式控制 LED 的亮灭。虽然这不是严格意义上的恒流驱动,但对于几十 kHz 的通信速率来说完全够用,而且电路简单、容易调试。如果要做真正的高效恒流驱动,可以加一个 AMC7135 或 PT4115 这类 LED 恒流驱动芯片,但那些通常是为照明调光设计的,通信场景下要额外注意频率响应。
2.2 发送端电路结构:从单片机信号到 LED 光输出
我的发送端原理图分为三级:信号输入级、开关驱动级、LED 负载级。
信号输入级很简单,就是 51 单片机的一个 I/O 口(比如 P1.0)输出方波。51 的 I/O 口驱动能力很弱,高电平输出电流只有几百微安,必须加驱动。我选的是 S8050 NPN 三极管做一级共射放大,后来又试过 S8550 PNP 管的方案,最终定下来用 S8050 更顺手,因为逻辑是“高电平导通、低电平截止”,和单片机输出的正逻辑完全一致。
开关驱动级的计算是重点。S8050 的直流放大倍数 hFE 在 100 到 300 之间,驱动 350mA 的 LED 电流,基极电流至少要 3.5mA 以上,我留了 5 倍裕量取 15mA。单片机高电平 5V,减去三极管 VBE 约 0.7V,基极限流电阻就是 (5 - 0.7) / 0.015 = 286Ω,取标称值 270Ω。实测这个配置下三极管完全饱和,VCE 压降约 0.2V,LED 电流稳定在设定值附近。
LED 负载级用的是 1W 白光 LED,限流电阻取值要按实际电源电压计算。5V 电源减去 LED 正向压降 3.2V,再减去三极管饱和压降 0.2V,剩下 1.6V 落在限流电阻上。如果目标电流 350mA,电阻值就是 1.6 / 0.35 = 4.57Ω,取标称 4.7Ω,电阻功率需要 1.6 × 0.35 = 0.56W,我选了 1W 的规格,留足余量。
2.3 调制频率与数据速率的关系
发送端的调制频率决定了整个系统的通信速率。51 单片机用 12MHz 晶振时,一条指令周期是 1μs,如果直接用 I/O 口翻转输出方波,最高能到几百 kHz,但实际通信时要考虑接收端的响应速度和程序处理开销。
我实测下来,用 38kHz 的载波频率做 OOK(通断键控)调制,数据速率可以做到 4800bps 甚至 9600bps。这个参数不是随便定的,它同时考虑了 LED 的开关响应(大功率 LED 的上升下降时间通常几十纳秒到几百纳秒,完全能跟上)、光电二极管的响应速度(PIN 管通常几十纳秒,也没问题),以及 51 单片机软件解调的极限。
注意:如果直接把串口的 TXD 信号接到 LED 驱动电路上,不做载波调制,虽然能通信,但很容易受环境光干扰。没有载波的话,接收端无法区分“环境光变化”和“信号变化”。所以最好先调制到 38kHz 或更高的载波上,接收端再用带通滤波或软件相关检测来解调。
3. 接收端原理图拆解:光信号到数字电平的还原
3.1 光电探测器选型:光敏二极管 vs 光敏三极管
接收端的核心是光电探测器。市面常见的有光敏电阻、光敏二极管、光敏三极管,做通信的话,我个人推荐 PIN 光电二极管,比如 BPW34。光敏电阻响应太慢(毫秒级),做低频光控还行,做通信完全不行;光敏三极管虽然灵敏度高,但结电容大,响应速度也比 PIN 管慢一个数量级,在几十 kHz 的应用里勉强能用,再高就吃力了。
BPW34 这类 PIN 管的响应时间在 100ns 级别,光谱响应峰值在 900nm 附近,对白光 LED 的蓝光加荧光粉光谱也有不错的响应。它能输出的光电流很小,典型值在几十微安到几百微安之间,必须经过放大才能变成可处理的电压信号。
3.2 接收端电路结构:跨阻放大与电压比较器
接收端的电路分为三级:光电转换级、放大级、整形级。
光电转换级就是 BPW34 反向接入电路,光照时产生光电流。为了让光电流能转换成电压,我在二极管两端并联了一个大电阻,比如 100kΩ 到 1MΩ。光电流流过这个电阻,产生电压信号。这个电阻的取值很关键:太小信号幅度不够,太大又会限制带宽。我用的 200kΩ,在室内正常照明条件下,输出摆幅大约 200mV 到 1V,够后续放大用。
放大级可以用运放做同相放大,也可以用三极管做单管放大。我两种都试过。运放方案线性度好、调试方便,推荐用 LM358 或 LM393。但要注意 LM358 的增益带宽积只有 1MHz,放大 38kHz 信号没问题,再高就得换 NE5532 或 LMV358。三极管方案电路简单,但静态工作点容易受温度和环境光影响,需要仔细调偏置电阻,适合追求极简电路的情况。
整形级我用的是 LM393 电压比较器,正输入端接放大后的信号,负输入端接一个可调电位器设置阈值电压。当光信号强度超过阈值时,比较器输出跳变,直接把信号整形成 0~5V 的标准数字方波,送给单片机的外部中断引脚。这个阈值调整是接收端调试中最关键的环节,阈值太低会收到噪声,太高又会漏掉信号,我用一个 10kΩ 多圈电位器实现精细调节。
3.3 接收端的 PCB 布局注意事项
接收端的 PCB 布局对性能影响很大,这个真的踩过坑。BPW34 光电二极管的感光面要开窗,不能遮挡;放大电路的地线要单点接地,避免数字地噪声串进来;LM393 的输出上拉电阻需要接在 5V 和输出引脚之间,否则输出端不会达到高电平。
另外,整个接收电路最好加一个金属屏蔽罩,或者至少把光电二极管以外的部分用覆铜挖空处理,减少空间电磁干扰。我刚开始做的时候,放大后的波形上毛刺特别多,用示波器一量,发现是 LM393 输出的数字信号通过地线耦合到了模拟前端。后来把模拟地和数字地分开走线,在电源入口处用一个 0Ω 电阻单点连接,毛刺立刻小了很多。
4. 通信协议与软件配合:单片机怎么把数据“说”出去
4.1 直接传串口数据可以吗
硬件链路搭好之后,最直接的想法就是把 51 单片机的串口 TXD 直接接到 LED 驱动上,接收端把光信号整形后送进 RXD。这个方案在低速、短距离下可以工作,但有几个隐患。首先是串口空闲电平的问题——UART 空闲时 TXD 是高电平,这意味着 LED 会在不传数据时一直亮着,既费电又发热;其次,如果数据中出现连续多个 0x00,LED 会以极高频率翻转,这对驱动电路的响应要求很高。
实际测试中,直接用 9600 波特率传字符串,刚开始几帧是好的,但连续跑几十秒后会出现误码。原因主要是 LED 在大电流下发热,光输出功率下降,接收端的信号幅度跟着降低,最后掉到比较器阈值以下。解决办法除了加强散热,就是改用 PWM 载波调制,让 LED 的平均电流降下来,同时用信号处理的方式区分“亮”和“暗”。
4.2 用曼彻斯特编码提高可靠性
为了兼顾可靠性和实现难度,我参考了类似 RC5 遥控协议的做法,在物理层之上加了一层曼彻斯特编码。曼彻斯特编码的核心思想是:每个数据位用两次电平跳变表示,比如“0”是低到高,“1”是高到低。这样做有两个好处:一是接收端可以通过检测跳变来恢复时钟,不需要发送端和接收端严格同步波特率;二是信号中不会出现长串的连续高电平或低电平,LED 的平均功耗稳定,也便于接收端做自动增益控制。
具体实现上,我发送端用定时器 0 产生一个 9600Hz 的位时钟,每个位周期 104μs,把原始数据按曼彻斯特规则编码后,通过 P1.0 输出。接收端用外部中断 INT0 检测信号边沿,在中断服务程序里记录边沿间隔,再按曼彻斯特规则解码。这块逻辑说起来简单,但实际调试时要注意中断服务程序不能太长,否则会漏掉下一个跳变。
4.3 完整的数据帧格式设计
为了防止接收端解析到错误的“帧”,我在数据区前面加了一组固定的帧头和长度字段。帧头用 0xAA 0x55,这个组合在曼彻斯特编码下会产生最高频率的翻转,便于接收端做同步。长度字段放在帧头后面,占 1 个字节,紧跟着是数据区和 1 字节的校验和。
校验和就是简单的累加取反,在演示场景下够用了。如果以后要扩展到更复杂的系统,可以换成 CRC8,51 单片机软算 CRC8 也不过几条指令的事情。帧格式定义清楚之后,发送端和接收端的代码各自维护一套协议解析结构体,联调起来就方便多了。
5. 调试实录:那些原理图上看不到的问题
5.1 环境光干扰:白炽灯、荧光灯和阳光
光通信最大的天敌是环境光。白炽灯有 100Hz 的频闪,荧光灯有高频分量,太阳光则是稳定的强直流背景。我刚开始在办公室日光灯下测试,接收端的输出波形上叠加了明显的 100Hz 纹波,比较器阈值稍微调低一点,就会被这个纹波触发,产生大量误码。
解决办法有两个方向:一是在光电二极管前面加一个滤光片,只让 450nm 左右的光通过,因为白光大功率 LED 的蓝光成分在这个波段有很强的辐射;二是在电路上做高通滤波,电容耦合只让交流信号通过,把直流背景隔掉。我在放大级和整形级之间加了一个 100nF 的耦合电容,效果立竿见影,日光灯干扰基本消除。
当然也可以从软件上做文章——连续采样多次,取多数表决。但对 51 单片机来说,软件滤波会占用大量 CPU 时间,如果数据速率不高(比如 1200bps),倒是完全来得及。
5.2 距离与对准:为什么通信距离只有几米
大功率白光 LED 虽然很亮,但接收端的有效孔径很小,BPW34 的感光面积只有几平方毫米。光在空间中是按平方反比衰减的,距离从 1 米拉到 2 米,接收到的光强就只有原来的四分之一。我实测在室内环境,不加透镜的情况下,可靠通信距离大约在 1.5 米到 2 米之间,超过 3 米就比较吃力了。
要提高距离,最有效的办法是加光学系统。发送端 LED 前面加一个聚光透镜,接收端光电二极管前面加一个凸透镜汇聚光线,能把距离拉到 5 米以上。这个思路在红外遥控器里非常成熟,白光通信同样适用。另一个办法是提高发送端的调制深度,让 LED 工作在“完全导通”和“完全截止”之间,而不是只做小幅调光,这样接收端的信号摆幅才能最大。
注意:大功率 LED 长时间满电流工作,结温会迅速升高。结温升高不仅导致光衰,还会改变 LED 的光谱特性和开关速度。我测试时给 LED 加了一块小型铝散热片,连续跑半小时后外壳温度仍然接近 50℃,建议项目演示时加散热风扇或降低占空比。
5.3 示波器波形观察与排查思路
调试这套系统,示波器是必备工具。我建议至少观察三个点:发送端单片机的输出波形、接收端放大级的输出波形、比较器整形后的最终数字波形。只要这三段波形都是干净、幅度合理、频率正确的,那问题大概率出在软件协议上。
有一次我遇到一个问题:数据发送端波形完全正常,接收端放大后的波形也有信号,但比较器输出就是没有方波。排查了半天,发现是 LM393 的开漏输出——它本身没有高电平输出能力,必须接上拉电阻才能输出高电平。我在原理图上漏画了这个上拉电阻,焊板子的时候也没注意,结果比较器输出端只有低电平和悬空两种状态,后级单片机自然读不到正确信号。
5.4 常见问题速查表
| 故障现象 | 可能原因 | 排查方法 |
|---|---|---|
| LED 不亮或亮度很低 | 三极管没有饱和导通 | 检查基极限流电阻、测量 VBE |
| LED 亮但接收端无输出 | 光电二极管方向接反 | 确认 BPW34 阴极接电源,阳极接放大电路输入 |
| 接收波形毛刺很多 | 模拟地和数字地共地耦合 | 分开布线,单点连接电源地 |
| 距离一远就丢包 | 接收光强不足 | 加透镜、用更高灵敏度的探测器、加大发送电流 |
| 环境光变化时波形漂移 | 直流耦合导致静态点漂移 | 信号链路加耦合电容高通滤波 |
| 比较器输出无高电平 | LM393 是开漏输出,缺上拉电阻 | 加 10kΩ 上拉电阻到 VCC |
5.5 一个值得记录的教训:供电稳定性的重要性
最后说一下供电。整个系统中,发送端 LED 的瞬态电流变化很大,如果电源内阻大或者线缆太长,LED 亮灭瞬间会在电源线上产生明显的电压跌落。这个跌落不仅影响 LED 亮度,还会通过电源线耦合到接收端的运放供电上,造成信号失真。
我的做法是发送端和接收端各用一路独立的 5V 稳压电源,LED 驱动级的电源线上加一个 470μF 电解电容和 100nF 陶瓷电容并联滤波。如果只能用同一个电源,至少要把 LED 驱动的供电走线和模拟放大的供电走线分开,或者加一个 LC 滤波网络隔离。
6. 个人体会与后续扩展方向
这套基于 51 单片机和大功率白光 LED 的可见光通信系统,真正让我觉得有收获的地方,不是单一的技术点,而是把“模电”“数电”“单片机”“光学”几个领域串在了一起。设计原理图只是第一步,调试过程中的信号完整性分析、器件选型权衡、甚至散热处理,都是非常真实的工程经验。
如果感兴趣,我个人很建议在现有基础上做两个方向的扩展。一个是把数据速率提上去,把 51 换成 STM32,用定时器做 PWM 载波,接收端用高速比较器加数字锁相环解码,这样能轻松做到 115200bps 以上的透明传输。另一个是加入双向通信,两个节点都用 LED 加光电二极管的方式,做成一个光通信的收发一体机,那就更有意思了。
至于抗干扰方面,还可以试试把数据编码从曼彻斯特改成 4B5B 或 8B10B,这类编码方式自带 DC 平衡和游程长度限制,在光通信链路里效果很好。只是 51 单片机的性能有限,软解调可能吃力,升级到 STM32 后就会顺手很多。
做这类实验,最大的感受就是“纸上得来终觉浅”。原理图画得再漂亮,不上电实测,永远不知道阈值该调多少、散热片该加多大、环境光干扰有多严重。希望这篇记录能帮你少走几步弯路,尤其是发送端驱动电阻计算和接收端 LM393 上拉这两个地方,值得多花点时间琢磨。
本文还有配套的精品资源,点击获取