文章目录
- 问题
- 1、为什么一接入 USB 设备, PC 机就能发现它?
- image.png
- USB 设备刚接入 PC 时,还没有编号;那么 PC 怎么把"分配的编号"告诉它?
- 硬件框架
- 2、软件框架
- usb发信号
- usb信号
- 位填充+反向不归零编码
- 发送/接收数据的过程
- 包的格式
- pid名
- 事务的组成:
- 有哪些 USB 包?
- 传输:
- 设备描述符
- 是什么
- 具体例子
- 移植usb
- 移植过程中出现的问题
- 使用freertos来改造收发函数
- 用到信号量,二进制信号量
- 用到队列来放入数据后,从对列中读数据
- 如何使用
- 注意:
5v电源\GND地\差分信号线;
一共4条线;
中间两条差分信号来传输信号;
问题
1、为什么一接入 USB 设备, PC 机就能发现它?
PC 的 USB 口内部, D-和 D+接有 15K 的下拉电阻,未接 USB 设备时为低电平。 USB设备的 USB 口内部, D-或 D+接有 1.5K 的上拉电阻;它一接入 PC,就会把 PC USB 口的 D-或D+拉高,从硬件的角度通知 PC 有新设备接入 ;
如图画出的这个引脚的电压就被拉高了,就有信号的跳变;
2、PC 机上接有非常多的 USB 设备,怎么分辨它们?
每一个 USB 设备接入 PC 时, USB 总线驱动程序都会给它分配一个编号。 PC 机想访问某个 USB 设备时,发出的命令都含有对应的编号(地址) ;
USB 设备刚接入 PC 时,还没有编号;那么 PC 怎么把"分配的编号"告诉它?
新接入的 USB 设备的默认编号是 0,在未分配新编号前, PC 使用 0 编号和它通信。
硬件框架
hub表示可以接扩展的usb接口,func就是接具体的功能的usb接口;
最多接到tiger7之后只能是func了;
1、USB Host:它跟处理器相连,处理器通过 USB Host 跟各类 USB 设备通信。 USB Host 中集成有一个 root hub ;
2、USB Device:
这分为两类设备
a. Hub:用来扩展 USB 接口
b. Function:就是普通的 USB 设备,比如 U 盘、声卡等
2、软件框架
APP可以通过usb设备驱动程序访问usb设备,也可以绕过设备驱动直接使用host程序来访问usb设备
高速模式
先打开全速模式;
设备给hub发送高速模式的信号;
hub收到信号后发出高速模式的信号后,device收到就行了;
hub port是下拉电阻;
device是下拉电阻;
设备端是上拉电阻,hub是下拉电阻
usb发信号
usb信号
对比I2c和spi通信,这两个是两条线,时钟线SCK和数据线SDA
这种是同步信号
usb是一条通道,先发一段信号,接收方收到信号时能计算出周期,从而按照这个周期来接收
位填充+反向不归零编码
反向不归零编码:如下,到下一个波形发生变化就是0,不变就是1;
位填充:连续发送 6 个 1 后面会插入 1 个 0 ;
发送/接收数据的过程
包的格式
1.SOP:用来表示包的起始
2.SYNC:用来同步时钟
3.PID:表示包的类型
4.地址:在 USB 硬件体系中,一个 Host 对应多个 Logical Device,那么 Host 发出的包,如何确定发给谁?a. 发给所有设备:包里不含有设备地址b. 发给某个设备:包里含有设备地址、端点号
5.帧号、数据等跟 PID 相关的内容
6.CRC 校验码
7.EOP:用来表示包的结束
pid名
host发送命令包、数据包
device的握手包
接收:
host发命令包
device发送数据包
host发送握手包
事务的组成:
事务由包组成、包由域组成(域就是上图的sop域、sync域等等)、域由bit组成
事务分三个阶段:命令、数据、握手
有哪些 USB 包?
根据包数据里的 PID 的 bit1, bit0 可以分为 4 类:
令牌包(Token): 01B
数据包(Data): 11B
握手包(Handshake): 10B
特殊包(Special): 00B
传输:
批量传输,就是批量事务传输
中断传输,用中断事务,必须周期性的发起这些传输
实施传输,没有握手阶段,只用命令和数据阶段
控制传输:
set up;set up 三个事务:token \data\ hand shake
data stage:一个或者多个批量传输,每个批量传输里面都有token \data\ hand shake,这三个阶段
status stage:一个批量事务
具体例子:
批量传输
控制传输
第二阶段是批量传输
第三阶段是状态阶段
设备描述符
是什么
使用设备描述符来描述设备、配置、接口、端点;
有设备描述符、配置描述符、接口描述符、端点描述符;
所谓描述符,就是一些格式化的数据,用来描述信息;
在linux里面看是这样的
例如usb手册中端点描述符,各个数据的含义如下
具体例子
0x80是bit7置位1
1000 0000
从bit0开始算的,所以是bit7,第8个数字是1;
流程
1、获取设备描述符
2、设置地址;host把地址发个设备,这个只用setup阶段和data阶段前两个阶段
3、获取设备描述符;使用新地址,重新读取设备描述符,设备描述符长度是 18
4、获取配置描述符;它传入的长度是 255,想一次性把当前配置描述符、它下面的接口描述符、端点描述符全部读出来
5、设置配置
移植usb
没有thread,需要自己移植过来配置;
移植过程不详细展开;
需要添加宏开关: UX_INCLUDE_USER_DEFINE_FILE ;
表示去用用户定义的那些头文件;
4层对应四个group文件
看一下描述符的厂商id
usb有接收和输出两个端点
assignEp
移植过程中出现的问题
(6): warning: ISO C99 requires whitespace after the macro name [-Wc99-extensions]#define STM32H563xx.UX_INCLUDE_USER_DEFINE_FILE 1
解决办法:
这边应该是空格,我敲了一个.所以报错了
使用freertos来改造收发函数
这函数只是启动传输,他会立刻返回;
用到信号量,二进制信号量
SemaphoreHandle_t xBinarySemaphore;
发送:
1、先定义出来
2、创建
3、等待give后就take
用到队列来放入数据后,从对列中读数据
1、定义队列
2、创建队列
(200,1)200个数据,一个数据1个字节
3、写入数据
4、从队列中读数据,单独写一个函数
当pc把数据发给开发板子后
read就会被调用
如何使用
定义出来,直接用getchar
注意:
读队列和写队列都要有保护机制:
就是if(队列),队列不为空才去读,为空则返回-1表示错误信息;不然就无法识别usb设备
函数添加保护机制,如果队列为空就要报错