文章目录

  • 前言
  • 一、UFCS 与USB-PD的优缺点比较
  • 二、UFCS协议分析工具
    • 1.PULSEVIEW
    • 2.DSview
    • 3.UFCS协议分析软件插件共享
  • 总结

前言


不同品牌终端和适配器之间不能有效识别,只能实现较低功率的充电。一方面,用户快充体验受到很大的制约和限制,不兼容问题成为用户的一大痛点;另一方面,由于充电标准不统一,导致产业链上下游厂商研发通用快充电源芯片和配件的风险和成本相对高昂。技术制式的不统一也将妨碍终端绿色能源和循环经济的长期发展。

目前USB-PD已经成为欧洲的标准,所有厂商都表示支持。中国也在2021年提出了UFCS标准,目前正在积极推广中,基于中国是世界第一大手机市场,更是第一大的电子产品制造国,UFCS应该有着巨大的前景!

一、UFCS 与USB-PD的优缺点比较

UFCS 的物理层就是UART串口,几乎所有的MCU都自带UART串口硬件,这就让产品开发起来很简单了。而USB-PD 采用BMC编码,简单说就是用脉冲的宽窄代表1和0,而且信号的高电平才1V左右,这就必须要有硬件比较器,增加了成本。好处当然是抗干扰的能力更强。然而UART经过几十年的发展,也有许多的工业应用,比如RS232, RS485, LIN, MODBUS…, 足够应付各种场景了吧?!

USB-PD的频率是300Kbps, 软件发送边沿的跳变就要600KHz, 接收采样就需要5-10倍的速度,才能有效保证不丢数据位,这对于ARM32位的MCU也需要主频48MHz 才能够用。对于应用量更大的8位MCU,就只能靠硬件来实现物理层了,纯软件处理速度跟不上。用硬件的缺点首先是增加了成本,其次硬件开发周期长,合并进入芯片,这个过程至少也要半年一年。芯片debug也就是流片的成本,又要几十万,上百万。而在UART基础上做个UFCS的协议软件,也就2-3周时间。

还有一点很重要,USB-PD需要额外的两条CC线,来传送数据,完成通讯。UFCS则是利用USB原有的D+,D-两条数据线来通讯。这和高通,华为等手机大厂的方式一样,好处又是硬件简单。而且可以在USB-A/B USB-C 等所有USB 口上实现,USB-PD就只支持新的type-C接口了。

基于以上的点看,USB-PD标准发布至今已经10年了,才刚刚开始大面积应用,应该是跟各种硬件成本和应用难度不无关系,重新开发硬件,开发软件都不是简单的事情。

当然,UFCS目前功能还比较简单。USB-PD的以下功能,UFCS暂时还没有:

  1. Dual-role, 就是一个口,又能充电也能放电,就是有的手机口还能当充电宝,给其他手机充电。只看手机对手机,感觉比较鸡肋。但是,如果发挥想象力,你的手机,电脑,显示器,笔电等等电器都用USB线连在一起,只需要一个充电器了。乱七八糟的插座,是不是就不要那么多了?
  2. Alternative, 就是这个PD口可以代替视频线,音频线,HDMI,雷电,等等,你的显示器,只需要一根线跟主机连接,连电源线也不要了。所有的设备之间连接只有USB,不管是信号线还是电源线,只有USB一种,简单了吧?

以上是最近几个月学习USB-PD和UFCS,的一些体会,下面也分享一些有用的东东给大家,希望对UFCS的发展添砖加瓦。(本文欢迎转发,但请保留作者联系信息 i2tv@qq.com)

二、UFCS协议分析工具

1.PULSEVIEW

PULSEVIEW 是sigrok开源的协议分析软件,无数的协议分析仪和示波器都用了这家的软件,上百种协议的软件都是开源的,比如UART, IIC, SPI, USB-PD, LIN, CAN呀, 相当赞!我来贡献UFCS协议分析包,不知道能否被接受呢。先共享出来给大家用吧。


