无线DAP-Link:嵌入式无线调试的工程实现与隔离设计

从零构建无线DAP-LINK:ESP32如何重塑嵌入式调试体验 本文详细介绍了如何利用ESP32构建无线DAP-LINK调试器,突破传统有线调试在高压、隔离或空间受限环境中的限制。通过硬件选型、电路设计、软件协议栈实现及性能优化,展示了ESP32在嵌入式调试中的创新应用,为开发者提供灵活、安全的无线调试解决方案。 阅读详情

1. 无线调试的工程价值与设计边界

在嵌入式系统开发流程中,调试接口的物理连接方式远不止是“线长一点还是短一点”的便利性问题。它直接定义了硬件隔离等级、系统安全边界、测试可重复性以及现场部署灵活性。传统有线调试(如ST-Link、J-Link通过SWD/JTAG连接)虽稳定可靠,但在特定场景下存在不可忽视的工程约束:

  • 电气隔离缺失 :当目标板运行在高压电机驱动、工业变频器或电源管理模块附近时,调试线缆可能成为共模干扰耦合路径。曾有项目因USB线缆引入高频噪声导致ADC采样值跳变20%,排查两周后确认为地环路问题;
  • 物理接入限制 :密闭金属机箱、IP67防护外壳、旋转机构或高振动环境无法长期保留调试接口暴露;
  • 多节点批量烧录效率瓶颈 :产线对200台同型号设备逐台插拔下载器,单台耗时45秒,总耗时超2小时;
  • 安全策略冲突 :医疗设备认证要求调试接口必须物理断开才能进入运行模式,而有线方案难以实现自动化断连。

无线DAP-Link正是针对上述约束提出的工程解法。需明确其技术定位:它并非替代JTAG/SWD协议栈,而是将标准CMSIS-DAP协议封装进无线传输层,在保持GDB/IDE兼容性的前提下,将物理调试通道虚拟化。本方案基于ESP32-WROOM-32双核MCU构建无线桥接节点,通过Wi-Fi将PC端OpenOCD指令流转发至STM32目标芯片的SWDIO/SWCLK引脚。关键设计边界在于:
- 协议保真度 :所有CMSIS-DAP命令(如DAP_Transfer、DAP_SWJ_Clock)必须零字节透传,禁止任何协议层修改;
- 时序容忍度 :SWD协议要求最小时钟周期≥100ns,无线链路引入的指令延迟需控制在μs级,避免触发目标芯片SWD超时复位;
- 供电独立性 :桥接节点必须自持供电,禁止从目标板取电,否则破坏电气隔离初衷。

2. 硬件架构设计:隔离与可靠性保障

无线DAP-Link的硬件设计核心是构建三层隔离结构:电源隔离、信号隔离、协议隔离。这决定了其能否在工业现场长期稳定运行。

2.1 电源隔离方案

ESP32桥接节点采用DC-DC隔离电源模块(如RECOM R-78E5.0-0.5)而非LDO,原因在于:
- LDO无隔离能力,输入输出地仍为同一参考点;
- DC-DC模块提供3kV AC隔离耐压,实测可承受±15kV ESD脉冲而不复位;
- 隔离电源次级侧为ESP32和电平转换电路单独供电,彻底切断目标板与PC间的地电位差传导路径。

目标板SWD接口供电由桥接节点本地LDO(TPS7A05)提供,电压精度±1%。该设计强制目标板SWD逻辑电平与桥接节点同步,避免因电压不匹配导致的通信误码——曾有项目因目标板使用3.3V而桥接节点误用5V电平,导致SWDIO引脚持续灌电流达8mA,三天后目标芯片SWD接口永久损坏。

2.2 信号隔离电路

SWDIO与SWCLK信号采用双通道数字隔离器(Si8622ED)实现电气隔离,其关键参数选择依据:
- 传播延迟≤15ns :满足SWD最高速率4MHz(250ns周期)下的时序裕量要求;
- CMTI(共模瞬态抗扰度)≥75kV/μs :在电机启停产生的dV/dt=5kV/μs环境下仍能正常通信;
- 失效模式设计 :隔离器输出端配置10kΩ上拉电阻至3.3V,确保隔离器故障时SWDIO保持高阻态,避免目标芯片被意外拉低复位。

特别注意SWDIO双向信号的隔离处理:Si8622ED内部集成方向控

STM32+DAPLink打造无线脱机烧录器:手把手教你从PCB设计到固件拖烧(附开源地址) 本文详细介绍了如何基于STM32微控制器和开源DAPLink协议栈,从零打造一个支持无线传输和脱机烧录功能的专业工具。内容涵盖从硬件PCB设计、核心电路要点,到集成DAPLink固件、文件系统、虚拟U盘以及无线功能的完整固件架构,并提供了调试优化与量产考量,手把手教你实现从设计到固件拖烧的全流程。 阅读详情

相关推荐

告别线缆束缚:用ESP32自制无线DAP-LINK调试器,隔离高压、狭小空间调试神器

本文详细介绍如何利用ESP32自制无线DAP-LINK调试器,解决高压隔离、狭小空间等特殊环境下的调试难题。通过优化硬件架构和软件协议栈,实现高效、安全的无线调试方案,显著提升工程效率和安全性。

