学习笔记

您所在的位置:网站首页 ps转usb接口 学习笔记

学习笔记

2024-07-14 16:02| 来源: 网络整理| 查看: 265

USB通信

  USB是一种支持热插拔的高速串行传输总线   USB体系包括“主机”、“设备”以及“物理连接”三个部分。其中主机是一个提供USB接口及接口管理能力的硬件、软件及固件的复合体,可以是PC,也可以是OTG设备,一个USB系统中仅有一个USB主机;设备包括USB功能设备和USB HUB,最多支持127个设备;物理连接即指的是USB的传输线在USB 2.0系统中,要求使用屏蔽的双绞线。

  从逻辑上可以分为功能层(应用软件)、设备层(电脑上的USB接口)和总线接口(线与两个设备之间的连接)层三个层次。其中功能层完成功能级的描述、定义和行为;设备级则完成从功能级到传输级的转换,把一次功能级的行为转换为一次一次的基本传输; USB总线接口层则处理总线上的Bit流,完成数据传输的物理层实现和总线管理。

   物理上,USB设备通过分层的星型总线连接到HOST,但在逻辑上HUB是透明的,各USB设备和HOST直接连接,和HOST上的应用软件形成一对一的关系。 各应用软件——功能设备对之间的通讯相互独立,应用软件通过USB设备驱动程序(USBD)发起IRQ请求,请求数据传输。主机控制器驱动程序(HCD)接收IRQ(数据传输)请求,并解析成为USB传输和传输事务(Transaction),并对USB系统中的所有传输事务进行任务排定(因为可能同时有多个应用软件发起IRQ请求)。主机控制器(Host Controller)执行排定的传输任务,在同条共享的USB总线上进行数据包的传输。

USB协议 域

是USB数据最小的单位,由若干位组成(至于是多少位由具体的域决定),域可分为七个类型:

同步域(SYNC) ,八位,值固定为0000 0001,用于本地时钟与输入同步;标识域(PID),山四位标识符+四位标识符反码构成,表明包的类型和格式,这是一个很重要的部分,这里可以计算出,USB的标识码有16种;地址域(ADDR) :七位地址,代表了设备在主机上的地址,地址:000 0000被命名为零地址,是任何一个设备第一次连接到主机时,在被主机配置、枚举前的默认地址,山此可以知道为什么一个USB主机只能接127个设备的原因。端点域(ENDP) ,四位,由此可知一个USB设备有的端点数量最大为16个。帧号域(FRAM),(ADDR+ENDP)11位,每一个顿都有一个特定的顿号,顿号域最大容量0x800,对于同步传输有重要意义(同步传输为四种传输类型之一)数据域(DATA) :长度为0~1023字节,在不同的传输类型中,数据域的长度各不相同,但必须为整数个字节的长度校验域(CRC):对令牌包和数据包(对于包的分类请看下面)中非PID域进行校验的一种方法。 在这里插入图片描述 NRZI编码:0变1不变,6个1补0 包

由域构成的包有四种类型,分别是令牌包、数据包、握手包和特殊包,前面三种是重要的包,不同的包的域结构不同

令牌包:可分为输入包、输出包、设置包和帧起始包(注意这里的输入包是用于设置输入命令的,输出包是用来设置输出命令的,而不是放据数的)其中输入包、输出包和设置包的格式都是一样的: SYNC+PID+ADDR+ENDP+CRC5 (五位的校验码) 帧起始包的格式: SYNC+PID+11位FRAM+CRC5 (五位的校验码)数据包:分为DATAO包利IDATA1包,当USB发送数据的时候,当一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATAO包和DATA1包交替发送,即如果第一个数据包是DATAO,那第二个数据包就是DATA1。但也有例外情况,在同步传输中(四类传输类型中之一),所有的数据包都是为DATAO, 格式:SYNC+PID+0-1023字节+CRC16。握手包:包括ACK, NAK, STALL 以及NYET 四种,其中ACK表示肯定的应答,成功的数据传输; NAK表示否定的应答,失败的数据传输,要求重新传输; STALL表示功能错误或端点被设置了STALL属性; NYET表示尚未准备好,要求等待。 格式: SYNC+PID 事务

分别有IN事务、OUT事务和SETUP事务三大事务,每一种事务都由令牌包数据包、握手包三个阶段构成,这里用阶段的意思是因为这些包的发送是有一定的时间先后顺序的,事务的三个阶段如下:

令牌包阶段:启动一个输入、输出或设置的事务数据包阶段:按输入、输出发送相应的数据握手包阶段:返回数据接收情况,在同步传输的IN和OUT事务中没有这个阶段,这是比较特殊的。

事务的三种类型如下(以下按三个阶段来说明一个事务) :

IN事务:   令牌包阶段——主机发送一个PID为IN的输入包给设备,通知设备要往主机发送数据;   数据包阶段——设备根据情况会作出三种反应(要注意:数据包阶段也不总是传送数据的,根据传输情况还会提前进入握手包阶段); 1)设备端点正常,设备往入主机里面发出数据包(DATAO与DATA1交替); 2)设备正在忙,无法往主机发出数据包就发送NAK无效包,IN事务提前结束,到了下一个IN事务才继续; 3)相应设备端点被禁止,发送错误包STALL包,事务也就提前结束了,总线进入空闲状态。   握手包阶段——主机正确接收到数据之后就会向设备发送ACK包。OUT事务:   令牌包阶段——主机发送一个PID为OUT的输出包给设备,通知设备要接收数据;   数据包阶段——比较简单,就是主机会给设备送数据,DATAO与DATA1交替;   握手包阶段——设备根据情况会作出三种反应;   1)设备端点接收正确,设备往入主机返回ACK,通知主机可以发送新的数据,如果数据包发生了CRC校验错误,将不返回任何握手信息;   2)设备正在忙,无法接收主机发出数据包就发送NAK无效包,通知主机再次发送数据;   3)相应设备端点被禁止,发送错误包STALL包,事务提前结束,总线直接进入空闲状态。SETUP事务:   令牌包阶段——主机发送一个PID为SETUP的输出包给设备,通知设备要接收数据;   数据包阶段——比较简单,就是主机会设备送数据,注意,这里只有一个固定为8个字节的DATAO包,这8个字节的内容就是标准的USB设备请求命令(共有11条);   握手包阶段——设备接收到主机的命令信息后,返回ACK,此后总线进入空闲状态,并准备下一个传输(在SETUP事务后通常是一个IN或OUT事务构成的传输)。 传输

传输由OUT、IN、SETUP事务其中的事务构成,传输有四种类型,中断传输批量传输、同步传输、控制传输,其中中断传输和批量转输的结构一样,同步传输有最简单的结构,而控制传输是最重要的也是最复杂的传输。

中断传输:由OUT事务和IN事务构成,用于键盘、鼠标等HID设备的数据传输中;批量传输:由OUT事务和IN事务构成,用于大容量数据传输,没有固定的传输速率,也不占用带宽,当总线忙时,USB会优先进行其他类型的数据传输,而暂时停止批量转输;同步传输:由OUT事务和IN事务构成,有两个特殊地方,第一,在同步传输的IN和OUT事务中是没有返回包阶段的;第二,在数据包阶段所有的数据包都为DATAO;控制传输:最重要的也是最复杂的传输,控制传输由三个阶段构成(初始设置阶段、可选数据阶段、状态信息步骤),每一个阶段可以看成一个传输,也就是说控制传输其实是由三个传输构成的,用来于USB设备初次加接到主机之后,主机通过控制传输来交换信息,设备地址和读取设备的描述符,使得主机识别设备,并安装相应的驱动程序,这是每一个USB开发者都要关心的问题。 硬件设计

  USB协议比较麻烦,一般选取厂家封装好的芯片使用。 以FT232为例,设备连接的简化图如下图所示。 在这里插入图片描述

FT232

  用FPGA驱动FT232执行USB协议,故程序设计时,只需设计FPGA驱动程序即可。程序的时序图如下图所示。 在这里插入图片描述   RD时序必须至少晚于DATA 一个时钟周期。

  程序的信号流图如下图所示。 在这里插入图片描述