硬件价格从20元人民币到几万美元的都有,分析UFCS就去某宝或者PDD上买个几十元的就够用了。协议支持都是基于sigrok开源共享的,只是采样速度和阈值电平的调节不同。以上的图是用muselab家的板子采的,不是最低价,主要表示对开源的支持!

说到开源,我觉得是一种共享知识的模式,能让软件硬件迅速发展和普及,建议UFCS等等协议也应该开源,协议开放,并且提供参考源代码,参考硬件设计,让开发者可以拿来就用,这样发展就快了。第一步我先把自己写的UFCS协议分析包开源提供在这里,或者Gitee, github(访问太慢了,这是共享软硬件的资源宝库,应该设法加速呀!)。

2.DSview

另外,还要分析USB-PD的话,推荐DSlogic。也是基于sigrok的共享软件,二次开发的。


DSlogic主要优点是阈值电平可以调节,也就是识别更低的电平,因为USB-PD的高电平1V左右,普通MCU无法直接识别,必须有硬件比较器的电平转换。
另外一个重要优点就是上图蓝色的部分,直接点击搜索需要的特征值,然后点击就可以迅速找到数据包的位置,这个对于协议分析的效率很高,pulseview 要左右拉来拉去,用肉眼找数据,还是很费脑子的;)

个人版300-500元的价格,跟老外的价格比较起来,就是挣个茶水费喽。

3.UFCS协议分析软件插件共享

基于sigrok的协议分析软件,都有一个decoders目录,里面每个子目录是一个协议,包括两个文件__init__.py 和 pd.py。所以看这些python源码就可以知道上百种协议的原理了。改到MCU上,用c语言实现也就轻松愉快。
下载链接1
https://gitee.com/renxn/ufcs.git
下载链接2
https://github.com/392625227/UFCS-protocol-compare-with-USB-PD

只要下载里面的两个文件,在你的pluseview或者dsview的decoders下面加一个ufcs目录,再把__init__.py 和pd.py 拷贝到decoders/ufcs目录下,重新打开pulseview 或者 dsview就可以分析UFCS协议包了。
主要几个文件,最重要的最长,放在本文章最后面,直接黏贴都可以不用下载。.sr 文件是pulseview软件抓取的波形,先选UART,然后再选UFCS,就可以分析UFCS数据包。.dsl是DSview软件抓的UFCS波形,协议直接选UFCS就行。要学习UFCS的协议包格式,除了看TTAF 083-2022 移动终端融合快速充电技术规范.pdf,就是用pulseview 或者dsview直接看图识字,最简单不过了。开本文的分享的代码也很简单。
只要这里两个文件,在decoders下面加一个ufcs目录,再把__init__.py 和pd.py 拷贝到decoders/ufcs目录下,重新打开pulseview 或者 dsview就可以用分析UFCS协议包了。

1__init__.py 主要就一句话,为了pulseview, DSview软件找到这个协议

