news 2026/8/31 1:57:54

STM32与LED实现可见光通信:从编码到解码的完整工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32与LED实现可见光通信:从编码到解码的完整工程实践

简介:本资源是一套基于STM32平台实现可见光通信(VLC)的完整嵌入式开发工程,面向嵌入式开发者、物联网方向学生及光通信初学者,解决可见光调制解码、LED驱动控制、光电信号处理与轻量级协议栈构建等核心实践问题。压缩包含817个文件,涵盖156个C源码(.c)、168个头文件(.h)、156个编译中间文件(.o)及大量工程配置文件(.uvprojx/.uvoptx)、硬件设计文件(.brd/.sch)、调试输出(.axf/.hex)和HAL库驱动代码,总大小110.77MB,结构完整,支持Keil MDK直接编译调试。已有278人学习下载,资源包含STM32F7系列主控的TIM-PWM精确调光实现、OOK/FSK编码逻辑、光电接收前端信号调理代码、以及配套的keilkill.bat等实用工具脚本,目录组织清晰,便于分模块理解VLC物理层与链路层协同机制。 很多人第一次听说“可见光通信”的时候,第一反应都是:光也能传数据?是不是拿个手电筒晃一晃就算传数据了?其实还真差不多是这个意思,只不过要把“晃”的频率提高、把编码规则定义好,才能让对端STM32稳定收到信息。我自己这个项目就是用STM32加一颗LED把数据发出去,再用光敏器件把光信号收回来解调,实现了一块板子到另一块板子的无线传输。整个过程不涉及Wi-Fi、不涉及蓝牙,就是纯粹的光。这篇内容我会从链路搭建、硬件选型、STM32端的编码与解码、以及实测中踩过的坑一路讲到可以复现的程度,适合正在学STM32、想做点不一样的小项目,或者对Li-Fi这类技术感兴趣的朋友参考。

1. 项目整体思路:用一盏LED把数据“照”出去

1.1 可见光通信链路是怎么搭起来的

可见光通信的链路其实和红外遥控非常相似,核心就是把二进制数据变成光的亮灭变化,然后用接收端把光的强弱变化变回电信号,最后解码出原始数据。只不过红外遥控用的是人眼看不见的红外光,这里直接用可见光LED,看得见、也更好调试。

一条完整的单向链路包括四块:

  • 发射端:STM32负责把数据编码成脉冲信号。
  • 驱动电路:用三极管或MOS管控制LED快速开关。
  • 光通道:LED发出的光经过空气传播,到达接收端。
  • 接收端:光敏二极管或光敏电阻把光信号转成电信号,再通过比较器整形,送进STM32解码。

这里最容易忽略的一点是:LED的亮灭频率远高于人眼能感知的范围之后,人眼看到的就是“常亮”,但接收端却能够准确识别出光强的变化。这和手机屏幕的PWM调光原理其实是同类思路。理解了这一点,整个项目的基本逻辑就清楚了:关键在于“快”和“稳”,快是指LED的开关速度要跟得上波特率,稳是指接收端能在环境光干扰下识别出信号光。

1.2 调制方式怎么选:OOK、PWM编码和曼彻斯特

我一开始做这个项目的时候,第一版直接用的最简单的OOK调制,也就是On-Off Keying,发“1”的时候LED亮,发“0”的时候LED灭。这种方式的优点是代码简单,GPIO拉高拉低就行,缺点也很明显:同步性差,接收端不知道每个bit从哪里开始,而且连续发多个0的时候LED一直灭,电路状态很容易受环境光漂移影响。

所以第二版改成了PWM编码,也叫脉宽编码。这种方式的思路是用脉冲宽度来表示数据,比如定义1个时间单位宽度的脉冲代表“0”,2个时间单位宽度的脉冲代表“1”。接收端只需要测量每个脉冲的宽度就能解出数据。这样做的好处是接收端可以自动同步,但坏处是数据速率受最长脉宽限制,而且对定时精度要求比较高。

最终我采用的是曼彻斯特编码,这种编码在局域网和RFID里非常常见。规则很简单:每个bit的中间一定会发生一次跳变,上升沿表示“0”,下降沿表示“1”。由于每个bit都有跳变,接收端可以提取时钟同步信号,也不存在长串0或长串1导致的直流漂移问题。

三种方式对比下来,我的建议是:

调制方式实现难度抗干扰能力同步方式适用场景
OOK最简单需额外帧头玩具Demo、学习验证
PWM脉宽中等自带脉宽同步低速稳定传输
曼彻斯特稍复杂每bit自同步实际项目推荐

1.3 为什么选STM32而不是Arduino或者纯逻辑电路

选择STM32的原因其实很实在。第一是STM32的定时器资源非常丰富,可以同时承担PWM输出、输入捕获、编码器模式等多项任务。做可见光通信,发射端需要精确的PWM信号,接收端需要精确测量脉冲宽度,这两件事用STM32的定时器硬件就能完成,不需要靠CPU死等。

第二是STM32的中断系统足够灵活。接收光信号时,外部中断配合输入捕获可以在微秒级别响应脉冲跳变,这让高速解码成为可能。如果用Arduino,虽然也能做,但它的定时器只有一个16位,通道数量也少,灵活性和精度都差一些。

第三是后续扩展空间大。整个项目调试过程中需要串口打印数据、ADC采集环境光强度、甚至挂个OLED显示波形参数,STM32的资源完全够用,不会出现刚做一半发现外设不够的局面。这个项目我用的是STM32F103C8T6,也就是大家常说的“蓝丸”核心板,价格便宜、资料多,适合起步。

1.4 频率与波特率的匹配估算

很多新手做这类项目最大的问题是:想到什么频率就用什么频率,完全不计算。结果要么LED的开关速度跟不上,要么接收端根本采不到信号。

这里我算一个具体的例子。假设我准备用9600bps的波特率传数据,每个bit的时间是:

1 / 9600 约等于 104微秒

如果用曼彻斯特编码,每个bit中间要跳变一次,那接收端面对的最高信号频率是:

9600乘以2 等于 19200Hz,也就是19.2kHz

这个频率对LED来说完全没问题,普通照明级LED的开关响应在几十kHz甚至MHz级别都能跟上。真正的问题在接收端:如果选光敏电阻做接收,普通光敏电阻的响应时间在10毫秒到几十毫秒级别,换算成带宽只有100Hz左右,根本解不出19.2kHz的信号。所以要么把波特率降到几百bps,要么把接收端换成响应速度更快的光敏二极管。

这个计算过程是可见光通信项目里最关键的“为什么”,之后再选择器件和波特率,心里就有底了。

2. 硬件电路设计:发射端与接收端到底怎么接

2.1 发射端:一颗三极管搞定LED开关

发射端电路不复杂,但有几个细节会影响可靠性。STM32的GPIO引脚输出高电平是3.3V,而LED一般需要20mA左右的驱动电流,直接接GPIO虽然也能亮,但驱动能力不够,而且开关速度上不去。所以需要加一级三极管或者MOS管放大。

我用的方案是S8050三极管,NPN型,便宜而且饱和压降低。电路接法是这样的:

  • STM32的PB0引脚通过一个1k电阻接S8050的基极。
  • S8050发射极接地。
  • 集电极接LED的负极。
  • LED正极接一个限流电阻,限流电阻再接到5V电源。

基极串联的1k电阻是为了限制基极电流,防止IO口过流。限流电阻的阻值需要计算。假设LED正向压降约3.2V(白光LED典型值),电源5V,目标电流20mA,那么:

(5V - 3.2V) / 0.02A = 90Ω

实际取100Ω,电流约18mA,足够亮,也不至于超功耗。需要注意的是:如果用STM32的3.3V供电而不是5V,限流电阻要用更小的值,否则驱动电流不够,LED亮度低,传输距离会明显缩短。

如果想让开关速度更快,可以把三极管换成AO3400这类N沟道MOS管,栅极直接接STM32引脚也能驱动,开关损耗更小,适合后面想把波特率往上推的场景。

2.2 接收端:光敏器件选型与信号整形

接收端是整个项目中最容易出问题的地方。刚开始我用的是光敏电阻加分压电路,直接接到STM32的ADC引脚,希望通过判断ADC值的大小来识别0和1。试下来发现一个严重问题:光敏电阻响应太慢,波形上升沿和下降沿都是斜坡,到了几十bps以上就完全没法识别了。

后来我换成了“光敏二极管加比较器”的方案。具体接法:

  • 光敏二极管反向接入电路,也就是阴极接5V,阳极通过一个电阻接地。
  • 光线越强,光敏二极管反向漏电流越大,电阻上的压降就越大。
  • 把这个压降信号接到LM393比较器的同相输入端。
  • 比较器的反相输入端接一个电位器,用来调节参考阈值。
  • 比较器输出端接STM32的EXTI引脚。

