USB转多路UART - USB 基础
一、 前言
断断续续做了不少USB相关开发,但是没有系统去了解过,遇到问题就很被动了。做这个USB转UART的项目就是,于是专门花了一天的时间学习USB及CDC相关,到写这文章时估计也忘得差不多了,趁项目收尾阶段记录一下,方便后面翻阅。
本文内容(包括图片)绝大多数来源网络,侵删。参考链接:
USB官网
USB通用串行总线基础知识详述
USB端点和传输协议(数据包、事物)详解
二、 总线

USB历代接口
经过多年发展,USB速率越来越高,总线由最初4根线,半双工发展到多根线,全双工。本文是基于 USB 2.0 版本,记录最初最基础的知识,了解了这些基础,后面的版本就很容易了。

USB总线

USB全速(高速)接线图
| 信号名称 | 说明 |
|---|---|
| Vbus | 电源,DC 5V |
| D+ | 叉分信号线,正 |
| D- | 叉分信号线,负 |
| GND | 电源地 |
由上面可知,USB 2.0 只有4根线,两根数据线是高速串行叉分线,半双工。电源线用来主机给从设备供电,最大500mA, 5V * 500mA = 2.5W, 功率不是很高。后来的快速充电技术要么提升了电压和电流,例如9V * 2A = 18W, 再后来USB接口增加了电源和数据线的数量,传输速率和供电功率都大大提升。
数据编解码和位填充
USB采用NRZI(非归零编码)对发送的数据包进行编码 。输入数据0, 编码成“电平翻转” ;输入数据1, 编码成“电平不变” ;(NRZI遇0翻转,遇1不变)。

USB NRZi编码格式
三、 USB总线系统中的设备
可以分为三种类型:
- 主机: 只能有一个,管理USB系统;
- 集线器(USB HUB): 用来扩展设备;
- 设备: 终端设备,如下图的鼠标键盘打印机;

USB设备拓扑
四、 端点(Endpoints)
在USB规范中,设备端点是唯一可寻址可通信的基本单元,端点是有通信方向的。物理上一个USB总线(4根线)连接一个设备终端,这个设备终端逻辑上可以有多个接口,每个接口可以有多个端点,从而在主机的系统上看该设备终端可能有多个设备。例如本项目,一个USB口扩展7个UART设备。
端点0: 每个终端设备肯定会有一个端点0,用于刚连接到主机时的初始化和枚举。想象一下,一个USB设备终端可能有10个8个端点,刚插到主机时,主机并不清楚,所以规定了一定要有一个端点0,主机最开始只与端点0通信,然后把其它的设备,接口,端点枚举出来。
端点类型
USB规范定义了四种端点类型:
- 控制端点: 收发控制信息,也可以传输数据。
- 中断端点: 用于传输少量的数据,实时时效性比较好,例如键盘鼠标。
- 批量端点: 用于传输大批量数据,实时时效性没要求,例如U盘文件传输。
-
等时端点: 连续,实时的传输,例如音频。

不同端点类型比较
五、 数据传输
USB通信包含一系列的帧,USB在2.0时代,分为低速设备(1.5Mbps),全速设备(12Mbps)和高速设设备(480Mbps).这些设备使用的帧的时间间隔是1±0.0005ms,而对于高速设备,又将每个帧分成了8个微帧,这样每个微帧的时间间隔变成了125±0.0625us。
每一帧包含一个起始帧(Start of Frame, SOF), 然后是若干个事务(Transaction)。每个事务由一系列数据包(packet)组成。每个数据包以同步标识(SYNC)开始,以结束标识(EOP)结束。有三种类型的包:令牌包,数据包,握手包。帧,事务,包关系如下图:

USB帧事务数据包关系图
包(package)
包是USB系统中信息传输的基本单元,所有数据都是经过打包后在总线上传输的。USB包由五部分组成,即同步字段(SYNC)、包标识符字段(PID)、数据字段、循环冗余校验字段(CRC)和包结尾字段(EOP),包的基本格式如下:
同步域(SYNC)
由8位/32位组成,作为每个数据包的前导,用来产生同步作用,使USB设备与总线的包传输率同步,它的数值固定为000000001。作用:
- 通知USB串行接口引擎数据要开始传输;
- 同步主机和设备之间的时钟。
标识符字段(PID)
包标识符PID是用来标识一个包的类型。PID共有8位,目前USB协议仅使用4位(PID0 - PID3),另外4位(PID4 - PID7)是PID0 - PID3的取反,用来校验PID。传输的顺序为PID0,PID1,PID2,PID3,...,PID7。
令牌包(token packet, PID1~0为01)、数据包(data packet, PID1~0为11)、握手包(handshake packet, PID1~0为10)、特殊包(special packet, PID1~0为00):