from .pd import Decoder
  1. pd.py 有点儿长,凑合看吧;)
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2023 edison ren <i2tv@qq.com>
## ref from uart & usb_power_delivery
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, see <http://www.gnu.org/licenses/>.
##import sigrokdecode as srd# Control Message type
CTRL_TYPES = {0: 'PING',1: 'ACK',2: 'NCK',3: 'ACCEPT',4: 'SOFT RESET',5: 'POWER READY',6: 'GET OUTPUT CAP',7: 'GET SOURCE INFO',8: 'GET SINK INFO',9: 'GET CABLE INFO',10: 'GET DEVICE INFO',11: 'GET ERROR INFO',12: 'DETECT CABLE INFO',13: 'START CABLE DETECT',14: 'END CABLE DETECT',15: 'EXIT UFCS MODE',
}# Data message type
DATA_TYPES = {1: 'OUTPUT CAP',2: 'REQUEST',3: 'SOURCE INFO',4: 'SINK INFO',5: 'CABLE INFO',6: 'DEVICE INFO',7: 'ERROR INFO',8: 'CONFIG WATCHDOG',9: 'REFUSE',10: 'Verify_Request',11: 'Verify_Response',255: 'Test Request'
}class Decoder(srd.Decoder):api_version = 3id = 'ufcs'name = 'UFCS'longname = 'Universal Fast Charging Specification'desc = 'Universal fast charging specification for mobile devices. T/TAF 083-2021. Coding by edison ren 2023.1.25 <i2tv@qq.com>'license = 'gplv2+'inputs = ['uart']outputs = []tags = ['PC/Mobile']options = ({'id': 'fulltext', 'desc': 'Full text decoding of packets','default': 'no', 'values': ('yes', 'no')},)annotations = (('type', 'Packet Type'),('training', 'Training'),('header', 'Header'),('data', 'Data'),('crc', 'Checksum'),('warnings', 'Warnings'),('src', 'Source Message'),('snk', 'Sink Message'),('payload', 'Payload'),('text', 'Plain text'),('cable', 'Cable Message'),('reserved', 'Reserved'),)annotation_rows = (('phase', 'Parts', (1, 2, 3, 4,)),('payload', 'Payload', (8,)),('type', 'Type', (0, 6, 7, 10, 11)),('warnings', 'Warnings', (5,)),('text', 'Full text', (9,)),)def __init__(self):self.reset()def reset(self):self.ss_block = None    # start pos with samles for showself.es_block = None    # end pos with samples for showself.dataidx = 0        # data pos with u8 in packet self.datapkt = []       # data buffer for packet, 4:128self.head = []          # header 2*u8 self.bytepos = []       # (s, e) pos of byte (start, end) self.text = ''          # info string def start(self):self.out_ann = self.register(srd.OUTPUT_ANN)def head_id(self):return (self.head[0] >> 1) & 15def head_power_role(self):return (self.head[0] >> 5) & 7def head_rev(self):return (self.head[1] >> 3) & 31def head_type(self):return self.head[2]def data_len(self):# data_msg count = data[3], ctrl_msg count = 0 return self.head[3] if (self.head[1] & 7) == 1 else 0def putx(self, s0, s1, data):self.put(s0, s1, self.out_ann, data)def putwarn(self, longm, shortm):self.putx(0, -1, [8, [longm, shortm]])def compute_crc8(self):CRC_8_POLYNOMIAL = 0x29rCRC = 0for s in range(self.plen - 1):rCRC ^= self.datapkt[s]for i in range(8):if (rCRC & 0x80):rCRC = (rCRC << 1) ^ CRC_8_POLYNOMIALelse:rCRC = (rCRC << 1)return (rCRC & 0xff)def get_short(self, i):k = [self.datapkt[i], self.datapkt[i+1]]val = k[0] <<8 | (k[1])return valdef get_word(self, i):hi = self.get_short(i)lo = self.get_short(i+2)return lo | (hi << 16)def get_dword(self, i):hi = self.get_word(i)lo = self.get_word(i+4)return lo | (hi << 32)def puthead(self):# message reviever, SRC, SNK, Cablepwr_role = self.head_power_role()if pwr_role == 1:ann_type = 6role = 'SRC'elif pwr_role == 2:ann_type = 7role = 'SNK'elif pwr_role == 3:ann_type = 10role = 'Cable'else:ann_type = 11role = 'Reserved't = self.head_type()if self.data_len() == 0:if t > 15:shortm = 'reserved cmd'else:shortm = CTRL_TYPES[t]else:shortm = DATA_TYPES[t] if t in DATA_TYPES else 'DAT???'longm = '(r{:d}) {:s}[{:d}]: {:s}'.format(self.head_rev(), role, self.head_id(), shortm)self.putx(self.bytepos[0][0], self.bytepos[2][1], [ann_type, [longm, shortm]])self.text += longmdef get_source_cap(self):numbpdo = int(self.data_len()) // 8strpdo = ''for numb in range(numbpdo):pdo = self.get_dword(4 + 8 * numb)mode = (pdo >> 60) & 15step_ma = ((pdo >> 57) & 7) * 10 + 10step_mv = ((pdo >> 56) & 1) * 10 + 10max_mv = ((pdo >> 40) & 0xffff) * 0.01min_mv = ((pdo >> 24) & 0xffff) * 0.01max_ma = ((pdo >> 8) & 0xffff) * 0.01min_ma = (pdo & 0xff) * 0.01strpdo = '[%d] %g/%gV *%gmv %g/%gA *%gma ' \% (mode, min_mv, max_mv, step_mv, min_ma, max_ma, step_ma)s0 = self.bytepos[4 + 8 * numb][0]s1 = self.bytepos[4 + 8 * numb + 7][1]# show data in hexself.putx(s0, s1, [3, ['[%d]%08x' % (numb, pdo), 'D%d' % (numb)]])# show data in commenttxt = '(PDO %s)' % strpdoself.putx(s0, s1, [8, [txt, txt]])# show data in full text stringself.text += ' - ' + txtreturn self.textdef get_request(self):rdo = self.get_dword(4)mode = (rdo >> 60) & 15curr = (rdo & 0xffff) * 0.01volt = ((rdo >> 16) & 0xffff) * 0.01s = '%gV %gA' % (volt, curr)return rdo, '(PDO #%d) %s' % (mode, s)def get_src_info(self):d = self.get_dword(4)#self.putwarn('bbbbbb%08x' % self.get_dword(4), 'aaa')it = ((d >> 40 ) & 0xff) - 50its = ',internal temp %s' % ('%dC' % it if it > -50 else 'no data')pt = ((d >> 32 ) & 0xff) - 50pts = ',usb port temp %s' % ('%dC' % pt if pt > -50 else 'no data')curr = (d & 0xffff) * 0.01volt = ((d >> 16) & 0xffff) * 0.01return d, '(SRC info: %gV %gA %s %s)' % (volt, curr, its, pts)def get_snk_info(self):d = self.get_dword(4)it = ((d >> 40 ) & 0xff) - 50its = ',battery temp %s' % ('%dC' % it if it > -50 else 'no data')pt = ((d >> 32 ) & 0xff) - 50pts = ',usb port temp %s' % ('%dC' % pt if pt > -50 else 'no data')curr = (d & 0xffff) * 0.01volt = ((d >> 16) & 0xffff) * 0.01return d, '(SNK info: %gV %gA %s %s)' % (volt, curr, its, pts)def get_cable_info(self):d = self.get_dword(4)id = ((d >> 48 ) & 0xffff)ids = 'Cable VID %04X' % (id)emk = ((d >> 32 ) & 0xffff)emks = 'Emark VID %04X' % emkimp = ((d >> 16) & 0xffff)imps = 'IMP %d' % imp curr = (d & 0xff)volt = ((d >> 8) & 0xff)return d, '(%s %s %s %gV %gA)' % (ids, emks, imps, volt, curr)def get_device_info(self):d = self.get_dword(4)id = ((d >> 48 ) & 0xffff)ids = 'Device VID %04X' % (id)pid = ((d >> 32 ) & 0xffff)pids = 'Protocol IC VID %04X' % emkhwv = ((d >> 16) & 0xffff)hwvs = 'HW rev%04X' % imp swv = (d & 0xffff) swvs = 'SW rev%04X' % imp return d, '(%s %s %s %s)' % (ids, pids, hwv, swv)def get_error_info(self):d = self.get_word(4)id = ((d >> 15 ) & 0x1ffff)ids = 'Reversed %04X' % (id)e14 = ((d >> 14 ) & 1)e14s = 'Watchdog %s' % ('OK' if e14 == 0 else 'NG!')e13 = ((d >> 13 ) & 1)e13s = 'CRC %s' % ('OK' if e13 == 0 else 'NG!')e12 = ((d >> 12 ) & 1)e12s = 'Input %s' % ('OK' if e12 == 0 else 'NG!')e11 = ((d >> 11 ) & 1)e11s = 'Current loss %s' % ('OK' if e11 == 0 else 'NG!')e10 = ((d >> 10 ) & 1)e10s = 'UVP %s' % ('OK' if e10 == 0 else 'NG!')e9 = ((d >> 9 ) & 1)e9s = 'OVP %s' % ('OK' if e9 == 0 else 'NG')e8 = ((d >> 8 ) & 1)e8s = 'D+OVP %s' % ('OK' if e8 == 0 else 'NG')e7 = ((d >> 7 ) & 1)e7s = 'D-OVP %s' % ('OK' if e7 == 0 else 'NG')e6 = ((d >> 6 ) & 1)e6s = 'CCOVP %s' % ('OK' if e6 == 0 else 'NG')e5 = ((d >> 5 ) & 1)e5s = 'Battery OTP %s' % ('OK' if e5 == 0 else 'NG')e4 = ((d >> 4 ) & 1)e4s = 'USB port OTP %s' % ('OK' if e4 == 0 else 'NG')e3 = ((d >> 3 ) & 1)e3s = 'SCP %s' % ('OK' if e3 == 0 else 'NG')e2 = ((d >> 2 ) & 1)e2s = 'OCP %s' % ('OK' if e2 == 0 else 'NG')e1 = ((d >> 1 ) & 1)e1s = 'UVP %s' % ('OK' if e1 == 0 else 'NG')e0 = ((d >> 0 ) & 1)e0s = 'OVP %s' % ('OK' if e0 == 0 else 'NG')return d, '(%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s)' % (ids, \e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0)def config_watchdog(self):d = self.get_short(4)return d, 'Watchdog overflow time %dms' % ddef refuse(self):d = self.get_word(4)rev = ((d >> 28 ) & 0xf)revs = ('Reversed %01X' % rev) if rev else ''rev2 = ((d >> 19 ) & 0xf)revs2 = ('Reversed %01X' % rev2) if rev2 else ''id = ((d >> 24 ) & 0xf)ids = 'MSG #%d' % (id)t = ((d >> 16 ) & 7)ts = ', Type %d' % tsc = ((d >> 8) & 0xff)cs = ', CMD %d' % cr1 = ((d >> 0) & 0x7)rs1  = ', unknow'      if r1 == 1 else ''rs1 += ', not support' if r1 == 2 else ''rs1 += ', busy'        if r1 == 3 else ''rs1 += ', over range'  if r1 == 4 else ''rs1 += ', other'       if r1 == 5 else ''return d, 'Refuse why? $s' % (ids + ts + cs + revs +revs2 + rs1)def verify_request(self):id = self.datapkt[4]dhi = self.get_dword(5)dlo = self.get_dword(5 + 8) return id, 'Verify request key ID %d, random %08x%08x' % (id, dhi, dhl)def verify_response(self):key = self.get_dword(4)rand = self.get_word(4+8) return id, 'Verify request data %08x, random %04x' % (key, rand)def decode_data_msg(self):dlen = self.data_len()# no data, do nothingif dlen == 0:returntxt = ''t = self.head_type()# SRC CAPif   t == 1:self.get_source_cap()# src cap has n(1-15) PDO, putx will be run n times within function,# so difference herereturn # requestelif t == 2:d, txt = self.get_request()# SRC infoelif t == 3:d, txt = self.get_src_info()# SNK infoelif t == 4:d, txt = self.get_snk_info()# cable infoelif t == 5:d, txt = self.get_cable_info()# device infoelif t == 6:d, txt = self.get_device_info()# error infoelif t == 7:d, txt = self.get_error_info()# config watchdogelif t == 8:d, txt = self.config_watchdog()# refuseelif t == 9:d, txt = self.refuse()# verify requestelif t == 10:d, txt = self.verify_request()# verify responseelif t == 11:d, txt = self.verify_response() # test requestelse:d, txt = 0xffffffff, 'TODO...' s0 = self.bytepos[4][0]s1 = self.bytepos[dlen+3][1]# show data in hexself.putx(s0, s1, [3, ['H:%08x' % d, 'DATA']])# show data in commentself.putx(s0, s1, [8, [txt, txt]])# show data in full text stringself.text += ' - ' + txtdef decode_pkt(self):# Packet headerself.head = self.datapkt[0:4]self.putx(self.bytepos[0][0], self.bytepos[1][1],[2, ['HEAD:%04x' % ((self.head[0] << 8) | self.head[1]), 'HD']])self.puthead()# Cmdself.putx(self.bytepos[2][0], self.bytepos[2][1],[2, ['CMD:%02x' % (self.head[2]), 'CMD']])# Data lengthif self.data_len():self.putx(self.bytepos[3][0], self.bytepos[3][1], [2, ['LEN:%02x' % (self.head[3]), 'LEN']])# Decode data payloadself.decode_data_msg()# CRC check self.crc = self.datapkt[self.plen-1]ccrc = self.compute_crc8()if  self.crc != ccrc:self.putwarn('Bad CRC %02x != %02x' % (self.crc, ccrc), 'CRC!')self.putx(self.ss_block, self.es_block,[4, ['CRC:%02x' % (self.crc), 'CRC']])# Full text traceif self.options['fulltext'] == 'yes':self.putx(self.bytepos[0][0], self.es_block, [9, [self.text, '...']])def decode(self, ss, es, data):ptype, rxtx, pdata = dataself.ss_block, self.es_block = ss, es# just keep DATAif ptype != 'DATA':return# '0xAA' is the SOP of a ufcs packageif pdata[0] == 0xaa:self.putx(ss, es, [3, ['SOP:0xaa', 'SOP']])self.reset()return# append data to packetself.datapkt.append(pdata[0])# append byte pos (start byte, end byte )self.bytepos.append((ss, es))# ctrl_msg or data_msg?if self.dataidx == 3 :if (self.datapkt[1] & 1) == 1:self.plen = self.datapkt[3] + 5else:self.plen = 4self.dataidx += 1# packet is fullif self.dataidx == self.plen:self.decode_pkt()