module usb_loopback_top ( input usb_clk_60m, //FT232输出的60M时钟 input sys_rst_n, //系统复位 ,低电平 input usb_rxf_n, //FT232H数据FIFO可读指示信号 input usb_txe_n, //FT232H数据FIFO可写信号 output usb_oe_n, //FT232H数据输出使能 output usb_rd_n, //FT232HFIFO读使能信号 output usb_wr_n, //FT232HFIFO写使能信号 output usb_siwu_n, //send immediate/wake up inout[7:0] usb_data //FT232 数据总线 ); wire [7:0] fifo_data_in; //从FT232进到FPGA的数据 wire [7:0] fifo_data_out; //从FPGA输出到FT232的数据 wire wr_en; //FPGA FIFO写使能 wire rd_en; //FPGA FIFO读使能 wire full; //FPGA FIFO写满信号 wire empty; //FPGA FIFO读空信号 assign usb_siwu_n = 1'b1; //立即发送,唤醒 //USB 同步FIFO读写 usb_rw u_usb_rw( .usb_clk_60m (usb_clk_60m ), .sys_rst_n (sys_rst_n ), .usb_rxf_n (usb_rxf_n ), .usb_txe_n (usb_txe_n ), .usb_oe_n (usb_oe_n ), .usb_rd_n (usb_rd_n ), .usb_wr_n (usb_wr_n ), .fifo_wr_en (wr_en ), .fifo_rd_en (rd_en ), .empty (empty ), .usb_data (usb_data ), .fifo_data_in (fifo_data_in ), .fifo_data_out (fifo_data_out ) ); //FPGA FIFO调用 fifo_generator_0 u_fifo_generator_0 ( .clk(usb_clk_60m), // input wire clk .srst(1'b0), // input wire srst .din(fifo_data_in), // input wire [7 : 0] din .wr_en(wr_en), // input wire wr_en .rd_en(rd_en), // input wire rd_en .dout(fifo_data_out), // output wire [7 : 0] dout .full(full), // output wire full .empty(empty) // output wire empty ); endmodule module usb_rw( input usb_clk_60m, //FT232输出的60M时钟 input sys_rst_n, //系统复位 ,低电平 //FT232H input usb_rxf_n, //FT232H数据FIFO可读信号 input usb_txe_n, //FT232H数据FIFO可写信号 output reg usb_oe_n, //FT232H数据输出使能 output usb_rd_n, //FT232H FIFO读使能信号 output usb_wr_n, //FT232H FIFO写使能信号 inout [7:0] usb_data, //FT232H 双向数据总线 //FPGA FIFO output fifo_wr_en, //FPGA FIFO写使能信号 output fifo_rd_en, //FPGA FIFO读使能 input empty, //FPGA FIFO读空信号 input [7:0] fifo_data_out, //FPGA FIFO数据输出 output [7:0] fifo_data_in //FPGA FIFO数据输入 ); localparam IDLE = 0; //FT232H 空闲 localparam READ = 1; //FT232H 读状态,此时数据从FT232H发送到FPGA localparam WRITE = 2; //FT232H 写状态,此时数据从FPGA发送到FT232H reg[3:0] state; //读写状态 reg usb_oe_n_d0; //usb_oe_n下一拍 assign usb_rd_n = ((usb_oe_n_d0 == 0) && (usb_oe_n == 0 ))?1'b0 : 1'b1; //在usb_oe_n为低且在usb_oe_n下一拍也为低时拉低usb_rd_n,其他时候为高 assign fifo_data_in = (state == READ)? usb_data:8'hzz; //FT232H读状态,将USB数据总线上的值赋给FIFO数据输入,其他时候赋值为高阻态 assign usb_data = (state == WRITE)? fifo_data_out: 8'hzz; //在FT232H写状态,将FIFO的数据输出赋值给将USB数据总线,其他时候为高阻态 assign usb_wr_n = ((state == WRITE) && (usb_txe_n == 0 )&& (empty == 0))?1'b0 : 1'b1; //在FT232H写状态,且usb_txe_n为低,且FPGA FIFO 不空时,使能FT232H FIFO写 assign fifo_wr_en = ((usb_oe_n_d0 == 0) && (usb_rxf_n == 0 ))?1'b1 : 1'b0; //在usb_oe_n下一拍也为低,且usb_rxf_n也为低时使能FIFO写 assign fifo_rd_en =((state == WRITE) && (usb_txe_n == 0 )&& (empty == 0))?1'b1 : 1'b0; //在FT232H写状态,且usb_txe_n也为低时,且FPGA FIFO 不空时,使能FIFO读 //产生FT232H数据输出使能usb_oe_n always@(posedge usb_clk_60m or negedge sys_rst_n)begin if(!sys_rst_n) usb_oe_n


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3