2023年6月22日发(作者:)
毕 业 设 计 [论 文]
题 目: 基于STM32的USB虚拟串口
学 院:
专 业:
姓 名:
学 号:
指导老师:
完成时间: 2014年5月19 日
河南城建学院本科毕业设计(论文) 中文摘要
摘 要
USB接口由于支持热插拔和标准统一等特点得到了广泛应用,越来越多的电脑设备开始采用USB接口进行数据的传输,而如何在不改变现有应用软件的情况下,将设备移植到USB接口成为人们研究的热门。
论文以USB通信设备类中的抽象控制模型为基础,研究了通信设备类及实现虚拟设备的原理,设计并实现了基于通信设备类的虚拟串口驱动程序。
论文研究设计了基于通信设备类的虚拟串口驱动程序的结构和实现方案,程序主要由通信命令转换和数据传输两部分构成,通信命令转换符合通信设备类中抽象控制模型的规范,数据传输部分对现有虚拟串口的实现技术进行了改进。论文的主要工作如下:
1) 研究了USB协议的请求和传输模式,分析了通信设备类实现虚拟设备的方案。
2) 给出了一种符合通信设备类中抽象控制模型的虚拟串口实现方案。该方案提供了一种基于通信设备类开发虚拟设备的模板,对设计中的诸多问题进行了详细的说明,并改进了虚拟串口驱动程序中数据的处理流程。
3) 将改进后的数据处理流程应用于虚拟串口的实现中,生成了一种基于通信设备类的稳定、高速的虚拟串口。最后,在串口测试软件下对虚拟串口驱动程序进行了测试,达到了预期目标。
关键字: 通讯设备类;枚举过程;虚拟串口程序;抽象控制模型
1 河南城建学院本科毕业设计(论文) 英文摘要
Abstract
USB interface supports plug and play which has unified standards, so it has a wide range of applications. More and more computer device use USB interface to transfer data, so
how to make many old deaves to support USB interface without changing current application is becoming the hot field.
USB Communication Device Class and it's abstract control model are studied, principles of Communication Device Class and implementation techniques of abstract device are also analyzed in the thesis. On the basis of this, design and implementation of virtual serial
port driver based on Communication Device Class are given.
The overall structure and implementation scheme of virtual serial port driver based on CDC are designed. The virtual serial port driver is made up of two parts which are communication command transfer module and data transmission module. The communication command transfer module satisfies the specification of abstract control model, and the data transfer part improves the technique of current virtual serial port. The main works in the thesis
are as follows:
1) The request and transfer model for USB protocol are studied, and the implementation techniques of virtual serial port are analyzed.
2) The implementation scheme of virtual serial port driver that satisfy abstract control mode in CDC is graven. A new template for the development of virtual serial port based on CDC is brought out, and it describes some issues for the virtual serial port driver in details, at the same time, the processing steps for virtual serial port driver is improved.
3) The improved data processing steps for virtual serial port driver is applied in the implementation of ritual serial port driver, and a stable, high-speed virtual serial port is made. At last, the test for the virtual serial port driveon ActiveSync is given, and the test result show that it's function is achieved the requirement goals.
Keywords: Communication Device Class ;Enumeration Process;
Virtual Serial Port Driver ;Abstract Control Model
2 河南城建学院本科毕业设计(论文) 目录
目 录
摘 要...................................................................................................................................... 1
Abstract .................................................................................................................................... 2
目 录...................................................................................................................................... 3
第1章 绪论 ............................................................................................................................. 4
1.1 USB虚拟串口设计背景及其意义 ................................................................................ 4
1.2 USB虚拟串口设计研究方法及目标 ............................................................................. 4
1.3 USB虚拟串口设计国内外研究现状 ............................................................................. 5
第2章 USB及串口简单介绍.................................................................................................... 7
2.1 USB简介 ................................................................................................................... 7
2.2 串口简介 .................................................................................................................... 7
2.3 USB虚拟串口简介 ..................................................................................................... 8
第3章 USB和USB CDC协议 ................................................................................................. 9
3.1 通用串行总线USB ..................................................................................................... 9
3.1.1 USB协议相关知识介绍 .................................................................................... 9
3.1.2 USB协议枚举过程分析 .................................................................................. 10
3.2 USB CDC协议........................................................................................................ 11
3.3 USB通信过程 .......................................................................................................... 12
第4章 虚拟串口的实现 ......................................................................................................... 15
4.1 串口的工作原理........................................................................................................ 15
4.2 USB虚拟串口设计 ................................................................................................... 16
4.2.1 STM32 USB部分说明 .................................................................................... 16
4.4.2 USB电路连接 ................................................................................................ 16
4.2.3 虚拟串口程序设计.......................................................................................... 17
第5章 结论 ........................................................................................................................... 20
参考文献 ................................................................................................................................ 22
致 谢.................................................................................................................................... 23
附录:.................................................................................................................................... 24
3 河南城建学院本科毕业设计(论文) 绪论
第1章 绪论
1.1 USB虚拟串口设计背景及其意义
USB是一种统一的传输规范,但是接口有许多种,最常见的就是咱们电脑上用的那种扁平的,这叫做A型口,里面有4根连线,根据谁插接谁分为公母接口,一般线上带的是公口,机器上带的是母口。现在的很多电子设备都采用USB接口来设计,使得各个设备之间的相互通信更为方便和快捷。然而越来越多的设备开始使用USB接口,对USB协议也是一个很大的挑战。一般在传输数据的接口与通信协议是一一对应的,而由于接口的不同,不太外设使用的协议也不同。
USB接口具有使用简单、支持热插拔、传输速度快、便于端口扩展等特点,在高速实时数据传输系统、数据采集系统等工业领域得到了广泛的应用。现代个人计算机往往都带有四个以上的USB接口。然而在现代嵌入式系统和工业现场中,最常用的标准外设是异步串行通信接口(串口),如何在没有串口的情况下得到串口数据,并完成数据传输成为一个亟待解决的问题。
首先,越来越多带USB接口的器件涌现出来,如带USB接口的单片机,或独立的USB接口器件,而这些器件的成本已经很接近使用RS232电平转换芯片所带来的成本。其次,市场上也出现了一些USB转串口的芯片或者USB转串口数据线,它们的一头为串口,另一头为USB接口,在其内部完成串口到USB协议的转换。它们通过USB接口连接到个人计算机后,操作系统识别的却是一个串口设备,这说明USB接口对于传统的串口调试工具和用户基于串口的应用程序是公开的,开发者完全不用更改PC端的调试和应用程序。但这些器件的USB类不属于标准的USB设备类,因此需要在操作系统上安装必要的驱动。另外由于不是操作系统自带的设备驱动,而且通信经过了多次转换,当调试遇到问题时常常无法确定是串口出了问题还是USB出了问题。这些问题限制了USB转串口器件的应用。
设备通信类(Communication Device Class)是USB组织定义的一类专门给各种通信设备使用的USB子类,是一种可以实现虚拟串口通信的协议。CDC类对实现USB接口和串口之间的转换提供了一个很好的解决办法。而且CDC类是USB的一个子类,操作系统默认提供此类驱动,故可以解决USB转串口类器件传输不稳定的问题。
1.2 USB虚拟串口设计研究方法及目标
本文所讲述的USB虚拟串口是采用STM32来实现的。STM32系列控制器具有高性能、低成本、低功耗的特点,它自身带的USB模块符合USB2.0规范和OTG1.3 4 河南城建学院本科毕业设计(论文) 绪论
规范,支持全速12Mbps和低速1.2Mbps两种模式。而且STM32官方封装了很多库函数,对于编写USB驱动节省了很多时间。本文在理解USB体系结构并深入研究USB CDC协议的基础上,通过分析USB枚举过程在STM32平台上实现了USB虚拟串口,通过虚拟串口达到了USB与串口通信的预期目的。
1.3 USB虚拟串口设计国内外研究现状
国内研究现开发设备控制芯片较难,中国台湾地区的许多公司可以生产这种转换的设备,并提供功能齐全的开发接口和文档说明。国内集成电路的设计开发公司的能力还有限,限于提供不太复杂的应用及单一产品中,并且在国内的市场占有率还很小,目前正处于蓬勃发展的阶段。
当前USB已经成为个人计算机(PC)必备接口,各种PC电子消费产品也逐渐配置了这种标准的接口。为了顺应这种情况,对于使用串口开发应用的人员需要提供串口与USB之间的转接组件,使串口数据和及其控制信号可以在USB总线上进行传输。
USB和串口之间的转换实现,有硬件实现和软件实现两种。硬件实现一般需要设计专用的设备控制芯片。开发设备控制芯片较难,需要有专业的硬件设计及编程能力,为了提高USB和串口转换的开发效率,国外有很多公司都开发出了相应的控制芯片。中国台湾地区的许多公司可以生产实现这种转换的设备,并提供功能齐全的开发接口和文档说明。国内集成电路的设计开发公司能力还有限,限于提供不太复杂的应用及单一产品中,并且在国内的市场占有率还很小,目前正处于蓬勃发展阶段。设备控制芯片分为通用设备控制器,定位于某几类USB产品的编程应用;专用设备控制器,定位于某一个USB产品的应用。通用设备控制器大部分被国外芯片垄断,国内在专用设备控制器已有所发展。
国内外已有很多商业上成熟的此类接口转换器,其重点都是放在虚拟串口设备的设计上。一个好的转接器需要设计一个能列举虚拟串口的驱动程序,在这种情况下,PC端的应用软件依然是针对RS-232串行端口编程的,外设也是以RS-232为数据通信通道,但从PC到外设之间的物理连接却是USB总线,其上的数据通信也是USB数据格式。采用这种方式的好处在于:一方面可以保护原有的软件开发投入,并使已有的针对RS-232外设的应用软件不加修改,便可继续使用;另一方面就是USB总线的高传输速率和即插即用的特性得到了充分利用。虚拟串口的用途最初都是用于串口转网络通信接口,也就是把对网口的操作映射为对串口操作。
例如,在传统的门禁系统、考勤系统、售饭系统、POS消费系统和一些其中控制系统中,传统串口总线获得了大量的应用。但与网络相比,传统串口总线在传输距离 5 河南城建学院本科毕业设计(论文) 绪论
和可靠性方面存在较大的局限性,随着网络的普及,通过TCP/IP网络实现网络连接,解决传统串口在传输距离和可靠性方面方面存在较大的局限性成为必然选择。由于原来的平台软件是通过电脑串口收发数据,为了使平台软件不用改变工作方式,需要在电脑平台上安装虚拟串口驱动,通过虚拟串口驱动可以将硬件转换器从网络上传送来的数据重定向到一个虚拟串口上。这样,平台软件通过虚拟串口进行数据收发。
USB和串口之间的转换实现,还有一种实现是软件实现。这里的软件实现主要指设计USB转串口的驱动程序。在USB中CDC子类成为规范之前,USB转串口的驱动程序的实现各种各样,且基于特定的设备,通用性较差。USB中CDC子类中抽象控制模型规范了虚拟串口实现的框架,增强了虚拟串口驱动程序的通用性。
6 河南城建学院本科毕业设计(论文) USB及串口简单介绍
第2章 USB及串口简单介绍
2.1 USB简介
USB是英文Universal Serial Bus(通用串行总线)的缩写,是一个外部总线的标准,用于规范电脑与外部设备的连接和通讯,是应用在PC领域的接口技术。USB传输速度极快,使用很方便,它可以连接的非常多的外设。比如:鼠标、键盘、移动硬盘等。
USB设备之所以会被大量应用,主要有以下优点:
1) 可以热插拔。这让用户在使用外接设备时不需要重复关机这样的动作。
2) 携带方便。USB设备通常以“小、轻、薄”见长,对用户来说,同样40G硬盘,USB硬盘比IDE硬盘要轻一半,在想要随身携带大量数据时,当然USB硬盘会是首选了。
3) 标准统一。常见的是IDE接口的硬盘,串口的鼠标键盘,并口的打印机扫面议,可以有了USB之后,这些应用外设统统可以用同样的标准与PC连接,这时就有了USB硬盘,USB鼠标,等等。
4) 可以连接多个设备。USB在PC上往往具有多个接口,可以同时连接几个外设,最高可连接127个设备。
每个USB只有一个主机,主机也称为根,根结或根Hub,它做在主板上或作为适配卡安装在计算机上,主机包含有主控制器和根集线器,控制着USB总线上的数据和控制信息的流动,每个USB系统只能有一个根集线器,它连接在主控制器上。关于USB的数据传输:主控制器负责主机和USB设备间数据流的传输。它支持四种基本的数据传输模式:控制传输,等时传输,中断传输及数据块传输。
[1]2.2 串口简介
串行通信接口即是串口,采用串行通信方式的扩展接口。其通信线只有一根用来传输数据,数据传输方式是一位一位的顺序传送。这样的传输方式简单可以降低很多成本,故很多嵌入式系统采用此种接口。串口适用于长距离通信,但其传输速率较慢。串口通信可以分为单工、半双工和全双工三种[2]。单工数据传输只支持数据在一个方向上传输;半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
7 河南城建学院本科毕业设计(论文) USB及串口简单介绍
串口通常有RXD和TXD两个端口,RXD是接收端,TXD是发送端。串口将RXD连接到另一个设备的TXD端,TXD连接到另一个设备的RXD端,然后通过CLK的时序就可以进行数据的发送与接收了。
2.3 USB虚拟串口简介
USB通信设备类在物理层通过USB总线,采用虚拟串口的方式为主机提供一个物理串口。在系统内部,USB芯片提供一个批量传输IN端点和一个批量传输的OUT端点,用于数据的接受和发送,模拟串口的RXD线和TXD线;另外,芯片还提供中断IN端点,发送当前串口的状态,实现对串口传输的控制。串口设备的数据,由系统的串口采集,在芯片内完成USB包的封装,通过USB总线上传至主机,再由相应的串口应用程序(串口调试助手)进行处理。对用户来说,看到的是基于串口的数据采集和传输,而实际上实现的是基于USB协议包的数据传输。
8 河南城建学院本科毕业设计(论文) USB和USB CDC协议
第3章 USB和USB CDC协议
3.1 通用串行总线USB
3.1.1 USB协议相关知识介绍
USB端点
USB通信最基本的形式是通过一个名为端点的东西。USB端点只能往一个方向传送数据,从主机到设备(称为输出端点)或者从设备到主机(称为输入端点)。端点可以看作是单向的管道。USB是主机与外围设备之间的一种串行连接。它以单一类型的总线连接不同类型的设备[3]。USB通过具有一定格式的“信包”按一定的“规程”来传输信息,根据信息的性质可以分为4种传输类型:
1) 控制模式:主要用于配置USB设备,获取设备信息,发送数据到设备,或者获取设备的报告。每一个USB设备都必须具有名为端点0的控制端点,USB核心使用该端点在插入设备时进行相应的配置。在USB虚拟串口设计中使用该模式进行配置USB设备,并通过该模式在主机与设备间交换控制请求。
2) 中断模式:虽然是中断模式,实际上是用于对USB设备周期性查询来实现的。USB设备不存在主动向主机发送“中断请求”的能力,只能被动地接受主机通过USB总线查询。在USB虚拟串口设计中使用该模式来实时报告设备状态。
3) 批量模式:批量端点用于传输大量的数据,没有很强的时间要求,但需要确保数据的可靠传输。在USB虚拟串口设计中该模式进行数据发送与接收。
4) 等时模式:用于定时传输大量的数据,但不能确保数据是否丢失。
USB描述符
USB是通过描述符来对USB设备进行属性说明的,当USB第一次连接到主机上时,主机要求了解USB设备的一些基本信息,比如设备有何种功能,需要占用多少USB资源,属于何种设备类等。只有主机完全确认了这些信息之后,设备才能正常工作。这些信息是通过存储在设备中的USB描述符来体现的。当USB设备插入主机后,主机要对其进行总线枚举,配置该设备所需的驱动等信息。主机通过标准请求来读取USB的描述符。
标准的USB设备有5种描述符,分别为设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符。每一个USB设备都有一个设备描述符。而每一个设备描述符有一个默认的配置描述符,配置描述符主要定义了USB设备功能,那样就需要为每个功能定义一个配置。但是同一个时刻只有一个配置可用,一个配置支持至少一个接口。接口定义了实现功能的硬件的集合,接口往往包括多个端点。
9 河南城建学院本科毕业设计(论文) USB和USB CDC协议
USB枚举
枚举就是从设备读取一些信息,知道设备时什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序。调试USB设备很重要的一点就是枚举过程,只要枚举成功了,那么就已经成功大半了。
3.1.2 USB协议枚举过程分析
USB协议定义了设备的6种状态,枚举过程会经历4种状态的迁移:上电状态,默认状态,地址状态和配置状态(其他两种是连接状态和挂起状态)。
枚举过程实际上用到而且只用到了总线的“控制传输”的传输方式。这种传输方式通常用于配置、命令、状态等情形,其中的设置操作setup和状态操作status过程的数据包具有USB协议定义的数据结构,因此,控制传输只能通过消息管道进行。
一个完整的控制传输包括三个过程:建立连接、数据过程、状态过程。建立连接的过程都是有主机发起,它开始于一个Setup令牌包,后面紧跟着一个DATA0包。如果是控制输入传输,数据过程则为输入数据,若是控制输出传输,则数据过程是输出数据。
数据过程可选型是指设置过程需要指定数据长度,如果指定为0,则没有数据过程。状态过程跟在数据之后,状态过程恰好和数据过程的数据传输方向相反,因为此阶段主要是用来确认之前两阶段的所有数据已经正确传输了。
下面是枚举详细过程:
首先获取设备描述符。USB主机检测到USB设备插入后,就会先对设备复位。设备复位后,USB主机就会对地址为0的设备发送获取设备描述符的标准请求。所有的USB设备在总线复位后其地址都为0,这样主机就可以跟那些刚刚插入的设备通过地址0(端点0)通信。主机在建立阶段发出获取设备描述符的输入请求,设备收到该请求后,在数据过程将设备描述符返回给主机。主机在成功获取到一个数据包的设备描述符后并且确认没有什么错误后(注意:有些USB设备的端点0大小不足18字节(但至少具有8字节),而标准的设备描述有18字节,在这种情况下,USB设备只能暂时按最大包将部分设备描述符返回,而主机在成功获取到前面一部分描述符后,就不会再请求剩下的设备描述符部分,而是进入设置地址阶段),就会返回一个0长度的状态数据包给设备。
然后获取地址。主机再对设备复位一下,接下来就会进入到设置地址阶段。这时USB主机发出一个设置地址的请求(建立过程,设置地址无数据过程),地址包含在建立包中,具体的地址USB主机会负责管理,它会分配一个唯一的地址给新的设备。USB设备在收到地址后,返回0长度的状态包,主机收到0长度的状态包之后,会 10 河南城建学院本科毕业设计(论文) USB和USB CDC协议
返回一个ACK给设备。设备在收到这个ACK之后,就可以启用新的地址了。这样设备就分配到了一个唯一的设备地址,以后主机就通过它来进行访问该设备。
然后主机再次获取设备描述符。这次跟第一次可能有点不一样,这次需要获取完全部的18个字节的设备描述符。当然,如果你的端点0缓冲大于18字节的话,那就跟第一次的情形一样了。
接下来,主机就会获取配置描述符。配置描述符总共为9字节。主机在获取到配置描述符后,根据里面的配置集合总长度,再获取配置集合。配置集合包括配置描述符,接口描述符,端点描符等等。
然后主机就会根据获取的配置集合对设备进行配置,使设备从地址状态进入配置状态。最后主机发送最后一个Setup包,允许所有端点进入工作状态。
过程大体分为:获取设备描述符、设置地址、再次获取设备描述符(此次获取完整的设备描述符)、获取配置描述符、对设备进行配置。
枚举就相当于主机与USB连接的一个过程,为了能够进行数据交换的一个相互识别的过程。枚举完成后,主机就可以对USB设备进行读写操作了。
3.2 USB CDC协议
USB通信设备类的研究目前尚未成熟,可以参考的资料文献和代码都比较少,更多的是依靠讨论得出方法,然后对该方法的可行度和可靠性进行试验。存在开发难度大,需要解决的问题多等困难。此外,驱动程序开发对操作系统的依赖性很高,需要对操作系统的相关细节了解透彻,但是微软的Windows NT系列操作系统不开源,无法查证实现细节,这也加大了设计实现的难度。由于驱动程序运行在内核态,因此在用户态能用的很多标准函数都无法使用,需要重新查阅函数用法,驱动程序的开发不能像用户态程序一样方便地进行调试[4]。
USB为了实现不同的应用,将具有特定属性与服务的一类设备划分为一个类(Class)。如果提供相似格式的数据流或者相似的主机交换方式,两个设备则被统一在一个类中。如USB标准就有:Audio Class、Communications Device Class、HID Class、Video Class 等用于在USB接口上实现不同的设备接口。USB标准协议中,有一类专用于通讯设备(主要包括电信通信设备和中速网络通信设备)的CDC协议,USB的CDC类(Communications Device Class)是USB通信设备类的简称。
可以通过USB CDC协议来将USB接口虚拟为其他通讯接口如串口,以太网接口,ISDN接口等等。根据CDC类协议所针对通信设备的不同,CDC协议又被分成几种不同的模型:USB传统电话业务(POTS)模型,USB ISDN模型和USB网络模型。其中,USB传统纯电话业务模型,有可分为直接线控制模型(Direct Line Control
11 河南城建学院本科毕业设计(论文) USB和USB CDC协议
Model)、抽象控制模型(Abstract Control Model)和USB电话模型(USB Telephone
Model),如图3.1所示。本文所讨论的虚拟串口就属于USB传统纯电话业务模型下的抽象控制模型。
直接线控制
电话业务模型 ISDN模型
网络模型
CDC类
抽象控制
电话模型
图3.1 CDC类分类
CDC协议由根据不同的功能可以分为三个部分:通讯设备类(Communication
Devices Class)、通讯接口类(Communication Interface Class)和数据接口类(Data
Interface Class)[5]。通讯设备类是设备层次的定义,通常用于标示一个通讯设备与该设备可以提供相应的接口。通讯接口类则定义了相应的通讯服务,包括如何对设备进行管理和控制,数据接口类则定义了如何传输数据。这两个接口子类占有不同数量和类型的终端点 (Endpoints)。对于前面所述的不同CDC类模型,其所对应的接口的终端点需求也是不同的。如所需要讨论的抽象控制模型对终端点的需求,通信接口类需要一个控制终端点(Control Endpoint)和一个可选的中断(Interrupt)型终端点,数据接口子类需要一个方向为输入(IN)的周期性(Isochronous)型终端点和一个方向为输出(OUT)的周期性型终端点。其中控制终端点主要用于USB设备的枚举和虚拟串口的波特率和数据类型(数据位数、停止位和起始位)设置的通信。输出方向的非同步终端点用于主机(Host)向从设备(Slave)发送数据,相当于传统物理串口中的TXD线(如果从单片机的角度看),输入方向的非同步终端点用于从设备向主机发送数据,相当于传统物理串口中的RXD线。
[6]3.3 USB通信过程
USB最主要的的是要理解USB主机发送命令给设备,设备要对主机的命令进行响应,USB通讯的基本单位为 “包”理解好“包”这个概念是学习USB的关键所在。
USB数据包的格式如图3.2所示。
12 河南城建学院本科毕业设计(论文) USB和USB CDC协议
Field
Bits
PID
4+4
ADDR
7
11
ENDP
4
FrameNumber
DATA
N*8(N=0,...,1024)
CRC
5/16
图3.2 USB数据包的格式
对于数据包来说,PID之后直接跟数据域,数据域的长度为N字节,数据域后以16位的CRC校验和结束。握手包仅有PID域,没有数据也没有校验和。分离传输会用到一类特殊的包,Start-Split和Complete-Split包,其格式分别如图3.3和如图3.4所示。
Field
Bits
SPLID
PID
8
Hub
Addr
7
SC
1
Port
7
S
1
E
1
ET
2
CRC5
5
图3.3 Start-Split 包
Field
Bits
SPLID
PID
8
Hub
Addr
7
SC
1
Port
7
S
1
U
1
ET
2
CRC5
5
图3.4 Complete-Split包
在Start-Split和Complete-Split包中主要指定了此次分离传输所在的HUB的地址和下行端口编号以及端点类型(控制、中断、批量、同步)。以及此次传输中数据在整个数据中的位置(第一个包、中间的包、末尾的包)。
令牌包可分为输入包、输出包、设置包和帧起始包(注意这里的输入包是用于设置输入命令的,输出包是用来设置输出命令的,而不是放据数的)其中输入包、输出包和设置包的格式都是一样的:SYNC+PID+ADDR+ENDP+CRC5(五位的校验码)。
帧起始包的格式是SYNC+PID+11位FRAM+CRC5(五位的校验码)。
数据包可以分为DATA0包和DATA1包,当USB发送数据的时候,当一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATA0包和DATA1包交替发送,即如果第一个数据包是DATA0,那第二个数据包就是DATA1。但也有例外情况,在同步传输中(四类传输类型中之一),所有的数据包都是为DATA0,格式如下:SYNC+PID+0~1023字节+CRC16。
13 河南城建学院本科毕业设计(论文) USB和USB CDC协议
握手包的结构最为简单的包,格式如下:SYNC+PID。
数据在USB总线上的传输以包为单位,包只能在帧内传输。高速USB总线的帧周期为125uS,全速以及低速USB总线的帧周期为1mS。帧的起始由一个特定的包(SOF包)表示,帧尾为EOF。EOF不是一个包,而是一种电平状态,EOF期间不允许有数据传输。虽然高速总线和全速低速总线的帧周期不一样,当时包中帧编号的增加速度是USB/USBSOF一样的,因为在高速USB系统中,SOF包中帧编号实际上取得是计数器的高11位,最低三位作为微帧编号没有使用,因此其帧编号的增加周期也为1ms。
USB采用littleedian字节顺序,在总线上先传输一个字节的最低有效位,最后传输最高有效位,采用NRZI编码,若遇到连续的6个1要求进行为填充,即插入一个0。所有的USB包都由SYNC开始,高速包的SYNC宽度为32bit,全速/低速包的SYNC段长度为8bit。实际接收到的SYNC产度由于USB HUB的关系,可能会小于该值。
14 河南城建学院本科毕业设计(论文) 虚拟串口的实现
第4章 虚拟串口的实现
4.1 串口的工作原理
之所以取名为“串行”端口,是因为这种端口会将数据“串行化”。更具体地说,它一次获取一个字节的数据并传输该字节的8位。这样做的优势在于,串行端口只需要一条线路就能传输8个位,而并行端口则需要8条。相应的劣势在于,其传输数据的用时是拥有八条线路时的8倍。此外,串行端口还可以降低线缆成本,使线缆更加小巧。
在发送数据的每个字节之前,串行端口会发送一个开始位,这是一个值为0的单个位。在发送完数据的每个字节之后,它将发送一个停止位,表示该字节已传输完成。此外,它还可以发送奇偶校验位。
1) 波特率。这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。
2) 数据位。这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。
3) 停止位。用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
4) 奇偶校验位。在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的
15 河南城建学院本科毕业设计(论文) 虚拟串口的实现
检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
4.2 USB虚拟串口设计
4.2.1 STM32 USB部分说明
STM32的USB模块可以产生三种中断:USB唤醒中断、USB高优先级中断和USB低优先级中断,在STM32的参考手册中没有详细说明这三种中断对应哪些事件,现说明如下:
1) USB唤醒中断:在中断向量表中的位置是42。这个中断在USB设备从暂停模式唤醒时产生,唤醒事件由USB_ISTR寄存器的WKUP位标识。
2) USB高优先级中断:在中断向量表中的位置是19。这个中断仅由USB同步(Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,正确传输事件由USB_ISTR寄存器的CTR位标识。
3) USB低优先级中断:在中断向量表中的位置是20。这个中断由所有其它的USB事件产生,例如正确传输(不包括同步模式和双缓冲块模式)、USB复位等,事件标志位在USB_ISTR寄存器中。 在STM32的USB开发包的例子中包含了上述中断的处理,例如在USB扬声器的例子中,CTR_HP函数处理USB高优先级中断;在所有例子中都有USB_Istr()函数处理USB低优先级中断。
USB如何区分低速、全速和高速设备:对于全速和高速设备,上拉电阻是接在D+上;而低速设备则是上拉电阻接在D-上。
USB系统中只允许有一个主机,主机分为3个不同的功能模块:应用软件、USB系统软件和USB总线接口。客户软件负责和USB设备的功能单元进行通信,以实现其特定功能,它需要开发人员自行开发,包括USB设备驱动程序和界面应用程序两部分。客户软件不能直接访问USB设备,其与功能单元的通信必须经过USB系统软件和USB总线接口模块才能实现。
[8]4.4.2 USB电路连接
从主机角度上讲,USB设备可看作是由一些配置、接口和端点组成的,这是通常所说的USB设备架构,即一个USB设备可以含有一个或多个配置。在每个配置中可含有一个或多个接口,在每个接口中可含有若干个端点。其中,配置和接口是对USB设 16 河南城建学院本科毕业设计(论文) 虚拟串口的实现
备功能的抽象,实际的数据传输由端点来完成,在使用USB设备前,必须指明其采用哪个配置和接口。USB设备使用各种描述符来说明其设备构架,包括设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符等,它们通常被保存在USB接口芯片的固件中。
USB的电路连接如图4.1所示:
图 4.1 USB硬件接口图
4.2.3 虚拟串口程序设计
首先是枚举过程中的获取设备描述符部分,主机如果要识别成串口,就要将此USB设备的描述符写成虚拟串口的描述符,要根据CDC类通信协议进行编写。此程序设备描述符是一个数组,数组的成员是描述符的内容。
下面定义的数组即是设备描述符。
const uint8_t Virtual_Com_Port_DeviceDescriptor[] =
{
0x12, /* 描述符字节长度*/
USB_DEVICE_DESCRIPTOR_TYPE, /* 设备描述符类型*/
0x00,
17 河南城建学院本科毕业设计(论文) 虚拟串口的实现
0x02, /* USB规范发布号,表示用哪种协议,0x20表示USB2.0*/
0x02, /* 类型代码 即CDC */
0x00, /* 子类型代码 */
0x00, /* 协议代码*/
0x40, /* 端点0最大分组大小,值为,8、16、32、64*/
0x83,
0x04, /* 供应商ID*/
0x40,
0x57, /* 产品ID。由产品ID和供应商ID,就可以让操作系统加载不同的驱动程序*/
0x00,
0x02, /* 设备出产编码*/
1, /* 制造商标示符*/
2, /* 产品标示符*/
3, /* 设备串口号描述符*/
0x01 /* 可能配置数,指配置字符串的个数*/
};
在枚举前期,USB主机发送SETUP包,然后获取设备描述符,然后会得知设备的类型,再加载相应的驱动,此时USB虚拟串口就成功了。完成枚举之后,就可以编写作为串口接收和发送数据的程序了。
在此设计中我们只需用到STM32的GPIOA,GPIOB和串口以及USB时钟。所以先要允许GPIOA,GPIOB和串口的时钟。USB时钟会在接下来使能。
下面看第一个Set_System()函数:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);这个函数叫允许USB断开线。通过查看RCC_APB2Periph_GPIO_DISCONNECT在程序中的定义为RCC_APB2Periph_GPIOA。
而USB_DISCONNECT_PIN在程序中定义的为GPIO_Pin_11。说明是程序定义的断开线引脚是PA11,查看STM32引脚图可以看出PA11是连接USB引脚的DM引脚。此引脚连接到一个上拉电阻控制的三极管上面,接下来将USB的断开引脚即PA11配置成上拉的。这也就意味着在开始时这个上拉电阻使得三极管导通,从而使时DP脚被加上一个1.5K的电阻,这样就可以开始枚举了。
第二个函数Set_USBClock(),这个函数就是先将USB所在的总线AP1经过PLL分频,得到AP1时钟,然后再允许USB时钟使能。
18 河南城建学院本科毕业设计(论文) 虚拟串口的实现
第三个函数USB_Interrupts_Config(),由名字可以看出是配置USB中断的。在该函数中使能了两个中断,一个是USB,一个是串口。程序中没有设定它们的抢占优先级,故默认它们的优先级分组相同,USB的响应优先级为0,串口的响应优先级为1,由于抢占优先级相同,不存在嵌套关系,故这两个中断都不会被另一个中断打断。在它们中断函数里面是我要处理的各个事情,等一下再介绍它们。
最后是USB_Init()。第一句是将pInformation 指向Device_Info结构体;第三句是将pProperty指向Device_Property结构体;第四句将pUser_Standard_Requests指针指向User_Standard_Requests结构体。这三个结构体都是与具体设备枚举和功能实现相关的。最后一句实际上运行的是DEVICE_PROP中的Virtual_Com_Port_init()这个函数。这个函数通过查看可以看到几个函数:
1) Get_SerialNum(),此为获取设备序列号,转变为Unicode字符串。
2) Power On(),连接USB设备,实质是让主机检测到USB设备。
3) USART_Config_Default(),配置串口至缺省状态,在这里波特率被设置为9600,并且允许了接收中断。发送中断没有允许。
4) bDeviceState = UNCONNECTED,将当前状态定义为未连接状态。
到此初始化结束了。
下面就是中断部分了。中断函数是串口的接受中断,程序中串口的发送中断是没有允许的。那么串口是如何发送数据呢?不用中断方式,那就是直接来用写寄存器方式来发送了。不过写寄存器方式,当有大量数据发送时就会出现问题,因为它没有判断是否发送缓冲区为空。
串口接收中断调用的函数为USART_To_USB_Send_Data()。函数功能是从串口向USB端发送数据。然后数据再从USB端向主机发送,这样就可以与主机相互通信了。
在做好的虚拟串口端可以连接一个硬件,使其通过串口将数据发送给USB虚拟的串口处理器中,然后可以通过设备的USB向PC机发送数据。而对于PC机,USB设备相当于一个串口设备,它识别的也是个COM口,所以我们可以通过串口调试助手来查看接收到的数据。也可以用串口调试助手来发送数据,通过USB虚拟的串口设备来返回该数据。
19 河南城建学院本科毕业设计(论文) 虚拟串口的实现
第5章 结论
随着越来越多的外设开始使用USB接口进行数据通信,合理并快速地实现基于USB的数据传输显得尤为重要,而基于通信设备类的虚拟设备实现又是开发人员研究的重点。论文研究了以USB通信设备类为核心的虚拟串口实现方案,并对虚拟串口驱动的加载及卸载、通信命令转换和数据高速传输进行了研究,实现了基于通信设备类的虚拟串口驱动程序的可用版本。与现有类似驱动程序相比,该系统具有符合通信设备类的抽象控制模型和高速传输等优点,此外它还与Windows2003、XP、Vista和Win7系统在源代码级别兼容,具有广阔的应用前景。论文中通信设备类的研究及基于通信设备类的虚拟串口实现,对开发人员设计其他基于通信设备类的虚拟设备实现方案具有很好的指导意义。
本论文主要完成以下工作:
1) 深入研究了Windows驱动的工作原理,阅读了英文原版的Windows NT文件系统及USB协议中通信设备类的相关书籍,既学习了Windows驱动程序的的一般开发方法,又学习了符合USB协议的驱动程序的开发方法。阅读了相关的驱动开发源码,掌握了Windows NT操作系统下虚拟设备驱动程序的开发方法;
2) 研究了现有的虚拟串口实现技术,分析了各种实现方法的优缺点,从中选择了通信设备类的抽象控制模型作为虚拟串口实现的理论依据,避免了重新设计USB转串口电路板及兼容性的问题,这使得虚拟串口驱动有更广阔的应用前景,通用性和高效性;
3) 学习了USB协议,对通信设备类进行了深入的研究和分析,并且根据通信设备类中各模型的特点,确定了虚拟串口驱动所用的模型为抽象控制模型;
4) 根据虚拟串口驱动程序的设计目标,研究了虚拟串口驱动程序的总体结构和详细方案,对虚拟串口驱动程序中的难点和重点问题进行深入的分析和解决方法的优化;
5) 根据虚拟串口驱动程序的研究结果,实现了该驱动程序的演示版本,进行了兼容性和稳定性的测试,通过测试得出了还需要对系统做后续的改进和完善的工作。
20 河南城建学院本科毕业设计(论文) 结论
21 河南城建学院本科毕业设计(论文) 参考文献
参考文献
[1] Universal Serial Bus Specification,Revision 2.0. Compaq,Hewlett-Packard,Intel,Lucent,Microsoft,NEC,Philips Inc[J],2000.
[2] 许永和.EZ-USB FX 系列单片机USB外围设备设计与应用[M].北京:北京航空航天大学出版社,2002.
[3] MindShare,inc,Don Anderson,Dave Dzatko,孟文.USB系统体系[M].北京:中国电力出版社,2003.
[4] 李肇庆,廖峰,刘建存.USB接口技术[M].北京:国防工业出版社,2004
[5] 王成儒,李英伟.USB2.0原理与工程开发[M].北京:国防工业出版社,2004.
[6] 张帆,史彩成.Windows设备驱动程序开发指南[M].北京:北京航空航天大学出版社,2008.
[7] Walter Oney. Programming the Microsoft Windows Driver oft
Press[J],2003.
[8] Chris g Windows WDM Device Drivers. Focal Press[J],1999.
[9] 周立功.USB2.0与OTG规范及开发指南[M].北京:北京航空航天大学出版社,2004.
[10]肖踞雄,翁铁成,宋中庆.USB技术及应用设计[M].北京:清华大学出版社,2004.
[11]Jan Axelson. USB Complete: The Developer’s Guide[M]. Lakeview Research,2011.
22 河南城建学院本科毕业设计(论文) 致谢
致 谢
时光荏苒,四年的大学生活已经接近尾声。在毕业论文完成之际,我谨向所有给予了我指导、关心和支持的老师、同学和亲人们致以最衷心的感谢!
首先,深深感谢我的导师侯宁老师。有了您的悉心指导与勉励,我才能顺利完成了理论学习和毕业论文。您平易近人、治学严谨、知识渊博,对待生活积极乐观,为我们营造了轻松积极的环境,真正做到了传道、授业、解惑。您在学习和生活上给予了我很多引导和帮助,为人的和蔼、敏锐的把握能力和孜孜不倦的研究精神永远是我学习、生活和工作的榜样,这将成为我人生中一笔宝贵的财富。非常有幸能够成为您的学生,在此谨向尊敬的侯老师致以最衷心的感谢,同时也祝您身体健康、工作顺利、合家欢乐!
其次,感谢陈景富和仇灵杰两位师兄,感谢你们给予的支持和热情帮助。感谢实验室里的师弟师妹们给我的大学生活带来的快乐与欢笑!同时,感谢电子信息专业的所有老师,您们的辛勤劳动为莘莘学子们打开了通往科学知识殿堂的大门,您们的谆谆教诲和渊博的专业知识使我在大学期间受益颇丰。感谢河南城建学院的教育和培养,使我在各方面的素质有了质的提高。
非常感激我的父母和亲人,一直以来都是你们在默默地支持我、关心我、鼓励我,给了我无私的爱与感动。感谢我最最亲爱的父母,正是您们的含辛茹苦与激励使我不断进取,成为我在成长道路上不竭的动力源泉。在我的人生路途上,每一个新的脚步都凝聚了您们的心血与操劳,纵然岁月无情地在您们的发丝上悄悄地留下了印痕,在未来的日子里,我将倍加努力,不辜负您们的期望!在此,一并感谢所有好朋友的关怀与鼓励,衷心地祝愿大家开心快乐每一天!
23 河南城建学院本科毕业设计(论文) 附录
附录:
/* Includes ------------------------------------------------------------------*/
#include "include.h"
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_desc.h"
#include "usb_pwr.h"
#include "queue.h"
INT8U Flag_USBSendOver = 1; /*发送完成标志*/
extern uint8_t USART_Rx_Buffer[];
Queue buff_in;
INT8U USB_Tx_Buffer[VIRTUAL_COM_PORT_DATA_SIZE]; /*发送缓存64字节*/
INT8U USB_Tx_Buffer0[1]={5}; /*发送缓存64字节*/
int main(void)
{
INT8U i = 0;
INT8U temp;
Set_System();
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
{
Queue_Rst(&buff_in,(QUEUE_DATA_TYPE*)
//buff_ = 5;
USART_Rx_Buffer,USART_RX_DATA_SIZE); /*初始化接收循环队列*/
while (1)
if(bDeviceState == CONFIGURED)
{
if(1 == Flag_USBSendOver && buff_ != 0) /*有数据需要24 河南城建学院本科毕业设计(论文) 附录
发送,上一次发送完成*/
{
Flag_USBSendOver = 0;
if(buff_ > 64) /*一次最多发送64字节*/
{
//for(i=0;i!=10;i++)
UserToPMABufferCopy(USB_Tx_Buffer0,
ENDP1_TXADDR, 1); /*发送数据*/
SetEPTxCount(ENDP1,1);
SetEPTxValid(ENDP1);
for(i=0;i!=64;i++)
Queue_Read(&buff_in, &USB_Tx_Buffer[i]);
到发送缓冲区*/
UserToPMABufferCopy(USB_Tx_Buffer,
ENDP1_TXADDR, 64); /*发送数据*/
SetEPTxCount(ENDP1,64);
SetEPTxValid(ENDP1);
}
else
{
temp = buff_; /*读取要发送的字节数*/
for(i=0;i!=temp;i++)
Queue_Read(&buff_in, &USB_Tx_Buffer[i]);
到发送缓冲区*/
UserToPMABufferCopy(USB_Tx_Buffer,
ENDP1_TXADDR, temp); /*发送数据*/
SetEPTxCount(ENDP1,temp);
SetEPTxValid(ENDP1);
/*读/*读25
河南城建学院本科毕业设计(论文) 附录
}
}
}
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %drn", file, line) */
/* Infinite loop */
while (1)
{}
}
#endif
/*Includes--------------------------------------------------------*/
#include "usb_lib.h"
#include "usb_desc.h"
/* USB Standard Device Descriptor */
const uint8_t Virtual_Com_Port_DeviceDescriptor[] =
{
0x12, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00,
0x02, /* bcdUSB = 2.00 */
0x02, /* bDeviceClass: CDC */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
0x40, /* bMaxPacketSize0 */
0x83,
26 河南城建学院本科毕业设计(论文) 附录
0x04, /* idVendor = 0x0483 */
0x40,
0x57, /* idProduct = 0x7540 */
0x00,
0x02, /* bcdDevice = 2.00 */
1, /* Index of string descriptor describing manufacturer */
2, /* Index of string descriptor describing product */
3, /* Index of string descriptor describing the device's serial
number */
0x01 /* bNumConfigurations */
};
const uint8_t Virtual_Com_Port_ConfigDescriptor[] =
{
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType:
Configuration */
VIRTUAL_COM_PORT_SIZ_CONFIG_DESC, /* wTotalLength:no of
returned bytes */
0x00,
0x02, /* bNumInterfaces: 2 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration
*/
0xC0, /* bmAttributes: self powered */
0x32, /* MaxPower 0 mA */
/*Interface Descriptor*/
0x09, /* bLength: Interface Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */
/* Interface descriptor type */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
27 河南城建学院本科毕业设计(论文) 附录
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x00, /* iInterface: */
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x01, /* bDataInterface: 1 */
/*ACM Functional Descriptor*/
0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x02, /* bmCapabilities */
/*Union Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x82, /* bEndpointAddress: (IN2) */
0x03, /* bmAttributes: Interrupt */
28 河南城建学院本科毕业设计(论文) 附录
VIRTUAL_COM_PORT_INT_SIZE, /* wMaxPacketSize: */
0x00,
0xFF, /* bInterval: */
/*Data class interface descriptor*/
0x09, /* bLength: Endpoint Descriptor size */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x00, /* iInterface: */
/*Endpoint 3 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x03, /* bEndpointAddress: (OUT3) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */
0x00,
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint 1 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */
0x81, /* bEndpointAddress: (IN1) */
0x02, /* bmAttributes: Bulk */
VIRTUAL_COM_PORT_DATA_SIZE, /* wMaxPacketSize: */
0x00,
0x00 /* bInterval */
};
typedef struct _DEVICE_INFO
{
uint8_t USBbmRequestType; /* bmRequestType */
29 河南城建学院本科毕业设计(论文) 附录
uint8_t USBbRequest; /* bRequest */
uint16_t_uint8_t USBwValues; /* wValue */
uint16_t_uint8_t USBwIndexs; /* wIndex */
uint16_t_uint8_t USBwLengths; /* wLength */
uint8_t ControlState; /* of type CONTROL_STATE */
uint8_t Current_Feature;
uint8_t Current_Configuration; /* Selected configuration */
uint8_t Current_Interface; /* Selected interface of current configuration */
uint8_t Current_AlternateSetting;/* Selected Alternate Setting of current
interface*/
ENDPOINT_INFO Ctrl_Info;
}DEVICE_INFO;
/* Includes ----------------------------------------------------*/
#include "usb_lib.h"
/* Private typedef --------------------------------------*/
/* Private define ---------------------------------------------*/
#define ValBit(VAR,Place) (VAR & (1 << Place))
#define SetBit(VAR,Place) (VAR |= (1 << Place))
#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255))
#define Send0LengthData() { _SetEPTxCount(ENDP0, 0);
vSetEPTxStatus(EP_TX_VALID);
}
#define vSetEPRxStatus(st) (SaveRState = st)
#define vSetEPTxStatus(st) (SaveTState = st)
#define USB_StatusIn() Send0LengthData()
#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID)
#define StatusInfo0 1 /* Reverse bb0 & bb1 */
30 河南城建学院本科毕业设计(论文) 附录
#define StatusInfo1 0
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint16_t_uint8_t StatusInfo;
bool Data_Mul_MaxPacketSize = FALSE;
/* Private function prototypes -----------------------------------------------*/
static void DataStageOut(void);
static void DataStageIn(void);
static void NoData_Setup0(void);
static void Data_Setup0(void);
/* Private functions ---------------------------------------------------------*/
uint8_t *Standard_GetConfiguration(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl__wLength =
sizeof(pInformation->Current_Configuration);
return 0;
}
pUser_Standard_Requests->User_GetConfiguration();
return (uint8_t *)&pInformation->Current_Configuration;
}
RESULT Standard_SetConfiguration(void)
{
if ((pInformation->USBwValue0 <=
Device__Configuration) && (pInformation->USBwValue1 == 0)
&& (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/
{
31 河南城建学院本科毕业设计(论文) 附录
pInformation->Current_Configuration = pInformation->USBwValue0;
pUser_Standard_Requests->User_SetConfiguration();
return USB_SUCCESS;
}
else
{
return USB_UNSUPPORT;
}
}
uint8_t *Standard_GetInterface(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl__wLength =
sizeof(pInformation->Current_AlternateSetting);
return 0;
}
pUser_Standard_Requests->User_GetInterface();
return (uint8_t *)&pInformation->Current_AlternateSetting;
}
RESULT Standard_SetInterface(void)
{
RESULT Re;
/*Test if the specified Interface and Alternate Setting are supported by
the application Firmware*/
Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0,
pInformation->USBwValue0);
if (pInformation->Current_Configuration != 0)
{
if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0)
32 河南城建学院本科毕业设计(论文) 附录
|| (pInformation->USBwValue1 != 0))
{
return USB_UNSUPPORT;
}
else if (Re == USB_SUCCESS)
{
pUser_Standard_Requests->User_SetInterface();
pInformation->Current_Interface = pInformation->USBwIndex0;
pInformation->Current_AlternateSetting = pInformation->USBwValue0;
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}
uint8_t *Standard_GetStatus(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl__wLength = 2;
return 0;
}
/* Reset Status Information */
StatusInfo.w = 0;
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
/*Get Device Status */
uint8_t Feature = pInformation->Current_Feature;
33 河南城建学院本科毕业设计(论文) 附录
/* Remote Wakeup enabled */
if (ValBit(Feature, 5))
{
SetBit(StatusInfo0, 1);
}
else
{
ClrBit(StatusInfo0, 1);
}
/* Bus-powered */
if (ValBit(Feature, 6))
{
SetBit(StatusInfo0, 0);
}
else /* Self-powered */
{
ClrBit(StatusInfo0, 0);
}
}
/*Interface Status*/
else
{
return (uint8_t *)&StatusInfo;
}
/*Get EndPoint Status*/
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
uint8_t Related_Endpoint;
uint8_t wIndex0 = pInformation->USBwIndex0;
Related_Endpoint = (wIndex0 & 0x0f);
if (Type_Recipient == (STANDARD_REQUEST |
INTERFACE_RECIPIENT))
34 河南城建学院本科毕业设计(论文) 附录
if (ValBit(wIndex0, 7))
{
/* IN endpoint */
if (_GetTxStallStatus(Related_Endpoint))
{
SetBit(StatusInfo0, 0); /* IN Endpoint stalled */
}
}
else
{
/* OUT endpoint */
if (_GetRxStallStatus(Related_Endpoint))
{
SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */
}
}
}
else
{
return NULL;
}
pUser_Standard_Requests->User_GetStatus();
return (uint8_t *)&StatusInfo;
}
RESULT Standard_ClearFeature(void)
{
uint32_t Type_Rec = Type_Recipient;
uint32_t Status;
if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT))
35 河南城建学院本科毕业设计(论文) 附录
{/*Device Clear Feature*/
ClrBit(pInformation->Current_Feature, 5);
return USB_SUCCESS;
}
else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{/*EndPoint Clear Feature*/
DEVICE* pDev;
uint32_t Related_Endpoint;
uint32_t wIndex0;
uint32_t rEP;
if ((pInformation->USBwValue != ENDPOINT_STALL)
|| (pInformation->USBwIndex1 != 0))
{
return USB_UNSUPPORT;
}
pDev = &Device_Table;
wIndex0 = pInformation->USBwIndex0;
rEP = wIndex0 & ~0x80;
Related_Endpoint = ENDP0 + rEP;
if (ValBit(pInformation->USBwIndex0, 7))
{
/*Get Status of endpoint & stall the request if the related_ENdpoint
is Disabled*/
Status = _GetEPTxStatus(Related_Endpoint);
}
else
{
Status = _GetEPRxStatus(Related_Endpoint);
}
36 河南城建学院本科毕业设计(论文) 附录
if ((rEP >= pDev->Total_Endpoint) || (Status == 0)
|| (pInformation->Current_Configuration == 0))
{
return USB_UNSUPPORT;
}
if (wIndex0 & 0x80)
{
/* IN endpoint */
if (_GetTxStallStatus(Related_Endpoint ))
{
ClearDTOG_TX(Related_Endpoint);
SetEPTxStatus(Related_Endpoint, EP_TX_VALID);
}
}
else
{
/* OUT endpoint */
if (_GetRxStallStatus(Related_Endpoint))
{
if (Related_Endpoint == ENDP0)
{
/* After clear the STALL, enable the default endpoint receiver */
SetEPRxCount(Related_Endpoint, Device_ketSize);
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
else
{
ClearDTOG_RX(Related_Endpoint);
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
}
37 河南城建学院本科毕业设计(论文) 附录
}
pUser_Standard_Requests->User_ClearFeature();
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
RESULT Standard_SetEndPointFeature(void)
{
uint32_t wIndex0;
uint32_t Related_Endpoint;
uint32_t rEP;
uint32_t Status;
wIndex0 = pInformation->USBwIndex0;
rEP = wIndex0 & ~0x80;
Related_Endpoint = ENDP0 + rEP;
if (ValBit(pInformation->USBwIndex0, 7))
{
/* get Status of endpoint & stall the request if the related_ENdpoint
is Disabled*/
Status = _GetEPTxStatus(Related_Endpoint);
}
else
{
Status = _GetEPRxStatus(Related_Endpoint);
}
if (Related_Endpoint >= Device__Endpoint
|| pInformation->USBwValue != 0 || Status == 0
|| pInformation->Current_Configuration == 0)
38 河南城建学院本科毕业设计(论文) 附录
{
return USB_UNSUPPORT;
}
else
{
if (wIndex0 & 0x80)
{
/* IN endpoint */
_SetEPTxStatus(Related_Endpoint, EP_TX_STALL);
}
else
{
/* OUT endpoint */
_SetEPRxStatus(Related_Endpoint, EP_RX_STALL);
}
}
pUser_Standard_Requests->User_SetEndPointFeature();
return USB_SUCCESS;
}
RESULT Standard_SetDeviceFeature(void)
{
SetBit(pInformation->Current_Feature, 5);
pUser_Standard_Requests->User_SetDeviceFeature();
return USB_SUCCESS;
}
uint8_t *Standard_GetDescriptorData(uint16_t Length,
*pDesc)
{
uint32_t wOffset;
ONE_DESCRIPTOR
39 河南城建学院本科毕业设计(论文) 附录
wOffset = pInformation->Ctrl__wOffset;
if (Length == 0)
{
pInformation->Ctrl__wLength = pDesc->Descriptor_Size - wOffset;
return 0;
}
return pDesc->Descriptor + wOffset;
}
void DataStageOut(void)
{
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
uint32_t save_rLength;
save_rLength = pEPinfo->Usb_rLength;
if (pEPinfo->CopyData && save_rLength)
{
uint8_t *Buffer;
uint32_t Length;
Length = pEPinfo->PacketSize;
if (Length > save_rLength)
{
Length = save_rLength;
}
Buffer = (*pEPinfo->CopyData)(Length);
pEPinfo->Usb_rLength -= Length;
pEPinfo->Usb_rOffset += Length;
PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length);
40 河南城建学院本科毕业设计(论文) 附录
}
if (pEPinfo->Usb_rLength != 0)
{
vSetEPRxStatus(EP_RX_VALID);/* re-enable for next data reception */
SetEPTxCount(ENDP0, 0);
vSetEPTxStatus(EP_TX_VALID);/* Expect the host to abort the data OUT stage
*/
}
/* Set the next State*/
if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize)
{
pInformation->ControlState = OUT_DATA;
}
else
{
if (pEPinfo->Usb_rLength > 0)
{
pInformation->ControlState = LAST_OUT_DATA;
}
else if (pEPinfo->Usb_rLength == 0)
{
pInformation->ControlState = WAIT_STATUS_IN;
USB_StatusIn();
}
}
}
void DataStageIn(void)
{
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
uint32_t save_wLength = pEPinfo->Usb_wLength;
uint32_t ControlState = pInformation->ControlState;
41 河南城建学院本科毕业设计(论文) 附录
uint8_t *DataBuffer;
uint32_t Length;
if ((save_wLength == 0) && (ControlState == LAST_IN_DATA))
{
if(Data_Mul_MaxPacketSize == TRUE)
{
/* No more data to send and empty packet */
Send0LengthData();
ControlState = LAST_IN_DATA;
Data_Mul_MaxPacketSize = FALSE;
}
else
{
/* No more data to send so STALL the TX Status*/
ControlState = WAIT_STATUS_OUT;
vSetEPTxStatus(EP_TX_STALL);
}
goto Expect_Status_Out;
}
Length = pEPinfo->PacketSize;
ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA;
if (Length > save_wLength)
{
Length = save_wLength;
}
DataBuffer = (*pEPinfo->CopyData)(Length);
42 河南城建学院本科毕业设计(论文) 附录
UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);
SetEPTxCount(ENDP0, Length);
pEPinfo->Usb_wLength -= Length;
pEPinfo->Usb_wOffset += Length;
vSetEPTxStatus(EP_TX_VALID);
USB_StatusOut();/* Expect the host to abort the data IN stage */
Expect_Status_Out:
pInformation->ControlState = ControlState;
}
void NoData_Setup0(void)
{
RESULT Result = USB_UNSUPPORT;
uint32_t RequestNo = pInformation->USBbRequest;
uint32_t ControlState;
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
/* Device Request*/
/* SET_CONFIGURATION*/
if (RequestNo == SET_CONFIGURATION)
{
Result = Standard_SetConfiguration();
}
/*SET ADDRESS*/
else if (RequestNo == SET_ADDRESS)
{
43 河南城建学院本科毕业设计(论文) 附录
if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0)
|| (pInformation->USBwIndex != 0)
|| (pInformation->Current_Configuration != 0))
/* Device Address should be 127 or less*/
{
ControlState = STALLED;
goto exit_NoData_Setup0;
}
else
{
Result = USB_SUCCESS;
}
}
/*SET FEATURE for Device*/
else if (RequestNo == SET_FEATURE)
{
if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP)
&& (pInformation->USBwIndex == 0))
{
Result = Standard_SetDeviceFeature();
}
else
{
Result = USB_UNSUPPORT;
}
}
/*Clear FEATURE for Device */
else if (RequestNo == CLEAR_FEATURE)
{
if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP
&& pInformation->USBwIndex == 0
&& ValBit(pInformation->Current_Feature, 5))
{
44 河南城建学院本科毕业设计(论文) 附录
Result = Standard_ClearFeature();
}
else
{
Result = USB_UNSUPPORT;
}
}
}
/* Interface Request*/
else
{
/*SET INTERFACE*/
if (RequestNo == SET_INTERFACE)
{
Result = Standard_SetInterface();
}
}
/* EndPoint Request*/
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
/*CLEAR FEATURE for EndPoint*/
if (RequestNo == CLEAR_FEATURE)
{
Result = Standard_ClearFeature();
}
/* SET FEATURE for EndPoint*/
else if (RequestNo == SET_FEATURE)
{
Result = Standard_SetEndPointFeature();
if (Type_Recipient == (STANDARD_REQUEST |
INTERFACE_RECIPIENT))
45 河南城建学院本科毕业设计(论文) 附录
}
}
else
{
Result = USB_UNSUPPORT;
}
if (Result != USB_SUCCESS)
{
Result = (*pProperty->Class_NoData_Setup)(RequestNo);
if (Result == USB_NOT_READY)
{
ControlState = PAUSE;
goto exit_NoData_Setup0;
}
}
if (Result != USB_SUCCESS)
{
ControlState = STALLED;
goto exit_NoData_Setup0;
}
ControlState = WAIT_STATUS_IN;/* After no data stage SETUP */
USB_StatusIn();
exit_NoData_Setup0:
pInformation->ControlState = ControlState;
return;
}
46
发布者:admin,转转请注明出处:http://www.yc00.com/news/1687366615a4657.html
评论列表(0条)