简介:本资源是一套基于STM32平台的可见光通信(VLC)完整嵌入式开发实践方案,面向嵌入式开发者、物联网方向学生及光电通信初学者,解决可见光调制解码、LED驱动控制与光信号收发系统集成等核心问题。压缩包含817个文件,总计110.77MB,涵盖156个C源文件(含stm32f7xx_hal_tim.c等关键驱动)、168个头文件(h)、156个编译中间文件(o/d)、154个Keil工程配置文件(crf/uvprojx/uvoptx)以及原理图(sch)、PCB(brd)、Hex固件、调试脚本(keilkill.bat)等,支撑从硬件接口配置、PWM编码实现、OOK调制解码到协议栈搭建的全流程开发。已有278人学习下载,资源结构清晰,包含F7系列完整Keil工程、HAL库适配代码、接收端电路设计参考及可直接烧录验证的二进制输出,特别适合动手构建室内定位、低功耗IoT光通信原型的实践者快速上手与深度调试。
1. 项目整体设计与思路拆解
1.1 从“光的开关”到“信息的传输”
很多人第一次听到“可见光通信”这个名词,脑子里冒出来的第一个念头是“光还能传数据?”,第二个念头可能是“这和光纤通信有什么区别?”。其实两者本质都是靠光来携带信息,只不过光纤通信用的是不可见的红外激光在玻璃纤维里跑,而可见光通信是直接利用我们日常照明用的LED灯,通过让LED以极快的速度闪烁来传递二进制数据。这个闪烁速度远远超过人眼的感知范围,所以在我们看来灯一直是亮的,但接收端的光敏器件却能捕捉到这些明暗变化,把它们还原成0和1。
这个项目选择STM32作为主控芯片,核心原因有三点。第一,STM32的GPIO翻转速度足够快,配合定时器能做到微秒级的精确延时,这是可见光通信的基础。第二,STM32的ADC配合DMA可以高速采样接收端的模拟信号,不需要外加复杂的模拟解调电路。第三,STM32的生态太成熟了,标准库、HAL库的例程遍地都是,无论你之前用的是哪个系列、哪个开发环境,都能快速上手。
我用的是STM32F103C8T6这块经典的“蓝 pill”板子,72MHz主频,足以应付几Kbps到几十Kbps的通信速率。整套系统的架构大概是这样的:发送端由STM32控制一个LED的驱动电路,把要发送的文本或传感器数据编码成脉冲序列,通过LED的亮灭变化发出去;接收端用光电二极管把光信号转成电信号,经过运放整形之后送入STM32的ADC采样,软件里再做解码,还原出原始数据。
这个设计最吸引我的地方在于,它把课堂里学的通信原理真正落地了。你不再只是在示波器上观察正弦波,而是亲眼看着一句话从一盏LED灯传到一米外的接收器上,那种成就感是单纯跑代码给不了的。
1.2 方案选型:为什么不用蓝牙、Wi-Fi或红外
做无线数据传输,下意识的选择往往是蓝牙或Wi-Fi模块,这也是大多数人第一反应。但可见光通信有它独特的价值:它完全不需要射频天线和射频电路,也就不存在电磁干扰和被探测到的风险。在一些对射频敏感的场景,比如医院的手术室、飞机客舱、某些工业控制场所,可见光通信反而是更合适的选择。
和红外通信相比,可见光通信的优势在于光源本身就能照明,不需要专门的红外发射管,而且光的覆盖范围可以通过灯具布局灵活控制,光被挡住就断连,这个特性天然具备一定的私密性。
这里我也要说句实话,这个项目并不会取代Wi-Fi,它的意义更多在于让你理解通信系统的基本构成:信源、编码、调制、信道、解调、解码。这些概念在射频通信里都是在黑盒子里完成的,而在可见光通信里,整个链路从发送到接收都是你自己写的代码,任何一个环节出了毛病你都能直接定位,这对嵌入式开发的功底提升非常大。
1.3 通信速率的定位与预期管理
不要把目标定太高。网上有些论文里做几十Mbps的可见光通信,那是用了专用的LED驱动芯片、雪崩光电二极管、高速示波器采集卡、复杂的OFDM调制算法,这些设备加起来可能比一辆二手奥拓还贵。我们要做的是一个“能跑起来、能看懂、能扩展”的演示级系统,目标定在2Kbps到10Kbps就够了。
换算一下,10Kbps意味着每比特占100微秒,这个时间尺度对STM32的GPIO翻转和ADC采样来说都绰绰有余,对LED和光电二极管的带宽要求也不苛刻。普通LED的开关响应在纳秒级别,根本不会成为瓶颈。真正限制速率的是接收端的模拟前端带宽和软件解码的容错能力,这些我在后文会详细展开。
2. 硬件选型与电路搭建要点
2.1 发送端的LED驱动电路:三极管开关就够用
发送端的核心元器件只有一个LED和一个驱动三极管。STM32的GPIO输出能力只有几毫安,直接推LED的话亮度不够,通信距离会大打折扣。正确做法是用一个NPN三极管(我用的是S8050)做开关电路,GPIO通过一个1K限流电阻接到三极管基极,LED串一个限流电阻接在集电极和电源之间。
这样GPIO只需要输出几毫安的基极电流,就能控制集电极那边几百毫安的LED电流通断。LED我选的是白色高亮草帽灯,发光角度大、响应速度快、价格便宜,而且白色光的频谱覆盖范围宽,接收端的硅光电二极管对它的响应度很好。
限流电阻的计算公式是 R = (VCC - V_LED) / I_LED,假设VCC是5V,白色LED正向压降约3V,想让电流到100mA,电阻就是(5-3)/0.1 = 20欧姆,取一个常见的22欧姆。注意三极管饱和导通时的压降VCE(sat)大约是0.2V,所以实际电流会比理论计算略小一点,这个误差不影响使用。
2.2 接收端的雪崩式难题:光电二极管加跨阻放大
接收端的核心是光信号变成电信号。最常用的器件是硅光电二极管,工作在光伏模式时,光照强度变化会引起反向电流变化。但问题来了,这个电流非常微弱,通常只有微安级别,直接用STM32的ADC去采样根本采不到。
解决办法是加一级跨阻放大器(TIA),把微弱的电流信号转换成电压信号。OPA340、LM358这些运放都能干这个活,但LM358的带宽比较低,高速信号会变形,我实测下来推荐用OPA340,或者更便宜的MCP6002,单位增益带宽都在1MHz以上,对几Kbps的信号完全够用。
电路连接方式是:光电二极管反接在运放的反相输入端和地之间,运放的同相输入端接地,反馈电阻从输出端接到反相输入端。反馈电阻的取值决定了增益,我用的100K欧姆,实测在1米距离、100mA LED电流的条件下,接收端能输出约1V的峰峰值电压。如果距离拉远或者环境光干扰大,可以换成200K或者470K欧姆。
反馈电阻两端要并联一个小电容,通常是10pF到22pF,作用是抑制高频噪声和防止运放自激振荡。这个电容不加上去的话,输出波形会有严重的振铃,解码时很容易误判。
2.3 环境光的处理:别跟太阳硬刚
第一次实验时我把系统放在窗边,接收端波形乱七八糟,完全没法解码。后来才意识到,太阳光和室内照明灯的光强比LED信号大几个数量级,光电二极管工作在很大的直流偏置点上,信号完全被淹没了。
解决办法有两层。第一层是光学层面的,给接收端的电路加一个遮光罩,用黑色热缩管把光电二极管套起来,只在正前方留一个5毫米的小孔,这样能滤掉大部分来自侧面和上方的环境光。第二层是电路层面的,在跨阻放大器的输出端加一个高通滤波,隔掉直流分量,只保留交流信号。我用了一个1uF的电容串在运放输出和ADC输入之间,配合一个10K的下拉电阻,截止频率约16Hz,人眼的灯光频闪(100Hz)都能被有效衰减。
如果你想让系统在户外也能用,那就要考虑在光电二极管前面加一个滤光片,只允许和LED颜色匹配的光通过。比如用红色LED就配红色滤光片,这样能把阳光中其他光谱成分挡掉不少。
2.4 硬件清单与引脚分配
如果你准备照着做,我整理了一份硬件清单和引脚连接表,省得你去翻数据手册。
| 元器件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | STM32F103C8T6最小系统板 | 1 | 蓝Pill,便宜量大 |
| LED | 白色高亮草帽LED | 1 | 也可以串多个增强亮度 |
| NPN三极管 | S8050 | 1 | 也可以用2N2222 |
| 光电二极管 | 蓝色滤光硅光电二极管 | 1 | 对可见光响应好 |
| 运放 | OPA340或MCP6002 | 1 | TIA放大器 |
| 电阻 | 1K, 22Ω, 100KΩ, 10KΩ等 | 若干 | 按电路需求 |
| 电容 | 10pF, 1uF等 | 若干 | 反馈电容和高通 |
| 面包板 | 830孔 | 1块 | 原型验证够用 |
| USB转TTL | CH340 | 1 | 接收端串口输出调试 |
引脚分配我建议分成发送端和接收端两套板子来做,调试的时候互不干扰。
| 功能 | 引脚 | 说明 |
|---|---|---|
| 发送端 | PA0 | LED驱动信号输出(PWM或GPIO) |
| 接收端 | PA1 | ADC输入,采集运放输出 |
| 串口 | PA9/PA10 | 发送或接收数据打印 |
| 按键 | PB0 | 作为发送触发按键 |
3. 软件核心:编码、调制与解码的完整实现
3.1 编码方案:为什么用UART的帧格式
做通信的第一步是确定数据的帧格式。最直接的办法是用STM32的UART外设,把TXD引脚直接接到LED驱动电路上,让UART自己产生起始位、数据位、停止位。接收端再用另一个UART的RXD引脚拾取信号,理论上应该能解出来,但实测效果很差,原因在于UART对时序的容差要求比较高,而可见光信道的信号沿不够陡峭,导致采样点偏移。
所以我改用软件模拟的方式,自己定义了一个简单的帧格式:8位数据,1位起始位,1位停止位,无校验。这和UART的帧格式类似,但我在起始位和停止位之间留了更宽的保护时间,降低了解码难度。
发送端的编码流程是:把要发送的字符串转换成ASCII码,每个字符8位,按位发送。发送“1”对应LED点亮,发送“0”对应LED熄灭。为了让接收端更容易检测到帧的起始,我在每个字节前面发送一个较长的低电平作为前导码,然后才是标准的起始位、数据位、停止位。
3.2 定时器延时:用DWT代替HAL_Delay
很多新手写PWM都是用HAL_Delay死等,但HAL_Delay的定时精度只有1毫秒,而且会被中断打断,对通信时序来说是致命的。我推荐的方案是使用DWT(Data Watchpoint and Trace)模块,这是ARM Cortex-M3内核自带的一个周期计数器,精度是CPU主频的倒数,72MHz下约13.9纳秒。
DWT做延时有个好处是它不占用定时器资源,而且延时精度是纳秒级的,关键是不会被SysTick中断干扰。我在工程里封装了delay_us()和delay_ns()两个函数,发送端每发送一个bit,就用DWT延时一个固定的bit周期,整个发送过程不依赖任何外设定时器。
如果你用的是HAL库,可以在SystemInit()之后直接打开DWT,代码只有几行:
void DWT_Init(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; }void delay_us(uint32_t us) { uint32_t start = DWT->CYCCNT; uint32_t ticks = us * 72; while (DWT->CYCCNT - start < ticks); }延时函数的精度直接决定了通信速率的稳定性。比如你要实现10Kbps,每个bit周期是100微秒,延时误差不能超过±5%,也就是±5微秒,DWT的纳秒级精度完全满足要求。
3.3 数据发送:PWM与GPIO翻转的选择
有两种驱动方式可以选。第一种是用定时器的PWM输出,通过改变占空比来编码信号;第二种是直接用GPIO翻转,配DWT延时。两种我都试过,PWM方式的优点是波形干净,但缺点是修改占空比需要频繁操作定时器的比较寄存器,在高位速率下容易产生时序抖动。GPIO翻转加DWT延时则更直接,代码更简单,也更容易控制发送的bit时序。
我最后采用的是GPIO翻转方案。发送一个字节的函数大概长这样:
void send_byte(uint8_t data) { // 前导码:拉低LED,持续200us LED_OFF(); delay_us(200); // 起始位:拉高LED,持续100us LED_ON(); delay_us(BIT_PERIOD); // 数据位:LSB first for (int i = 0; i < 8; i++) { if (data & 0x01) { LED_ON(); } else { LED_OFF(); } data >>= 1; delay_us(BIT_PERIOD); } // 停止位:拉低LED,持续100us LED_OFF(); delay_us(BIT_PERIOD); }BIT_PERIOD取决于你目标的通信速率。我测试用的BIT_PERIOD是100微秒,对应10Kbps,这个速率在1米范围内能稳定解码。如果你想拉长距离,就把BIT_PERIOD加大,降到5Kbps,换来的是一些抗干扰能力。
3.4 接收端解码:ADC采样的“过采样”策略
接收端的核心在于如何准确判断每个bit是0还是1。方案有两种,一种是用比较器电路把模拟信号转成数字方波,再用STM32的输入捕获定时器去测量脉宽;另一种是直接用ADC采样模拟信号,在软件里设定阈值来判断。第一种方案电路更复杂,需要额外加一颗比较器芯片;第二种方案省电路,但对ADC的采样率和DMA配置有要求。
我采用了ADC+DMA的方案,思路是对每一个bit周期做多次采样,然后取平均或取中位数作为判断依据,这样能有效抵抗噪声尖峰干扰。比如BIT_PERIOD是100微秒,采样周期设为10微秒一采样,每个bit采样10次,去掉一个最高值和一个最低值,再把剩余8个值求平均。如果平均值大于阈值,判定为1,否则为0。
ADC的配置要点是:使用定时器触发ADC采样,这样采样时刻是和bit边界严格对齐的。我用TIM2产生10微秒的更新事件,触发ADC1的规则组采样,采样结果通过DMA搬运到内存缓冲区里。DMA一次搬运200个点,对应2000微秒(也就是2毫秒)的数据窗口,这正好够接收一个20字节的完整数据包。
这里有个容易踩的坑:ADC的采样时间要设置合理,太短会采不准,太长会拖慢采样率。我设置的是ADC_SAMPLETIME_13CYCLES_5,对应约0.46微秒的采样时间,加上转换时间总共约1微秒,比10微秒的采样周期快多了,完全来得及。
3.5 同步机制:如何找到字节边界
帧同步是软件解码里最容易翻车的地方。如果接收端不知道起始位在哪里,那采出来的数据全是错位的。我的做法是利用前导码的特性:发送前导码时LED保持熄灭,接收端采样到的电平应该是一个持续的低电平。我在接收循环里持续监视ADC的采样值,一旦检测到连续N个采样点都是低电平(阈值以下),就认为进入了前导码状态,然后开始监测起始位的上升沿。
起始位检测的代码逻辑是:在前导码之后,第一个采样值超过阈值的点就是起始位的开始,从这个点开始,往后推半个bit周期,落到bit的中心位置,再从这个中心位置开始,每隔BIT_PERIOD采样一次,连续采8个数据位,最后再检查停止位是否为低电平。如果停止位不是低电平,说明这一帧数据有误,丢弃重收。
实际调试时我发现,接收端的采样时刻和发送端的发送时刻不可能完全同步,总会有固定的相位偏移。所以我在每个bit的中心点采样,而不是在bit的起点采样,这样能把相位偏移的影响降到最低。这个思想和UART的过采样是完全一致的。
3.6 数据包的组帧与CRC校验
单个字节的收发能跑通之后,接下来就要组数据包了。我自定义的帧格式分四部分:帧头(0xAA 0x55)、长度(1字节)、数据(N字节)、CRC16校验(2字节)。帧头的作用是让接收端能够找到数据包的起始位置,长度字段标记有效数据的字节数,CRC16用来校验数据在传输过程中有没有发生位翻转。
CRC16的实现不复杂,标准的多项式是0x8005,查表法最方便。网上有现成的查表法实现,直接搬过来用就行,注意高位在前还是低位在前要和接收端保持一致。我这里给出一个精简版的CRC16查表函数:
uint16_t crc16_update(uint16_t crc, uint8_t data) { uint8_t i; crc ^= data << 8; for (i = 0; i < 8; i++) { if (crc & 0x8000) { crc = (crc << 1) ^ 0x1021; } else { crc = crc << 1; } } return crc; }数据包发送端通过串口助手或者OLED屏显示接收结果,接收端在解析完一帧数据后,通过串口打印到电脑上,方便观察。
3.7 环境光的周期性干扰:软件滤波与动态阈值
实验室里用的荧光灯和LED照明灯,它们的频闪频率通常是100Hz左右(经过整流桥后的脉动),这在接收端会引入一个低频率的周期性干扰。如果通信速率太低,比如1Kbps,一个bit周期是1毫秒,正好和100Hz的干扰周期重叠,解码时很容易误判。
解决这个问题的思路有两种。第一种是提高通信速率,让光照频闪在一个bit周期内变化量非常小,这个办法在速率高于5Kbps时就基本有效了。第二种是采用动态阈值,不要用一个固定的比较阈值,而是用一个缓慢跟踪平均值的滑动阈值。原理是当前ADC采样值减去滑动平均值,得到的是交流分量,再用这个交流分量做判决,环境光的直流成分就被自动消除了。
动态阈值的实现代码不复杂,维护一个长度为32的环形缓冲区,每采到一个新的ADC值就填入缓冲区并计算平均值,判决阈值就是平均值加上一个固定偏移量。
4. 调试过程与常见问题实录
4.1 发送端波形正常、接收端全是噪声
这是我遇到的第一个大问题。发送端的LED亮灭明显正常,用手机慢动作拍摄能看到灯在闪,但接收端ADC采到的数据完全看不出规律。
排查过程是这样的:先用万用表测量运放电源脚电压,发现只有2.8V,而运放要求最小3.3V。原来是面包板供电线接触不良,导致运放工作在欠压状态,输出摆幅被严重压缩。换掉供电跳线后波形立刻恢复正常。
这个问题的教训是:先量电源,再查信号,不要一上来就怀疑程序逻辑。电源不干净的话,整个系统都不可能稳定工作。
4.2 环境光变化导致的误码率飙升
白天和晚上调试同样的代码,晚上的误码率明显低,白天经常出现解码错误。原因是白天环境光强,光电二极管的暗电流和光电流都偏大,使得运放输出的直流偏置点接近电源轨,交流信号摆幅被压缩。
解决办法是给接收端加一个自动增益控制,最简单的做法是用电位器手动调节反馈电阻的阻值。我后来换成了数字电位器MCP4131,通过SPI接口调整反馈电阻从10K到100K,实现了软件层面的增益控制。实际效果很明显,正午阳光直射时缩小增益,光照平稳时放大增益,误码率控制在极低水平。
如果你不想加数字电位器,还有个土办法是把接收端的遮光罩做长一点,减小视场角。这个方法简单粗暴,但效果还不错。
4.3 HAL_Delay卡死之谜
有朋友参考我的代码时反馈说,发送数据的时候程序总是卡在延时函数里,感觉像死循环。我一看他的代码,发现他在HAL库工程里用了HAL_Delay,而HAL_Delay依赖SysTick中断。如果之前初始化了某个外设时不小心关闭了SysTick,或者SDK的启动代码默认的状态有差异,HAL_Delay就会一直卡在while循环里等标志位。
这就是为什么我更推荐用DWT做延时。DWT不依赖任何中断,不会出现这种莫名其妙卡死的现象。如果你还是想用HAL_Delay,千万记得确保SysTick中断是开启的,并且在中断服务函数里调用HAL_IncTick()。
4.4 接收端数据错位,第一个字节对不上
数据错位这个问题非常典型,现象是整包数据里每一个字节的bit顺序都不对,看起来像是所有bit都左移了一位或者右移了一位。
原因分析后发现,问题出在起始位检测的相位偏移上。我原先是检测到上升沿后立即开始采样第一个数据位,但实际上,上升沿之后数据线上还可能有一个短暂的拖尾,导致第一个数据位的采样点偏早。解决办法是,在检测到上升沿后延时半个bit周期,跳到bit中心再开始采样,每两个采样点之间刚好间隔一个bit周期。这个“半个bit周期”的补偿在实际调试中非常关键。
4.5 通信距离上不去的瓶颈
我的系统一开始只能稳定通信20厘米,超过30厘米就丢包。排查下来发现瓶颈不在LED的亮度,而在接收端的灵敏度。20厘米处光电二极管接收到的光功率大约是30微瓦,跨阻放大器输出的信号峰峰值只有200毫伏,ADC的量化噪声已经占了不小的比例。
我做了三处改进,通信距离立刻提升到1米以上。第一,把反馈电阻从100K加大到470K,增益提升到原来的5倍。第二,在运放输出端到ADC输入之间加了一级RC低通滤波,截止频率设为30KHz,滤掉了大部分高频噪声。第三,在光电二极管前面加了一个聚光透镜,用放大镜老花镜片就能凑合,聚焦后的光信号可以增强三到五倍。
4.6 常见问题速查表
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 接收端无信号 | 运放电源异常 | 先测电源,确认运放工作电压 |
| 波形噪声大 | 缺少反馈电容或RC滤波 | 在反馈电阻两端加10pF电容 |
| 白天误码率高 | 环境光直流偏置过大 | 加遮光罩、加透镜、增大增益 |
| 解码数据错位 | 起始位采样点太早 | 延时半个bit周期再采样 |
| 程序卡死在delay | 用了HAL_Delay且SysTick异常 | 改用DWT延时函数 |
| 通信距离短 | 接收端灵敏度不够 | 加大反馈电阻、加聚光透镜 |
| 帧头找不到 | 前导码长度不够 | 拉长前导码低电平时间 |
5. 性能优化与后续扩展方向
5.1 提高速率的策略:从OOK到PPM
基础版本用的是OOK(On-Off Keying)调制,也就是亮代表1、灭代表0,一个bit周期内只有一个状态,这个方案实现简单但频谱效率低。如果想让通信速率翻倍,可以考虑PPM(Pulse Position Modulation)调制:把1毫秒的时间窗口分成4个时隙,光脉冲出现在第一个时隙代表00、第二个时隙代表01、第三个时隙代表10、第四个时隙代表11。这种方式一个时隙窗口可以传递两个bit的4种状态,同样时间内信息量翻倍。
PPM的解码需要在接收端做时隙同步,复杂度和OOK不在一个量级,但对STM32来说仍然可以承受。我的经验是先用OOK跑通链路,再挑战PPM,这样思路更清晰。
5.2 多路复用与全双工通信
一个LED只能单向传输,如果想做双向通信,可以用两个LED+两个光电二极管,一发一收互不干扰。如果你想让一个LED同时传输多路信号,可以用不同频率的副载波调制,比如10KHz的副载波和20KHz的副载波分别携带两个声道的数据,接收端用带通滤波器分离后再解调。这个方法在室内定位系统里比较常见。
STM32F103的DSP性能有限,2048点FFT在72MHz下大约需要几毫秒,做实时解调会有些吃力。如果要做多路副载波,建议直接用STM32F4系列或H7系列,硬件FPU对FFT加速的效果非常明显。
5.3 更远距离的探索:光学天线与自适应增益
如果需要几十米的通信距离,LED要换成大功率COB光源,光电二极管要换成雪崩光电二极管(APD)加前置放大器,接收端还要加光学天线。一个简单的光学天线就是一个菲涅尔透镜,能把大范围的光聚焦到APD的感光面上。我见过有人用老式CRT电视机屏幕前面的菲涅尔透镜做光学天线,效果出奇地好。
自适应增益控制在远距离通信里很重要。光强、距离、天气都会改变接收信号的幅度,如果增益固定,要么小信号被淹没在噪声里,要么大信号把运放推向饱和。我上面提到的MCP4131数字电位器加上一个简单的自动增益控制算法,就能实现从10K到470K的增益动态调整。
5.4 把可见光通信和智能家居结合
最后聊一个我觉得很有意思的扩展方向:把可见光通信模块嵌入到智能台灯里。目前很多智能台灯用Wi-Fi或蓝牙做控制,如果把通信链路换成可见光,手机摄像头对准灯光就能传输配置数据,不需要网络环境,也不用额外配网。虽然传输数据量有限,但足够传一些控制指令、设备ID、密钥初始化的信息。
我在实际测试中就做过一个demo:把一段文字编码后通过台灯的LED发出去,手机摄像头以60fps拍摄灯光的明暗变化,再用图像亮度序列解码。手机每秒最多采60帧,对应比特率只有30bps左右,但传一段几十字节的设备配置信息完全够用。这个方向还带来了一个附加价值——光通信用作一种低成本的近场通信手段,可以用于室内设备认证和服务发现。
要说得更直白一些,可见光通信本质上是用光作为介质解决“最后一米”的通信问题,把它和现有无线方案结合,比单纯把一盏灯变成路由器更有工程实用价值。而在做的过程中,你会对通信原理、嵌入式时序控制和硬件调试产生新的理解,这比跑通一个demo本身更有意义。
本文还有配套的精品资源,点击获取