总结

总的来说,UFCS简单实用,硬件用UART,软件开发容易,扩充功能方便,应该很有前景。个人对UFCS的发展壮大也贡献一点微薄之力。

UFCS中国的快充统一标准,共享PULSEVIEW 和 DSview协议分析软件相关推荐

  1. UFCS新一代融合快充协议的发展

    一.简述 UFCS--Universal Fast Charging Specification,新一代融合快充协议 2022年10月,中国通信标准化协会与电信终端产业协会联合在京召开移动终端融合快充 ...

  2. 加速户外电源快充普及!6大厂商率先推出双向快充芯片

    户外电源.便携式储能电源作为一种典型的清洁能源系统,近年来在欧美国家实现了大范围普及,并融入到了人们日常生活当中.国内方面,虽然目前户外电源的普及程度不如国外,但当下国家正在大力倡导新能源产业,作为绿 ...

  3. USB-PD快充和QC快充的区别

    USB-PD快充和QC快充的区别 (1)USB接口的区别 USB-PD快充是属于USB Type-C接口的一种充电协议,只能用于USB type-C接口. QC协议可以是我们常见的安卓Micro-B接 ...

  4. 三大快充技术详解 怎样才能发挥最大功效?

    三大快充技术详解 怎样才能发挥最大功效? 2016-08-23 10:38 在锂电池技术处于瓶颈时期,快充技术在近一年内快速普及,不光是旗舰机中采用了该技术,甚至在千元入门机内也可以看到,你要没个快充 ...

  5. 华为Nova9搭载鸿蒙OS采用4K录像镜头100W快充9月23日发布

    昨日华为官网正式宣布华为Nova 9系列将于9月23日举行发布会,将推出全新的华为Nova 9系列.消息一经公布便吸引了大批网友的关注,这款机型的外观和荣耀50系列 除了配色和logo略有差异外其他方 ...

  6. PD协议芯片,20W45WPD快充方案

    PD协议芯片,18w20W45WPD快充方案 一.基本信息 1.协议控制:它的电源电压是 VCC 脚,典型应用范围是从 3.3-21V.CC1/CC2/DP/DM 用于接到 type C 座子上,与手 ...

  7. iPhone用android充电头,iPhone 6s用什么充电头充电最快?安卓快充头可以混用吗?

    原标题:iPhone 6s用什么充电头充电最快?安卓快充头可以混用吗? 在锂电池技术没有大突破.新能源电池尚未应用到电子产品的环境下,续航问题一直困扰着广大手机用户.而快速充电技术的出现则让用户使用零 ...

  8. 充电器快充取电芯片XSP06Q+锂电池5A电流快速充电

    今天介绍一种新的使用充电器给锂电池快速充电的方式.特点是直接取充电器的9V/12V电压3-5A的电流给电池充电,不需要使用传统的5V升压到12V然后再降压充电.这样大功率充电,充电时间短,效率高. 使 ...

  9. USB Type-C转HDMI+USB3.0+PD快充方案扩展坞设计方案资料|带PD快充USB-C转HDMI+USB3.0多功能扩展坞电路参考|多功能扩展坞设计资料

    ALGOLTEK(安格) AG9311是一款高度集成的解决方案,通过USB Type-C将视频和音频从DisplayPort  alternate mode传输到HDMI输出,它可以轻松的将USB T ...