weixin_30876945的博客 479

无线调试新纪元:ESP32S3 DAP-Link在物联网开发中的实践与挑战

本文探讨了ESP32S3 DAP-Link无线调试技术在物联网开发中的应用与挑战。通过分析其双模工作能力、硬件架构优化及实践配置流程,展示了无线调试在高危环境、远距离维护等场景中的显著优势,为开发者提供了效率革命性的解决方案。

palm99的专栏 625

基于ESP32的无线DAP-LINK调试器设计与实现

本文详细介绍了基于ESP32的无线DAP-LINK调试器设计与实现,重点分析了其核心价值、硬件设计要点和软件架构。通过WiFi实现无线调试,解决了传统有线调试器在高压隔离、移动自由和多设备共享等方面的局限,特别适用于嵌入式开发中的特殊场景。文章还提供了ESP32选型建议、关键电路设计和性能优化技巧,帮助开发者高效构建无线调试解决方案。

weixin_29159613的博客 364

告别线缆束缚:用ESP32自制无线DAP-LINK调试器,实测KEIL/IAR远程调试

本文详细介绍了如何利用ESP32自制无线DAP-LINK调试器,实现KEIL/IAR远程调试,摆脱传统有线调试的束缚。通过优化Wi-Fi传输稳定性,这款低成本方案在嵌入式开发中展现出高效性能,特别适合高压隔离和多设备协同调试等特殊场景。

weixin_30820077的博客 415

告别线缆束缚:用ESP32自制无线DAP-LINK调试器,KEIL/IAR远程调试实战

本文详细介绍了如何利用ESP32模块自制无线DAP-LINK调试器,实现KEIL/IAR远程调试,解决传统有线调试器在高压隔离环境、运动设备诊断和多设备协同中的局限。通过硬件搭建、固件开发和PC端配置的实战指南,帮助开发者轻松实现无线调试自由,提升工作效率。

weixin_30388677的博客 355

KEIL/IAR无线调试新玩法:手把手教你给ESP32刷机,实现CMSIS-DAP v2无线化改造

本文详细介绍了如何将ESP32开发板改造为支持CMSIS-DAP v2协议的无线调试器,适用于KEIL MDK和IAR Embedded Workbench。通过WiFi连接,开发者可以摆脱有线调试的物理限制,提升ARM Cortex-M开发的灵活性和效率。文章包含硬件准备、固件刷写、开发环境配置及实战技巧,特别适合需要远程或多设备调试的场景。

weixin_30562507的博客 528

基于ESP32的无线DAP-LINK调试器:从有线到无线的设计实践与场景解析

本文详细介绍了基于ESP32的无线DAP-LINK调试器的设计与实现,重点分析了从有线到无线转换的技术要点和实际应用场景。通过硬件设计优化和软件协议栈改造,解决了无线调试中的延迟和带宽问题,特别适用于高压设备和运动设备的调试场景。文章还提供了性能测试数据和优化建议,帮助开发者更好地利用无线调试技术提升开发效率。

weixin_42653691的博客 374

用ESP32打造无线DAP-Link:从CMSIS-DAP协议到SWD时序的完整指南

嵌入式开发中,调试器与目标板之间的有线连接常常成为移动场景的瓶颈。CMSIS-DAP作为ARM标准的调试接口协议,传统上依赖USB传输,而ESP32凭借集成WiFi/蓝牙和双核处理能力,为调试器无线化提供了理想载体。通过解析CMSIS-DAP命令并在GPIO上模拟SWD时序,PC端的OpenOCD或pyOCD即可通过网络远程操作调试器,实现断点、读写寄存器和固件烧录。这一方案在无人机、机器人、产线远端维护等场景中显著提升调试灵活性。本文从协议原理到硬件接线、固件实现和主机端配置,系统梳理无线DAP-Link

weixin_29159441的博客 344

无线调试器的双面刃:速度与兼容性的博弈

本文深入探讨了无线调试器在嵌入式开发中的速度与兼容性挑战,重点分析了基于ESP32和DAP-LINK的无线调试方案。通过技术架构解析、速度优化实战和跨平台兼容性攻坚,为开发者提供了选型建议和故障排查指南,帮助在高压隔离调试、移动设备开发等场景中提升效率。

weixin_29175469的博客 427

ESP32秒变双模调试器:一份代码实现有线DAP-LINK与无线WiFi调试自由切换

本文详细介绍了如何利用ESP32芯片实现有线DAP-LINK与无线WiFi调试的双模自由切换方案。通过硬件复用和智能切换设计,开发者可以在不同场景下灵活选择调试方式,显著提升嵌入式开发效率。重点解析了硬件架构、软件实现及性能优化策略,为开发者提供了一套完整的双模调试器解决方案。

weixin_42620340的博客 422

基于ESP32S3的无线DAP-Link调试器:从零DIY扔掉USB线