令牌类型.
特殊包是一些在特殊场合使用的包。总共有4种:PRE、ERR、SPLIT和PING。其中PRE、SPLIT和PING是令牌包,ERR是握手包。这里不打算展开讲。
帧传输过程
如下图,所有通信都由主机定时发起,帧头一定是SOF,然后包含多个事务,每个事务有多个包,每个包都是SYNC开头,EOP结束。要注意每个事务是有应答的,即一个帧里面数据传输的方向是不断切换的。下图中,主机先发一个SOF,然后发一个SETUP包,这个包带有DATA0,设备端收到后返回ACK。然后主机连续发了3个IN令牌包,前2个从设备端都回复NAK,表示无数据上传。第3个IN回复数据了,主机收到后回复了ACK。然后下一帧,主机发送SOF后,发了个OUT令牌包,跟着又发送了数据DATA0,从设备端回复ACK。

USB帧时间数据传输过程.
举一个实际的例子,全速USB传输每一个帧为1ms。首先会发送一个SOF包(帧起始包),此时USB主机检测到总线没有事务可以传输,则总线进入idel(空闲状态),这里的空闲时间996.917us,3us左右是EOP占用的时间。
5个idle后,有事务了,分析一下这次传输。同样的首先会发送一个SOF包(帧起始包),等了176.817us后,紧接着USB主机会发送一个SETUP令牌包,收到ACK后继续SETUP包和数据包,从设备端也返回了ACK包。下一个是IN的事务,不详细讲。两个事务传输完成后,主机检测到没有事务了,总线同样会进入空闲状态,这里空闲了478.767us。所有的时间开销加起来差不多1ms。然后后面又有几个没有事务的帧。