最新文章

  1. GitHub重大更新:在线开发上线,是时候卸载IDE了
  2. 编写OD插件将IDA中分析出来的函数名导入到OD中
  3. python爬虫吧-Python爬虫——抓取贴吧帖子
  4. mysql dba系统学习(1)mysql各版本编译安装
  5. 中关村Win11 32位微软原版ISO V2021.08
  6. 模为2的逆元是什么_两种求模m逆元的方法
  7. mysql8无法修改端口_mysql8.0.18 修改端口报错 Can't start server: Bind on TCP/IP port: Permission denied...
  8. android activity传值到dialog,android 自定义AlertDialog 与Activity相互传递数据
  9. Linux Iptables 语法大全
  10. V-rep学习笔记:机器人逆运动学数值解法(Cyclic Coordinate Descent Method)
  11. Python项目打包成exe文件
  12. 罗马音平假字复制_罗马音游戏id可复制app下载-罗马音大全可复制v2.1 免费版-速游网...
  13. java修改jpg图片、mp3音频文件的后缀名
  14. 索尼Xperia XZ1 Compact刷机,解锁BL,刷Twrp Recovery和Root教程
  15. Cousera Sequence,Time Series and PredictionWK1
  16. RabbitMQ 使用的AMQP模型解析
  17. excel几个表合成一张_【一分钟Excel】如何快速合并多个工作表
  18. html酷炫电子时钟效果,纯js实现电子时钟特效
  19. 微信服务号如何创建一个带参数的微信二维码?
  20. python分块处理功能_Python自然语言处理学习笔记之信息提取步骤分块(chunking)...

热门文章

  1. Windows10ISO英语 20h2原版系统镜像2021年5月份版
  2. (待拔草)关于电烙铁焊接时排放有毒气体的现象、解决方法
  3. 阿里云Serverless 极速搭建Hexo博客
  4. 创建orcl表空间和用户并给用户授权
  5. 网站为什么要css,在网页制作中为什么要使用CSS技术
  6. php志愿者服务平台的设计与实现
  7. HTML新年祝福抽奖小游戏,春节祝福抽奖小游戏代码
  8. 鱼C工作室c++(P43-44)链接和作用域
  9. 虚拟人,会成为品牌下一次逆势的解药吗?
  10. JSON解析(详细)