嵌入式调试中,物理USB连接常常成为开发瓶颈:电机转动绞线、飞控拆装耗时、多人协作受限。CMSIS-DAP作为ARM标准调试协议,命令层与传输层解耦,这为无线化改造提供了可能。借助WiFi替代USB,将DAP命令封装为TCP报文,由ESP32S3芯片原生完成协议解析与SWD时序生成,即可构建一套脱离线缆的无线调试方案。本文从协议原理出发,介绍如何基于ESP32S3设计数据通路、处理TCP粘包与SWD时序细节,并实现兼容OpenOCD与pyOCD的主机端接入。方案兼顾有线/无线双模共存,实测批量打包后下载速度

aofan9566的博客 886

ST-LINK V2仿真器,改成CMSIS-DAP仿真器,同时带有SWO和CDC功能

为什么要改,也许只是好奇。 TB上面ST-LINK仿真器的小板,包邮还不到15元。 附件中,-V20和-V21分别用于ST-LINK v2.0(只有一个单色LED),和v2.1(双色LED,或两个LED的) 如果要使用SWO/CDC功能,可能需要自己将有关GPIO线接到外面: SWO ------------- PB7。 CDC -------------- PA2/PA3(USART2)。

Dify如何实现自主学习

摘要:Dify通过构建感知-决策-执行-反馈的闭环实现"自主学习",本质是打造能自动获取信息、更新知识库并调整策略的Agent工作流。核心包括:1)建立知识库作为记忆体;2)搭建感知与执行工具获取实时信息;3)通过工作流编排决策"大脑",包含LLM决策节点、行动执行节点和反馈反思节点。典型应用如根据用户反馈优化回答风格,通过存储反思日志到知识库实现持续优化。这种机制使智能体能基于新数据和经验不断自我改进。

专注于技术研发行业技术主要有AI人工智能视觉识别、物联网技术、电商平台、app原生技术、微信小程序、鸿蒙语言开发、办公企业oa、ERP等,致力于做东半球最优秀的程序员 727

ROS Navigation global_planner框架解析

ROS Navigation global_planner框架解析主要讲一下我看源码总结的框架,如果大家跟着这个框架看源码的话可能会看的比较快。主要讲解global_planner关键配置参数含义及关键函数Astar,Dijkstra,QuadraticCalculator::calculatePotential,PotentialCalculator::calculatePotential,GridPath::getPath,GradientPath::getPath.

Jeff_Lee_的博客 4695

swupdate-签名验证

swupdate加密部分具体在中可以查看。

qq_28219531的博客 1149

RK3568 开发实战:手动构建 Linux 4.19 内核镜像与设备树优化

本文详细介绍了为RK3568开发板手动编译Linux 4.19内核的完整实战流程。从环境搭建、源码获取、内核配置,到设备树深度定制与优化,再到镜像打包与烧写,旨在帮助开发者脱离官方SDK依赖,实现对嵌入式Linux系统的完全掌控,提升硬件适配与性能优化能力。

weixin_29175469的博客 270

从零部署奥比中光Gemini335L:Python SDK编译与手眼标定环境实战

本文提供了一份从零部署奥比中光Gemini 335L深度相机的完整实战指南。详细介绍了驱动安装、Python SDK编译、CMake配置及虚拟环境搭建等关键步骤,并重点解析了如何通过编译生成Python模块,最终实现深度图与点云数据获取,为后续的机械臂手眼标定工作奠定坚实基础。

weixin_29031161的博客 399

从选型到调试:MCU外部晶振电路设计的实战避坑指南

本文详细解析了MCU外部晶振电路设计的关键要点,从选型到调试提供全面指南。重点探讨了晶振频率选择、负载电容计算、PCB布局优化等核心问题,并分享常见故障排查技巧与EMC设计经验,帮助工程师规避设计陷阱,提升嵌入式系统时钟稳定性。

weixin_30872577的博客 280

实验吧 损坏的U盘镜像

        从网站上可以下载一个CTF.hdd的文件,使用winHex打开,可以知道这是一个exFAT格式的文件。        用binwalk检查一下,发现文件中包含两个zip文件,使用foremost进行提取。一个压缩包需要密码解压缩,另一个解压后发现Password.txt文件。说明另一个压缩包的密码与checksum有关。        通过查看exFAT文件系统格式可以得知如何计算...

xingyyn78的博客 3513

西门子交换机环网冗余设置(实战篇2.2)

MRP的重组时间为 200ms 因此 PROFINET 通信必须选择大于 200ms 的看门狗时间,看门狗。ET200SP默认为 2ms*3=6ms) MRP 的重组时间为 200ms 故系统会报出看门狗超时。更新,默认是 3 个周期,超出设置的周期数就会报 IO 设备故障。时间不是直接配置的,而是作为没有 IO 数据可接受的更新周期,也就是允许几个周期没有数据。来达到大于 200ms 的看门狗时间的要求(看门狗时间 可接受更新周期数 更新时间)。是IO 控制器和 IO 设备)

weixin_42580591的博客 369

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

上一篇: MOSFET栅极振铃原理与抑制三大工程策略
下一篇: STM32F407电子琴系统时钟与GPIO驱动配置详解
github5actions
博客等级 码龄1天 0粉丝 1824原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值