LM393是开漏输出,所以输出端必须接一个上拉电阻到3.3V,否则输出电平飘忽不定。这个上拉电阻我选的10kΩ,兼顾速度和功耗。

比较器的作用是把模拟信号变成干净的数字方波,光敏二极管感受到的光强超过阈值时,输出高电平;低于阈值时,输出低电平。这样STM32的引脚就不会收到一堆中间状态的模拟电压,而是直接得到0和1的序列。

如果不想自己搭运放电路,也可以直接买一些光敏传感器模块,比如用LM393比较器加光敏电阻的模块,原理一样,但响应速度依然受光敏电阻限制。追求速度的话,建议找基于光敏二极管的模块,或者按上面的电路自己焊。

2.3 硬件避坑:环境光、供电与布局

这部分是我实际调试过程中最头疼的。第一次在白天窗边测试,接收端完全乱码,原因是自然光里的红外线和可见光成分在光敏二极管上产生了很强的直流偏置,把信号淹没了。解决办法有三个:

  • 机械遮光:给接收端套一个黑色热缩管或者3D打印的遮光罩,只留一个朝向发射端的小孔,把环境光挡掉大部分。
  • 软件阈值自适应:后面会详细讲,用ADC实时采集背景光强度,动态调整判断阈值。
  • 交流耦合:在比较器前端加一个高通滤波器,把缓慢变化的直流光和低频环境光滤掉,只保留高频信号光。这是比较电子的做法,效果最好。

供电方面要注意,LED瞬间开关会在电源线上产生电流尖峰,如果STM32和LED共用同一个电源,可能会引起复位或者ADC采样抖动。我在做的时候是LED单独用5V供电,STM32通过AMS1117降压到3.3V,两者共地但不共用电源轨,实测稳定很多。还有一种做法是给LED驱动加一个大电容做储能,让开关瞬间的电流冲击从电容里走,不在电源线上产生大压降。

布局上尽量让LED驱动电路远离接收端的模拟电路,因为它们之间会产生空间耦合。信号灯和接收管之间如果靠得太近,接收端会直接收到发射端的电路辐射干扰,而不是经过光通道的信号。我一开始把两块电路板正面贴正面测试,结果怎么调都不对,拉开距离到10厘米以上就正常了。

2.4 材料清单

为了让你少走弯路,我列一个完整清单,全部可以在常用元器件店买到:

器件型号/规格数量用途
STM32开发板STM32F103C8T6核心板2块发射端和接收端各一块
LED白光高亮LED1个光信号发射
三极管S80501个LED开关驱动
光敏二极管PIN光敏二极管1个光信号接收
比较器LM3931个信号整形
电阻100Ω、1kΩ、10kΩ若干限流、上拉、分压
电位器10kΩ1个比较器阈值调节
遮光管黑色热缩管1段遮挡环境光
面包板或洞洞板若干电路搭建

3. STM32侧软件实现:编码、发射与接收

3.1 发射端代码思路:PWM与定时器配合

发射端的核心任务是把要发送的数据按照曼彻斯特编码规则变成引脚上的高低电平变化。为了不占用CPU太多时间,我用的是定时器PWM输出,配合DMA或者中断来更新占空比。

先说思路。假设我配置定时器3的PWM输出频率为波特率的两倍,也就是19.2kHz,对于一个9600bps的曼彻斯特编码信号,每个数据bit在时间轴上占据两个PWM周期。比如发送“0”,电平在一个bit时间内从高变低,也就是先输出一个周期的PWM高电平,再输出一个周期的PWM低电平;发送“1”则反过来,先低后高。

利用HAL库配置PWM输出的代码大致是这样:

// 定时器3 PWM输出初始化,频率19.2kHz // 这里使用STM32CubeMX生成基础配置 TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 50; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

然后写一个发送函数,根据当前要发送的0/1序列,动态修改比较寄存器的值。如果在中断里修改CCR值,需要小心处理时序,防止在PWM计数过程中修改造成毛刺。一个比较实用的做法是使用DMA发送整个波形表,把一帧数据的电平序列预先算好,然后通过DMA不断向CCR写入新值,CPU只负责填充缓冲区和启动传输。