全速USB帧内容
实际开发中,当MCU做从设备时,一般MCU的软件架构都是在中断中响应主机端各种交互,例如可配置每个SOF都产生一个中断,或者收到SETUP包后产生中断,在中断中处理相应事务,软件不能做太耗时的处理,一般产生事件标志然后异步处理。数据IN是预先拷贝到指定的缓存(或者DMA缓存),当主机轮询时,硬件自动上传,没有数据就回复NAK。数据OUT也是硬件先接收到指定的缓存(或DMA缓存),回复ACK,接收完后产生中断,通知软件处理。
(END)
相关文章:
USB转多路UART - USB 基础
一、 前言 断断续续做了不少USB相关开发,但是没有系统去了解过,遇到问题就很被动了。做这个USB转UART的项目就是,于是专门花了一天的时间学习USB及CDC相关,到写这文章时估计也忘得差不多了,趁项目收尾阶段记录一下&am…...
接近50个实用编程相关学习资源网站
Date: 2024.07.17 09:45:10 author: lijianzhan 编程语言以及编程相关工具等实用性官方文档网站 C语言文档:https://learn.microsoft.com/zh-cn/cpp/c-languageMicrosoft C、C和汇编程序文档:https://learn.microsoft.com/zh-cn/cppJAVA官方文档&#…...
在数据操作中使用SELECT子句
目录 一、INSERT 语句中使用 SELECT子句 二、UPDATE 语句中使用 SELECT子句 三、DELETE 语句中使用 SELECT子句 一、INSERT 语句中使用 SELECT子句 在 INSERT 语句中使用 SELECT子句,可以将一个或多个表或视图中的数据添加到另外一个表中。使用 SELECT 子句还可以…...
Golang | Leetcode Golang题解之第274题H指数
题目: 题解: func hIndex(citations []int) int {// 答案最多只能到数组长度left,right:0,len(citations)var mid intfor left<right{// 1 防止死循环mid(leftright1)>>1cnt:0for _,v:range citations{if v>mid{cnt}}if cnt>mid{// 要找…...
区块链技术在智能家居中的创新应用探索
随着物联网技术的发展和智能家居市场的蓬勃发展,区块链技术作为一种去中心化的数据管理和安全保障技术,正在逐渐引入智能家居领域,并为其带来了新的创新应用。本文将探讨区块链技术在智能家居中的具体应用场景、优势以及未来发展方向。 智能家…...
无需业务改造,一套数据库满足 OLTP 和 OLAP,GaiaDB 发布并行查询能力
在企业中通常存在两类数据处理场景,一类是在线事务处理场景(OLTP),例如交易系统,另一类是在线分析处理场景(OLAP),例如业务报表。 OLTP 数据库擅长处理数据的增、删、改,…...
PHP 表单验证:邮件和URL
PHP 表单验证:邮件和URL 在Web开发中,表单验证是一个至关重要的环节,它确保了用户输入的数据的有效性和安全性。特别是在处理邮件地址和URL时,准确的验证尤为重要。本文将详细介绍如何使用PHP来验证表单中的邮件地址和URL。 邮件…...
前端八股文 路由的懒加载
为什么会有 路由的懒加载 在现代单页应用(SPA)的开发中,路由懒加载是一种提升应用性能的关键技术。通过按需加载组件,而非在应用启动时一次性加载所有模块,可以显著减少初次加载时间和资源消耗。本文旨在深入探讨前端…...
HarmonyOS Web组件(二)
1. HarmonyOS Web组件 官方文档 1.1. 混合开发的背景和好处 混合开发(Hybrid Development)是一种结合原生应用和Web应用的开发模式,旨在同时利用两者的优势。随着移动应用需求的多样化和复杂化,单一的开发方式往往难以满足所有…...
HarmonyOS应用开发者高级认证,Next版本发布后最新题库 - 单选题序号2
基础认证题库请移步:HarmonyOS应用开发者基础认证题库 注:有读者反馈,题库的代码块比较多,打开文章时会卡死。所以笔者将题库拆分,单选题20个为一组,多选题10个为一组,题库目录如下,…...
基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用
目录 专题一、深度学习发展与机器学习 专题二、深度卷积网络基本原理 专题三、TensorFlow与Keras介绍与入门 专题四、PyTorch介绍与入门 专题五、卷积神经网络实践与遥感图像场景分类 专题六、深度学习与遥感图像检测 专题七、遥感图像检测案例 专题八、深度学习与遥感…...
叶再豪降龙精英课程总结
文章目录 1.思维认知1.1 稻盛和夫成功公式1.2 龙头主升模式1.3 龙头主升-两种路径1.4 股市新手的炒股思路1.5 龙头案例1.6 降龙心法 2.情绪周期2.1 情绪周期2.1 情绪演绎周期2.2 情绪的四个部分2.2.1 指数的情绪周期2.2.3 热点情绪周期2.2.4 热点情绪演绎周期2.2.5 大热点支线2…...
算法 - 查找算法(顺序、折半、红黑树、AVL树、B+树、散列)
查找 顺序查找 查找算法原理: 顺序查找是一种简单的查找方法,从数组的第一个元素开始,依次比较每个元素,直到找到目标元素或者数组结束为止。 实现步骤: 从数组的第一个元素开始。逐一比较数组中的元素与目标值。如…...
TCP与UDP网络编程
网络通信协议 java.net 包中提供了两种常见的网络协议的支持: UDP:用户数据报协议(User Datagram Protocol)TCP:传输控制协议(Transmission Control Protocol) TCP协议与UDP协议 TCP协议 TCP协议进行通信的两个应用进程:客户端、服务端 …...
媲美Midjourney-v6,Kolors最新文生图模型部署
Kolors模型是由快手团队开发的大型文本到图像生成模型,专门用于将文本描述转换成高质量的图像。 Kolors模型支持中英文双语输入,生成效果与Midjourney-v6相媲美,能够处理长达256个字符的文本输入,具备生成中英文文字的能力。 Ko…...
深度学习程序环境配置
深度学习环境配置 因为之前轻薄本没有显卡跑不起来,所以换了台电脑重新跑程序,故记录一下配置环境的步骤及常见错误 本人数学系,计算机部分知识比较匮乏,计算机专业同学可以略过部分内容 深度学习环境配置 深度学习环境配置 CUD…...
【STM32 HAL库】全双工I2S+双缓冲DMA的使用
1、配置I2S 我们的有效数据是32位的,使用飞利浦格式。 2、配置DMA **这里需要注意:**i2s的DR寄存器是16位的,如果需要发送32位的数据,是需要写两次DR寄存器的,所以DMA的外设数据宽度设置16位,而不是32位。…...
【Spring Boot】网页五子棋项目中遇到的困难及解决方法
目录 一、HikariPool-1 - Starting异常二、Invalid bound statement (not found)异常三、The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary异常四、The server time zone value时区报错异常五、补充知识点…...
营销策划方案模板
这应该是目前最详细最完整的营销策划方案模板,营销公司内部都在使用的标准版本,你可以根据自己的营销内容直接填入这个模板,很快就能写好一份至少80分的营销策划方案。 如果暂时用不到也可以先收藏,以备不时之需。 废话不多说&a…...
Python入门基础教程(非常详细)
现在找工作真的越来越难了!今年更是难上加难 前几天在网上刷到这样一条热搜: #23岁找工作因年龄大被HR拒绝了# 是这个世界疯了还是我疯了? 合着只想要有20年以上工作经验的应届毕业生是吧 这好像就是现在的就业市场现状:“35岁…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