我实际使用的是定时器更新中断,在中断回调里判断当前发送到第几个bit,然后根据曼彻斯特编码规则置高或者置低对应的定时器通道。这样代码直白,也方便后面调整编码格式。

3.2 接收端代码思路:外部中断加输入捕获测脉宽

接收端的第一步是用外部中断检测比较器输出的跳变沿。每个上升沿或者下降沿代表曼彻斯特编码中bit中间的那个跳变。我用的方案是定时器输入捕获,这样能把跳变发生时的计数器值记录下来,自动计算脉宽,不用CPU去反复读计数器。

具体做法是:把接收引脚映射到定时器2的通道1,使能输入捕获和上升沿/下降沿中断。在中断回调中,读取当前捕获值和上一次捕获值,差值就是两个沿之间的时间,也就是半个bit或者一个bit的时长。根据这个时长判断当前电平持续了多长时间,从而还原出0和1。

这里有一个关键点需要在代码中处理:如果电平持续时间太长,超过了定时器溢出周期,会导致捕获计数归零,差值为负数或者异常小。解决办法是把定时器配置为1MHz计数频率,定时器溢出时间设置为10ms以上,这对应非常低的波特率余量。如果用TIM2,16位定时器在1MHz下最多计65535微秒,也就是约65ms,足够覆盖慢速信号了。如果波特率很高、两个沿之间时间很短,则不需要担心溢出问题。

使用HAL库时,输入捕获的启动方式如下:

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);

然后在回调函数里取计数差值:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { uint16_t current = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1); uint16_t diff = current - last_capture; last_capture = current; // 根据diff解析数据 } }

需要注意,中断回调里尽量不要做复杂的解码运算,否则会影响下一次捕获。我的做法是在中断里只把diff存到一个环形缓冲区,主循环里再取出解析。

3.3 数据帧协议与编解码

通信协议是保证数据可靠传输的核心。我定义了一个简单帧格式:

  • 前导码:0xAA 0xAA 0xAA,用于让接收端锁定时钟和同步。
  • 帧起始标志:0x7E。
  • 数据长度:1字节,表示后续数据字节数。
  • 数据载荷:若干字节。
  • 校验:CRC8或者简单的异或校验。

发射端发送时,先把帧拼接好,再进行曼彻斯特编码。接收端解码时,先从前导码中恢复时钟,然后检测0x7E定位帧头,再按照固定长度读数据,最后做校验。

编码函数不用太复杂,核心逻辑可以写成:

void manchester_send_byte(uint8_t byte) { for (int i = 0; i < 8; i++) { if (byte & 0x80) { // 发送“1”:先低后高 set_gpio_low(); delay_half_bit(); set_gpio_high(); delay_half_bit(); } else { // 发送“0”:先高后低 set_gpio_high(); delay_half_bit(); set_gpio_low(); delay_half_bit(); } byte <<= 1; } }

这里 delay_half_bit 可以用定时器延时或者DWT延时。如果用HAL_Delay,精度到毫秒级,对9600bps来说误差太大,必须用微秒级的延时。STM32F103可以用DWT -> CYCCNT寄存器实现精确延时,也可以在CubeMX里配置一个基础定时器做us级延时。

解码端的核心是状态机。每收到一个跳变,根据当前状态判断是数据还是干扰,然后按bit拼接字节。这个状态机需要处理三种情况:正常曼彻斯特跳变、噪声引起的毛刺、帧头检测。我建议大家在编码和解码的时候都加上调试输出,通过串口把接收到的脉宽时间打出来,这样调试比瞎猜效率高很多。

3.4 代码工程结构建议

工程结构虽然不直接影响功能,但直接影响你后期改代码的心情。我的建议是拆成四个模块:

  • bsp_led.c:LED驱动相关的GPIO和PWM初始化。
  • bsp_photo.c:光敏二极管接收、比较器输入捕获初始化。
  • manchester.c:曼彻斯特编码和解码状态机。
  • app_main.c:业务逻辑,比如读取传感器数据、组帧、解析帧、串口打印。

如果你用的是HAL库,建议直接从STM32CubeMX生成工程,把时钟、串口、定时器、GPIO都配好,再往工程里加自己的模块。如果用标准库,模板工程要自己搭,耗时会多一些,但代码逻辑更直观。两种方式我都试过,个人建议新手直接用CubeMX加HAL库,把更多精力放在协议调试上。

4. 实测记录与问题排查

4.1 上电测试流程和观测点

焊接好电路之后,不要急着接光电通信,先分模块测试。我的测试流程是这样的:

  • 第一步:用杜邦线把STM32的PB0手动拉高拉低,观察LED是否正常亮灭。
  • 第二步:用手机摄像头对准LED,发送一个慢速的方波信号,通过手机屏幕看到LED有肉眼不可见的闪烁,说明发射通路正常。
  • 第三步:把LED用手电筒或者手机闪光灯对准接收端,用万用表量比较器输出引脚,看是否能从低电平跳变到高电平。
  • 第四步:把发射端STM32和接收端STM32连接好,让接收端执行最原始的“收到高电平就点亮板载LED”的测试代码,确认整个链路是通的。
  • 第五步:再开始跑曼彻斯特编码解码代码,用串口把接收到的数据打出来。

前四步如果哪一步不正常,就不要往下走。很多问题最后查出来都是硬件接触不良或者电源没接好,白白浪费了很多时间。

4.2 排查实录:串口乱码、误码,距离上不去

我在调试过程中遇到最典型的问题有两个。

第一个问题是串口打印出来的接收数据一直是乱码,偶尔正确一个字节。用示波器看接收端波形,发现波形的边沿不是干净的方波,而是带有明显的振铃和缓坡。因为LM393比较器本身没有迟滞功能,信号在阈值附近来回抖动,导致一个跳变被误识别成多个跳变。解决办法是在LM393的输出端和同相输入端之间加一个几百kΩ的正反馈电阻,形成迟滞比较器,让上下阈值分开,这样信号一旦翻转就不会在边缘反复抖动。迟滞电阻我用的220kΩ,实测效果很好。

第二个问题是传输距离一直上不去,超过10厘米就开始丢包。排查下来发现LED使用的是普通5mm白光LED,发光角度太大,光能分散得厉害。我换成了聚光型LED,并且在接收端前面加了一个凸透镜聚焦,把距离提升到了50厘米以上。如果想再远,可以换更大功率的LED,比如1W的仿流明灯珠,配合恒流驱动。但要注意,功率上去后LED发热增加,PWM频率太高可能影响寿命。

4.3 参数调优:阈值自适应与滤波

环境光变化是可见光通信最麻烦的干扰源。白天和晚上、开灯和关灯,接收端的背景光强完全不一样,固定阈值只能在一个环境下工作。我后来做了一个自适应阈值方案:每隔一段时间,在接收端空闲时用ADC采样光敏二极管输出的平均电平,把这个值作为比较器的参考基准,动态调整判断阈值。STM32的ADC加上DMA扫描可以很轻松完成多通道采样,而且不占CPU时间,感兴趣的话可以参考“STM32 ADC多通道扫描循环采样DMA”的配置方式。

软件上还可以加一个简单的数字滤波,比如连续三次采样一致才认为电平有效,滤掉窄脉冲毛刺。曼彻斯特编码本身对毛刺有一定容忍度,因为合法的跳变间隔都是规律的,如果收到的脉宽明显异常,就直接丢弃。

4.4 常见问题速查表

现象常见原因解决办法
接收端完全无反应比较器供电或上拉电阻缺失检查LM393输出上拉到3.3V
串口输出乱码比较器无迟滞,边缘抖动增加220kΩ正反馈电阻
距离只有几厘米LED发光角太大换聚光LED或加透镜
白天阳光下无法工作背景光太强,直流偏置饱和加遮光罩或做交流耦合
高频时误码率高光敏电阻响应慢换光敏二极管接收
接收端偶尔复位LED电流尖峰干扰电源LED与STM32分开供电
帧头能抓到但数据错波特率偏差或时钟未同步检查编码函数延时精度,改用输入捕获测脉宽

5. 还可以往哪些方向扩展

5.1 从单向到双向通信

我目前做的是单向链路,发射端只管发,接收端只管收。实际使用中,双向通信更有意思。比如两个STM32节点各带一个LED和光敏接收管,采用半双工模式,定义主从关系,主节点发送数据后切换到接收模式,等待从节点应答。这和RS485通信的逻辑非常像,只是传输介质从线缆换成了光。我建议先把单工链路调稳,再考虑双向,否则收发切换的时序会让调试难度翻倍。

5.2 结合传感器做室内光通信节点

可见光通信很适合和传感器结合,做成“有光就有数据”的智能化场景。比如做一个基于STM32的智能台灯,LED既负责照明,又周期性向外发送温湿度数据,放在桌上的接收节点收到数据后显示在OLED屏幕上。开灯的同时就完成了数据分发,这种体验比单独拉一根串口线有意思得多。想做得更复杂的,可以引入FreeRTOS,接收解码任务、传感器采集任务、串口打印任务分时运行,系统扩展性会好很多。加上Wi-Fi模块之后,还能把光通信收到的数据转发到本地网络,形成“最后几米的光接入”方案。

5.3 需要再深挖的方向

如果想把可见光通信做成一个真正有说服力的作品,有几个方向值得深挖:一个是OFDM调制,把多个频率的光信号叠加在一起传输,频谱效率成倍提升,但F103的算力可能不太够,需要换更高主频的芯片;另一个是纠错编码,比如汉明码或者CRC重传机制,能在丢包率较高的可见光链路上显著提高可靠性;还有一个是室内定位,利用多个LED的位置信息和接收光强,通过三角定位估算接收端的位置,这一块在学术和工程上都很热。

给第一次做这个项目的人的三点建议

做可见光通信和我之前做普通串口通信、I2C传感器最大的不同在于:它没有一个稳定的有线通道,信号在空气里传播时会被各种因素干扰。这也正是它有意思的地方。根据我自己的实操经验,第一次做的话,先不要追求高速率,把波特率设在1200bps到2400bps之间,用最简单的曼彻斯特编码跑通链路,再一步步优化。等你看到接收端串口里正常打印出“Hello Li-Fi”的一瞬间,会觉得之前熬夜调阈值都是值得的。不要怕把电路改来改去,这个项目里,示波器看到的每一种古怪波形,都是对通信原理的一次直观理解。

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

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

FreeRTOS与LVGL联合开发嵌入式GUI:智能手表实战与工程优化

先问一个问题&#xff1a;你见过多少个嵌入式 UI 项目&#xff0c;是“功能能跑&#xff0c;但代码根本不敢维护”的&#xff1f;我以前接过一个手表原型项目&#xff0c;功能很简单&#xff1a;显示时间、心跳、计步&#xff0c;三个页面切换&#xff0c;加一个菜单。一开始用…

作者头像 李华
网站建设 2026/8/31 1:57:39

异环线下活动cos真红,角色还原技术全拆解

这次不聊新框架&#xff0c;聊一次游戏线下活动&#xff1a;异环在日本办了线下活动&#xff0c;菌烨小姐姐出了真红的 cos&#xff0c;还原度讨论度都很高。很多人第一眼关注的是“像不像”&#xff0c;但站在技术视角看&#xff0c;“还原”这件事本身就是可以拆解成参数、流…

作者头像 李华
网站建设 2026/8/31 1:56:00

DOTA2翻盘局深度复盘:BB落后2万经济逆转1Win,GPK帕克关键操作解析

1. 比赛背景与数据观察&#xff1a;BB vs 1Win 系列赛复盘先聊一下这场比赛的整体观感。BB 与 1Win 这场 BO3 打满三局&#xff0c;最终 BB 以 2:1 拿下胜利。这个比分本身并不算意外&#xff0c;真正让观众讨论最多的是第三局——BB 在中期一度落后 2 万左右的经济&#xff0c…

作者头像 李华
网站建设 2026/8/31 1:54:48

ComfyUI新手入门:从节点式工作流到AI视频生成全攻略

ComfyUI 是当前 AI 绘画和 AI 视频生成领域非常值得系统学习的工作流工具。它和普通画图软件不同&#xff0c;核心是节点式工作流&#xff1a;把加载模型、写提示词、采样、解码、保存这些步骤拆成节点&#xff0c;用连线串起来&#xff0c;组成一个可复用、可分享、可修改的流…

作者头像 李华
网站建设 2026/8/31 1:53:07

SaltStack实战:Master-Minion搭建与Nginx批量部署

一条“Salt 公会招人&#xff0c;50 级以上就行&#xff0c;等级接近的我会带”的招募启事&#xff0c;初看像游戏公会的门槛设计&#xff1a;目标明确&#xff0c;不要求零基础&#xff0c;也不要求顶尖&#xff0c;只要求彼此等级接近&#xff0c;方便互相带。放到技术圈里&a…

作者头像 李华