admin管理员组

文章数量:1567521

2024年1月11日发(作者:)

毕 业 设 计 [论 文]

题 目: 基于STM32的USB虚拟串口

学 院: 电气与信息工程学院

专 业: 电气工程及其自动化

姓 名:

学 号:

指导老师:

完成时间: 2015年5月19 日

河南城建学院本科毕业设计(论文) 中文摘要

摘 要

USB接口是最为简单的接口,它具有传输速度快、即插即用、端口扩展简单有效等特点,在数据传输技术飞速发展的当代USB接口得到广泛的应用。越来越多的电脑设备开始采用USB接口进行数据的传输,而通用异步串行通信口(简称串口或者COM口)是一种比较古老的串行通信口,在几年前的PC上,几乎是必备接口。以前的设备与PC相连基本上都是用的COM口,那么将设备移植到USB接口成为人们研究的热门。

本论文以USB通信设备类中的抽象控制模型为基础,对通信设备类及实现虚拟设备的原理进行了研究,设计并实现了基于通信设备类的虚拟串口驱动程序。

论文研究设计了基于STM32单片机的USB虚拟串口驱动程序的结构和实现方案,该程序主要由通信命令转换和数据传输两部分构成,虚拟串口的实现技术在数据传输方面进行了改进。论文的主要工作如下:

1.研究了USB协议的请求和传输模式,分析了通信设备类实现虚拟设备的方案。

2.给出了一种符合通信设备类中抽象控制模型的虚拟串口实现方案。该方案提供

了一种基于通信设备类开发虚拟设备的模板,对设计中的诸多问题进行了详细的说明,并改进了虚拟串口驱动程序中数据的处理流程。

3.将改进后的数据处理流程是现在虚拟串口中,生成的一种基于通信设备类的虚拟串口稳定、高速。最后,在串口测试软件下对虚拟串口驱动程序进行了测试,达到了预期目标。

关键字: 通讯设备类,枚举过程,虚拟串口程序,抽象控制模型

I

河南城建学院本科毕业设计(论文) Abstract

Abstract

USB interface is the most simple interface, it has the transmission speed, plug and

play, port extension characteristics such as simple and effective, in rapid development of

the contemporary USB data transmission technology has been widely used. More and more

computer equipment used USB interface for data transmission, and the universal

asynchronous serial communication port (hereinafter referred to as a serial port or COM) is

a relatively old serial communication port, in a few years ago on a PC, is almost a

necessary interface. Before the equipment connected to the PC are basically use the COM,

then transplanted device into the USB interface become a hot research.

Abstract in this paper by USB communication device class control model, based on

the communication device class and realize the principle of virtual device are studied,

designed and implemented based on the virtual serial port communication device class

driver.

Thesis study design based on the STM32 MCU USB virtual serial port driver

structure and implementation scheme of the program is mainly consisting of

communication command conversion and data transmission, the implementation

technologies of virtual serial port is improved in terms of data transmission. Paper's main

work is as follows:

study the requests of USB protocol and transmission mode, analyzes the

communication device class implementation scheme of virtual devices.

ts a communication device class of control model of the implement of virtual

serial port. This scheme provides a virtual device based on the communication device class

development of templates, to account for the problems in detail in the design, and improve

the virtual serial port driver in data processing.

processing of the improved process is now in virtual serial port, the generated

based on the virtual serial port communication device class stability, high speed. Finally,

under the serial test software of virtual serial port driver was tested, and reached the

anticipated goal.

Keywords: Communication

equipment Class ;The enumeration process;

Abstract Control Model

II

河南城建学院本科毕业设计(论文) 目录

目 录

摘 要 ........................................................................................................................................................ I

Abstract ..................................................................................................................................................... II

目 录 ........................................................................................................................................................ III

第1章 绪论 .............................................................................................................................................. 1

1.1 USB虚拟串口设计背景及其意义 ............................................................................................. 1

1.2 USB虚拟串口设计研究方法及目标 ....................................................................................... 2

1.3 USB虚拟串口设计国内外研究现状 ....................................................................................... 2

第2章 USB及串口简单介绍 ................................................................................................................. 4

2.1 USB简介 ................................................................................................................................... 4

2.2 串口简介 .................................................................................................................................... 4

2.3 USB虚拟串口简介 ................................................................................................................... 5

第3章 USB和USB CDC协议 ................................................................................................................... 6

3.1 通用串行总线USB ................................................................................................................... 6

3.1.1 USB协议相关知识介绍 ............................................................................................... 6

3.1.2 USB协议枚举过程分析 ............................................................................................... 8

3.2 USB CDC协议 .......................................................................................................................... 9

3.3 USB通信过程 ......................................................................................................................... 10

第4章 虚拟串口的实现 ........................................................................................................................ 12

4.1 串口的工作原理 ...................................................................................................................... 12

4.2 USB虚拟串口设计 ................................................................................................................. 13

4.2.1 STM32 USB部分说明 ................................................................................................ 13

4.4.2 USB电路连接 ............................................................................................................. 14

4.2.3 虚拟串口程序设计 ...................................................................................................... 15

第5章 结论 ............................................................................................................................................ 18

参考文献 .................................................................................................................................................. 19

致 谢 ...................................................................................................................................................... 20

附录: ...................................................................................................................................................... 21

III

河南城建学院本科毕业设计(论文) 第1章 绪论

第1章 绪论

1.1 USB虚拟串口设计背景及其意义

USB作为一种计算机总线技术,在现在的计算机上已经是不可或缺的了。看看我们身边的计算机外部设备,很多都是通过USB口连接计算机的:键盘、鼠标、打印机、数码相机、移动硬盘、优盘、移动光驱、扫描仪、MP3、MP4以及游戏手柄等,还有一些我们不太常见的USB设备,例如一些带有USB口协议的仪表仪器、烧录机、开发用的调试器、USB网卡、USB耳机、USB话筒及USB电话,此外,还有一些移动电话(手机)也具备USB口。许许多多的外设似乎都是通过USB和计算机相连的,可见USB是都么的强大。

USB具有速度快,连接简单方便,可扩展性强,支持热插拔操作和标准统一的特点,所以才会被使用如此广泛。当前的个人主机都配备有好多USB接口。然而在现代的工业设备中,许多的设备都是嵌入式系统,基本上都是采用最常用的标准外设异步串行通信接口(串口),那么如何在没有串口的情况下得到串口数据,并完成数据传输成为一个亟待解决的问题。

通用异步串行通信口(串口)随着USB的流行已经慢慢开始退出历史舞台了。但是很多的设备开发者,都喜欢使用串口与计算机进行通信,因为串口使用起来简单方便。那么问题就来了,现在的PC上基本上都是USB口没有串口,那么怎么跟设备的串口进行连接通信呢?有没有办法可以在计算机上新增加串口呢?这是必须可以的,通过使用PCI卡设计一个或者多个串口。当然,还可以通过USB口模拟出串口设备,因为USB也是一种总线,总线就可以连接不同的设备。所以我们就可以设计一个USB转串口的器件来解决这个问题。

这次设计的预期成果和市场上出现了一些USB转串口的芯片或者USB转串口数据线相似,大致结构是为了实现USB接口转串口,所以数据线一端是USB口,一端是串口,在串口线段完成串口到USB协议的转换。USB接口在连接计算机的时候,另一端串口端需要被操作系统识别,这说明USB接口对用户基于串口的应用程序和传统的串口调试工具是公开的,所以PC端的调试和应用程序不用做修改就可以被开发者识别。由于这些器件的USB类不属标准的USB类,因此需要安装必要的驱动在操作系统上。另外由于这些设备驱动不是操作系统自带的,而且需要多次转换在通信阶段,调试会遇到问题限制USB串口器件的应用,因为在调试期间常常无法确定是串口出了问题还是USB出了问题。

1

河南城建学院本科毕业设计(论文) 第1章 绪论

设备通信类(Communication Device Class)是USB组织定义的一类专门给各种通信设备使用的USB子类,是一种可以实现虚拟串口通信的协议。CDC类对实现USB接口和串口之间的转换提供了一个很好的解决办法。而且CDC类是USB的一个子类,操作系统默认提供此类驱动,故可以解决USB转串口类器件传输不稳定的问题。

1.2 USB虚拟串口设计研究方法及目标

本次设计所用到的是采用STM32来实现USB虚拟串口的。STM32系列控制器具有低成本、低功耗、高性能的特点,它自身带的USB模块符合USB2.0规范和OTG1.3规范,支持全速12Mbps和低速1.2Mbps两种模式。而且STM32官方封装了很多库函数,对于编写USB驱动节省了很多时间。本文研究了USB CDC协议并在理解USB体系结构,在STM32平台上通过分析USB枚举过程实现了USB虚拟串口,达到了USB与串口通信的预期目的。

1.3 USB虚拟串口设计国内外研究现状

国内的现开发设备控制芯片研究技术不高,只有中国台湾地区的许多公司可以生产这种转换的设备,并提供功能齐全的开发接口和文档说明。国内集成电路的设计开发公司的能力还有限,限于提供不太复杂的应用及单一产品中,并且在国内的市场占有率还很小,目前正处于蓬勃发展的阶段。

USB和串口之间的转换实现,有硬件实现和软件实现两种。硬件实现一般需要设计专用的设备控制芯片。设备控制芯片分为通用设备控制器,定位于某几类USB产品的编程应用;专用设备控制器,定位于某一个USB产品的应用。通用设备控制器大部分被国外芯片垄断,国内在专用设备控制器已有所发展。

虚拟串口设备的设计是一个很重要的部分,现在国内外已有很多商业上成熟的此类接口转换器,都把重点放在了这个设计上面。设计一个列举虚拟串口的驱动程序是判断一个好的转接器的重要指标。在这种情况下,PC端的应用软件依然是针对RS-232串行端口编程的,外设也是以RS-232为数据通信通道,但从PC到外设之间的物理连接却是USB总线,其上的数据通信也是USB数据格式。用这种方式有两个好处,一是可以保护原有的软件开发投入,并且在不用修改RS-232外设应用的情况下,便可继续使用;二是使USB总线的高传输速率和即插即用的特性得到了充分利用。虚拟串口的最初就是把网口的操作映射为对串口操作就是把串口转为网络通信接口。

传统的串口总线在许多方面都得到了大量的应用。例如在传统的售饭系统、POS 2

河南城建学院本科毕业设计(论文) 第1章 绪论

消费系统、门禁系统和一些其中控制系统等。传统的串口总线也有一些局限性。与网络相比的局限性在于它的传输距离和可靠性。所以在这个互联网飞速发展的时代,传统的串口总线可以选择通过TCP/IP网络实现网络连接的方式进行连接,这样就可以解决传统串口在传输距离和可靠性两方面较大的局限性。通过网络连接可以创建一个平台软件,利用这个平台软件和电脑串口连接完成来收发数据,假如按照先前的连接方式势必要改变该平台软件的工作方式,要解决这个问题使平台软件不用改变工作方式,可以在电脑平台上安装虚拟串口驱动,这样硬件转换器从网络上传来的数据就可以通过虚拟串口驱动定向传输到一个虚拟串口上。这样,传统的串口总线就可以利用网络创建平台软件并通过虚拟串口进行数据收发。

USB和串口之间的转换实现,还有一种实现是软件实现。这里的软件实现主要指设计USB转串口的驱动程序。在USB中CDC子类成为规范之前,USB转串口的驱动程序的实现各种各样,且基于特定的设备,通用性较差。USB中CDC子类中抽象控制模型规范了虚拟串口实现的框架,增强了虚拟串口驱动程序的通用性。

3

河南城建学院本科毕业设计(论文) 第2章 USB及串口简单介绍

第2章 USB及串口简单介绍

2.1 USB简介

USB是通用串行总线的缩写,英文是Universal Serial Bus。顾名思义,它是一个外部总线的标准,已有10多年的历史,它的功能主要是用于简化计算机和外部设备的连接,增加外设的易用性。在以前的计算机中,如果要连接外部设备,必然需要关掉计算机甚至要打开机箱之后才能连接或者是更换外设,还要在硬件上分配资源,最后重启计算机才能正常工作。这一过程是相当的不方便,而USB能够在计算机运行过程中随意地接入并能立刻识别投入使用,这样的特性叫做即插即用(Plug and Play)。这一特性是计算机变得更加容易使用,更加大众化。另外USB传输速度极快,具有很强的可扩展性,它可以连接的非常多的外设。比如:键盘、鼠标、耳机、移动硬盘等。

USB设备主要有以下优点:

1.方便携带。USB设备通常很小,很轻,比如常见的U盘,非常的小,但是内存容量却是相当的大。

2.即插即用。这使计算机用户不再做重复的开关机,连接更换设备避免了许多麻烦的步骤,简单方便。

3.可扩展性。计算机上往往有很多个USB接口,可以同时连接多个外设,最高可连接127个设备。

4.标准统一。常见的是串口的鼠标键盘,并口的打印机扫面议,可是有了USB之后,这些应用外设都可以和计算机直接相连,这时就有了USB硬盘,USB鼠标,等等。

2.2 串口简介

串口简单来说就是串行通信接口,其采用的是串行通信方式。其通信线只有一根用来传输数据,数据是按一位一位顺序传送这种传输方式的。这样的传输方式既简单又能降低很多成本,故此种接口被很多嵌入式系统采用。来自CPU的并行数据字符可以被串行接口接收并转换为连续的串行数据流发送出去,同时给CPU器件发送串口接收串行数据并转换为并行的数据字符。一般完成这种功能的电路,称为串行接口电路。串口可用于许多用途,比如连接打印机、鼠标、键盘或者Modem,同时也可连接工业仪器的仪表。在本文中将简单介绍这种串行接口的工作原理,并详细讲解串 4

河南城建学院本科毕业设计(论文) 第2章 USB及串口简单介绍

口的编程方法。串口适用于长距离通信,但其传输速率较慢。串口通信总共分为单工、半双工和全双工三类。只支持数据在一个方向上传输称为单工数据传输;允许数据在两个方向上传输称为半双工数据传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;允许数据同时在两个方向上传输称为全双工数据通信,因此,全双工通信结合了两个单工通信方式,它要求发送设备和接收设备都有独立的接收和发送能力。

串口通常有两个端口分别是RXD和TXD,RXD是用于接收的一端,TXD是用于发送的一端。串口将接收端连接另一个设备的发送端,发送端连接另一个设备的接收端,然后通过CLK的时序就可以进行数据的发送与接收了。

2.3 USB虚拟串口简介

USB通信设备类在物理层通过USB总线,采用虚拟串口的方式为主机提供一个物理串口。在系统内部,USB芯片提供一个批量传输IN端点和一个批量传输的OUT端点,用于数据的接受和发送,模拟串口的RXD线和TXD线;另外,芯片还提供中断IN端点,发送当前串口的状态,实现对串口传输的控制。串口设备的数据,由系统的串口采集,在芯片内完成USB包的封装,通过USB总线上传至主机,再由相应的串口应用程序(串口调试助手)进行处理。对用户来说,看到的是基于串口的数据采集和传输,而实际上实现的是基于USB协议包的数据传输。

5

河南城建学院本科毕业设计(论文) 第3章 USB和USB CDC协议

第3章 USB和USB CDC协议

3.1 通用串行总线USB

3.1.1 USB协议相关知识介绍

一、USB2.0协议

USB总线属一种轮训方式的总线,所有的数据通过主机控制端口进行初始化,每一总线执行动作最多传送三个数据包。主机在每次数据传输开始按照传输前制定好的原则发送描述传输种类、传输方向,以及USB设备地址和终端号的数据包,这就是所谓的标志包(token packet)。USB设备从解码后的数据包的适当位置取出属于自己的数据。数据传输方向要么是从设备到主机,要么从主机到设备,两个传输方向。标志包在传输开始时会标志数据的传输,包括数据传输的种类及方向,随后包含信息的数据会被发送端发送,如果没有数据传送,则发送端会表明没有数据传送。接收端会表明是否传送成功,依据是发送一个相应的握手包的数据包。在主机和设备的端口之间,发送端和接收端之间的USB数据传输,可被视为一个通道。存在两种类型的通道:流和信息。流的数据不像消息的数据,它没有USB所定义的结构,而且通道与数据带宽、传送服务类型,端口特性(如方向和缓冲区大小)有关。多数通道在USB设备设置完成后即存在。USB中有一个特殊的通道——缺省控制通道,它属于消息通道,当设备一启动即存在,从而设备的设置、查询状况和输入控制信息提供一个入口。

事务预处理允许对一些数据流的通道进行控制,从而在硬件级上防止了对缓冲区的高估或低估,通过发送不确认握手信号从而阻塞了数据的传输速度。当不确认信号发过后,若总线有空闲,数据传输将再做一次。这种流控制机制允许灵活的任务安排,可使不同性质的流通道同时正常工作,这样多种流通道可在不同间隔进行工作,传送不同大小的数据包。

二、USB描述符

USB2.0协议定义的标准描述符有设备描述符(Device Descriptor)、配置描述符(Configuration Descriptor)、接口描述符(Interface Descriptor)、端口描述符(Endpoint

Descriptor)、字符描述符(String Descriptor)及Device Qualifier Descriptor和Other Speed

Configuration Descriptor,其后两个是新加的标准描述符。

一个USB设备只要有一个设备描述符。设备描述符里决定了该设备有多少种配置,每种配置都有一个配置描述符;而在每个配置描述符中又定义了该配置里有多少 6

河南城建学院本科毕业设计(论文) 第3章 USB和USB CDC协议

个接口,每个接口都有一个接口描述符;在接口描述符里有定义了该接口有多少个端点,每隔端点都有一个端点描述符;端点描述符定义了端点的大小、类型等。如果有类特殊描述符,它跟在相应的接口描述符之后。由此可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,接下来是配置描述符,再接下来是接口描述符,最下面是端点描述符。在主机获取描述符时,首先获取设备描述符,接着在获取配置描述符,然后再根据配置描述符中的配置集合的总长度,一次将配置描述符、接口描述符、类特殊描述符(如果有)、端点描述符一次读回。对于字符串描述符,是单独获取的。主机通过发送获取字符串描述符的请求以及描述符的索引号、语言ID来获取对应的字符串描述符。

例如一个USB鼠标,设备有一个设备地址,USB主机依靠的就是这个设备地址来访问的。然而设备要和USB设备进行通信,单单靠设备地址是不够的,还要有一个端点地址。有了设备和端口地址,就可以准确地对端点发送以及读取数据了。而配置和接口,就是为了能够更方便的管理端点而抽象出来的概念。一个设备可以有多个配置,但是同一时刻只能有一个配置是可用的,每个配置下又可以有多个接口,当我们需要不同的功能时,只要选择不同的配置即可。

总的来说,接口就是端点的集合,配置就是接口的集合,设备就是配置的集合。所以我们只要弄清楚它们之间的关系,就能按照要求来构造出一个合格的USB设备。假如一个设备的各种描述符成功返回了,就可以说成功一大半了。

设备

配置

接口

端点

图3.1 设备、配置、接口、端点之间的关系

三、USB枚举

枚举就是介绍主机如何将连接设备,从设备如何读取信息,了解设备的类型,了解主机如何进行通信,最后使主机根据枚举获得的信息来加载合适的驱动程序。枚举是调试USB设备很重要的一点,枚举是判断USB设备连接的重要指标,只要枚举成功了,那么USB设备的调试也就基本成功了。

7

河南城建学院本科毕业设计(论文) 第3章 USB和USB CDC协议

3.1.2 USB协议枚举过程分析

USB协议定义了设备的6种状态,枚举过程会经历4种状态的迁移:上电状态,默认状态,地址状态和配置状态(其他两种是连接状态和挂起状态)。

USB主机在枚举到USB设备插入后,就该对设备进行枚举了,枚举就是从设备读取描述符信息,然后主机通过读取的信息来加载符合要求的驱动程序,从而识别连接的是什么设备,该如何进行通信等。调试USB设备中USB的枚举过程是很重要的,只要枚举成功了,那么工作就差不多了。

在枚举之前先要了解USB的一种传输模式:控制传输。这种传输模式是非常重要的,其作用是确保数据的正确性,设备在枚举过程中使用的就是控制传输这种传输模式。它可以分为三个过程:建立过程、可选的数据过程及状态过程。

第一个过程是由USB主机发起的。它开始与一个SETUP令牌包,紧跟一个DATA0数据包,然后就是数据过程了。对于控制读传输,数据过程就是输入数据;对于控制写传输,数据过程就是输出数据。假如在这一过程中,数据长度为0,那么就没有数据过程了。数据过程之后是状态过程。状态过程和数据过程的数据传输的方向是恰好相反的:对于控制读传输,状态过程是一个输出数据包;对于控制写输入,状态过程就是一个输入数据包。最后一个过程来判断数据是否已经正确传输了。

枚举的详细过程:

设备描述符的获取。USB主机在检测有USB设备连接插入后,会对该设备进行复位。复位后的地址为0,主机可以通过地址0和该USB设备进行通信。主机向地址为0的设备的端点0发送获取设备描述符的标准请求。设备收到请求后,按照主机请求参数将设备描述符返回给主机。主机正确获取一个数据包的设备描述符后,会返回给设备一个长度为0的确认数据包(状态过程)从而进入设置地址阶段。且需要注意,主机读取数据包的设备描述符的机会只有一次,一般的设备描述符有18个字节,然而有的USB设备的端点0大小不到18字节,可是USB主机也只能发送一次请求。所以,当设备端点0大小不满足要求时,这个问题就需要注意了。

地址的获取。USB会在控制传输的建立过程发送一个设备地址请求给设备的端点0(地址为0),建立过程的数据包中会包含一个新的设备地址。USB主机负责管理具体的地址,主机会给刚刚接入的设备分配一个唯一的地址。设备收到建立过程之后,就进入了状态过程,原因是此控制传输没有数据过程。设备在收到输入令牌包后会返回长度为0的状态数据包。若该状态包被主机确认正确收到,那么主机就会发送给设备应答包ACK,设备收到之后便会启用新的设备地址。这样主机就可以按照设备分配到的唯一的地址来访问此设备了。

8

河南城建学院本科毕业设计(论文) 第3章 USB和USB CDC协议

主机对设备描述符的再次获取。这次的获取有点特别,第一,主机是使用新的设备地址来访问设备,而不再使用地址0;第二,这次获取的设备描述符全部是18字节的,假如端点0最大包长度小于18字节,则主机就会发送多个IN令牌包来完成多次数据输入请求。

主机对配置描述符的获取。主机先获取配置描述符,然后获取配置集合,主机获取集合的方式是根据配置描述符描述的配置集合的总长度来获取的。配置描述符和配置描述符集合的请求差不多,区别就是指定长度不同。有些主机直接使用最大长度来获取配置描述符集合,而不是单独获取配置描述符,原因是设备实际返回的数据可以少于指定的字节数。配置描述符由端点描述符、类特殊描述符、接口描述符、配置描述符等组成。端点描述符、类特殊描述符、端点描述符是不能单独获取的,而是以一个集合的方式跟随配置描述符一并返回。

枚举就相当于主机与USB连接的一个过程,为了能够进行数据交换的一个相互识别的过程。枚举完成后,主机就可以对USB设备进行读写操作了。

3.2 USB CDC协议

什么是CDC类?USB的CDC类是USB通信设备类(Communication Device Class)的简称。CDC类是USB组织定义的一类专门给各种通信设备(电信通信设备和中速网络通信设备)使用的USB子类。根据CDC类所针对通信设备的不同,CDC类又被分成以下不同的模型:USB传统纯电话业务(POTS)模型,USB ISDN模型和USB网络模型。其中,USB传统纯电话业务模型,又可分为直接线控制模型(Direct Line

Control Model)、抽象控制模型(Abstract Control Model)和USB电话模型(USB

Telephone Model),如3.2图所示。本文所讨论的虚拟串口就属于USB传统纯电话业务模型下的抽象控制模型。

直接线模型

电话业务模型

ISDN模型

网络模型

CDC类

抽象模型

电话模型

图3.2 CDC分类

9

河南城建学院本科毕业设计(论文) 第3章 USB和USB CDC协议

3.3 USB通信过程

USB通信传输的基本单位是“包”,学习USB通讯的关键在于理解“包”概念,了解USB主机是如何发送命令给设备,然后设备是怎样对主机的命令做出响应的。

USB数据包的格式如3.1表所示:

表3.1 USB数据包的格式

Field

Bits

PID

4+4

ADDR

7

11

ENDP

4

Frame Number

DATA

N*8(N=0,...,1024)

CRC

5/16

数据包直接跟在PID之后,如图所示,数据域的长度为N字节,数据域之后以16位的CRC校验和结束。握手包没有数据,没有校验和,仅有PID域。Start-Split和Complete-Split包会在分离传输中用到,是一类特殊的包。

其格式如表3.2、3.3所示:

表3.2 Start-Split包

SPLID

PID

8

Hub

Addr

7

Field

Bits

SC

1

Port

7

S

1

E

1

ET

2

CRC5

5

表3.3 Complete-Split包

Field

Bits

SPLID

PID

8

Hub

Addr

7

SC

1

Port

7

S

1

U

1

ET

2

CRC5

5

10

河南城建学院本科毕业设计(论文) 第3章 USB和USB CDC协议

包标识符PID的作用是识别包的类型。它共有8位,其中USB协议用到的只有4位(PID0-PID3),其余4位是前边4位的取反(PID4-PID7),作用是校验PID。USB协议规定了4类包:令牌包、数据包、握手包和特殊包。

USB2.0协议中规定的各种PID如表3.4所示:

表3.4 USB2.0中定义的各种PID

PID类型 PID名

OUT

令牌包

IN

SOF

SETUP

DATA0

数据包

DATA1

DATA2

MDATA

ACK

握手包

NAK

STALL

NYET

PRE

ERR

特殊包

SPLIT

PING

PID[3:0]

0001B

1001B

0101B

1101B

0011B

1011B

0111B

1111B

0010B

1010B

1110B

0110B

1100B

1100B

1000B

0100B

0000B

确认

不确认

挂起

未准备好

前导(这是一个令牌包)

错误(这是一个握手包)

分裂事务(这是一个令牌包)

PING测试(这是一个令牌包)

保留,未使用

不同类的数据包

说 明

通知设备将要输出数据

通知设备将要输入数据

通知设备这是一个帧起始包

通知设备将要开始一个控制传输

如上表3.4所示,令牌包由4个包组成:输出包、输入包、设置包和帧起始包。其中输入、输出包和设置包的格式一样:SYNC+PID+ADDR+ENDP+CRC5。帧起始包的格式是:SYNC+PID+11位FRAM+CRC5。

数据包由4中不同的包组成,分别是DATA0包、DATA1包、DATA2包、MDATA包。当USB进行数据传输时,若发送的数据长度大于相应端点容量时,数据包会被分为好几个包,然后交替发送。

结构最为简单的是握手包,其格式为SYNC+PID。

11

河南城建学院本科毕业设计(论文) 第4章 虚拟串口的实现

第4章 虚拟串口的实现

4.1 串口的工作原理

串行口是一种常用的接口,具有连接简单易识别,所需要的连接线很少等特点,在计算机接口方面得到广泛的使用。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”该标准规定采用一个 25 个脚的

DB25 连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。

同步通信方式和异步通信方式这两种是串口进行通信的主要方式。同步通信方式的效率较高。因为在同步通信方式下,通信双方是通过共享一个单位时钟或电视脉冲来保证通信双方在通信时是以相同的时钟频率进行,不但准确协调,而且保证发送方和接收方的准确同步,所以效率较高;异步通信方式的效率较低。因为在异步通信方式下,通信双方要按照异步通信协议进行传输,且数据传输的单位是字符,异步通信顾名思义,不要求通信双方在相同的时钟下进行传输,而是收发方可采用各自的时钟源,这样就会导致发送方传送字符的时间间隔不确定,所以发送效率相比同步传送效率要低一些。

串行端口会在发送数据的每一个字节前发送一个开始位,该单位的值为0。然后会在发送数据的每一个字节后发送一个停止位,表示已经完成传输。另外,端口还可以发送奇偶校验位。

下面介绍一下波特率、数据位、停止位和奇偶校验位。

波特率。模拟线路信号的速率,也称调制速率,以波形每秒的振荡数来衡量,其单位是波特(Baud)。波特率与比特率的关系是比特率=波特率X单个调制状态对应的二进制位数。波特率用来衡量通信速度。假如5000波特率表示每秒钟5000个bit。如果协议需要6800波特率,那么时钟就是6800HZ,因为时钟周期就是指波特率。通常电话线的波特率是36000,28800和14400。波特率和距离成反比,所以可以远大于这些值。

数据位。数据位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。当计算机发送一个任意位的信息包时,信息包的标准值是5、7和8位,实际的数据不会是8位的。可以根据你想要传送的信息来 12

河南城建学院本科毕业设计(论文) 第4章 虚拟串口的实现

自行设置。每个包是指一个字节,包括开始和停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”便可以指任何通信的情况。

停止位。它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。数据在传输线上是定时的,每个设备都有自己的时钟,这样就有可能出现两个通信设备在通信过程中在数据线上发生不同步。所以停止位在表示每次传输结束的同时还可以提供给主机更多校正时钟的机会。停止位愈多,不同时钟同步的容忍程度就愈大,但是由于校正时钟的次数过多,当然数据传输的速度就会大大降低。

奇偶校验位。奇偶校验位在通信中是一种简单的检错方法。有4种检错方式:高、低、偶、奇。当然奇偶校验位是可有可无的。串口会设置校验位,一般会设置数据位的后面一位,用一个值来确保数据传输逻辑高位的奇偶性。举个例子如果数据是011,那么偶校验的校验位就是偶数个。对于奇校验校验位是1,那么就会有3个逻辑高位。高位和低位不是数据检查,而是简单的校验逻辑高位和逻辑低位。这样会有效消除噪声对通信的干扰或者判断传输和接收数据是否同步。

4.2 USB虚拟串口设计

4.2.1 STM32 USB部分说明

STM32的USB模块可以产生三种中断:USB唤醒中断、USB高优先级中断和USB低优先级中断,在STM32的参考手册中没有详细说明这三种中断对应哪些事件,现说明表4.1所示:

表4.1 STM32的USB模块分类

STM32的USB模块

USB中断唤醒

USB高优先级中断

在中断向量表中的位置是42。这个中断在USB设备从暂停模式唤醒时产生,唤醒事件由USB_ISTR寄存器的WKUP位标识。

在中断向量表中的位置是19。这个中断仅由USB同步(Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件产生,正确传输事件由USB_ISTR寄存器的CTR位标识。

在中断向量表中的位置是20。这个中断由所有其它的USB事件产生,USB低优先级中断

例如正确传输、USB复位等,事件标志位在USB_ISTR寄存器中。 在STM32的USB开发包的例子中包含了上述中断的处理,例如在USB扬声器的例子中,CTR_HP函数处理USB高优先级中断;在所有例子中都有USB_Istr()函数处理USB低优先级中断。

13

河南城建学院本科毕业设计(论文) 第4章 虚拟串口的实现

USB如何区分低速、全速和高速设备:对于全速和高速设备,上拉电阻是接在D+上;而低速设备则是上拉电阻接在D-上。

USB系统中只允许有一个主机,主机分为3个不同的功能模块:应用软件、USB系统软件和USB总线接口。客户软件负责和USB设备的功能单元进行通信,以实现其特定功能,它需要开发人员自行开发,包括USB设备驱动程序和界面应用程序两部分。客户软件不能直接访问USB设备,其与功能单元的通信必须经过USB系统软件和USB总线接口模块才能实现。

4.4.2 USB电路连接

USB设备可以含有一个或者多个配置,USB的设备构架从主机角度上讲,是由一些端点、接口和配置都成的USB设备。一个或者多个接口可以构成一个配置,前边也有讲到设备、配置、接口及端点它们之间的关系,所以每个接口会有若干个端点。其中,端点来完成实际的数据传输,而接口和配置只不过是对USB设备功能的抽象,是虚拟出来的,没有更多实际的意义。而它的作用就是能够指明USB设备连接时必须采用何种接口和配置。USB设备的构架需要用到许多描述符,也就是前边详细介绍的那5种描述符:字符串描述符、端点描述符、接口描述符、配置描述符和设备描述符等。这些描述符常常在USB接口芯片的固件中被保存。

图4.1 电路接线

14

河南城建学院本科毕业设计(论文) 第4章 虚拟串口的实现

4.2.3 虚拟串口程序设计

USB虚拟串口程序设计的设计程序要根据CDC类通信协议来编写。主要的就是设备描述符,设备描述符部分是通过枚举过程获取的。主机只有把USB设备的描述符写成虚拟串口的描述符,才能完成识别串口。描述符的内容是数组的成员,一个数组包含了设备描述符,此程序设备描述符就是一个数组。

下面的设备描述符即是数组:

表4.2 设备描述符程序

const uint8_t Virtual_Com_Port_DeviceDescriptor[] =

{

0x12, /* 描述符字节长度*/

USB_DEVICE_DESCRIPTOR_TYPE, /* 设备描述符类型*/

0x00,

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 /* 可能配置数,指配置字符串的个数*/

};

15

河南城建学院本科毕业设计(论文) 第4章 虚拟串口的实现

具体的步骤是,首先USB主机在枚举前期先发送SETUP包,其次USB主机将会获取设备描述符,然后主机识别设备类型,接着主机根据设备类型加载正确的驱动,这样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配置成上拉的。这是上拉电阻开始使三极管导通,从而加上一个1.5K的电阻在时DP脚上。这样枚举就开始了。

第二个函数Set-USBClock(),这个函数的作用就是先将AP1总线经过PLL分频,获取AP1时钟,然后使得USB时钟开始工作。

第三个函数USB-Interrupts-Config(),顾名思义,这个函数是配置USB中断的。在该函数中含有USB中断和串口中断这两个中断。优先级方面由于没有设定它们抢占优先级的程序,所以它们拥有相同的优先级分组。这两个中断不会存在嵌套关系,因为它们的抢占优先级相同,USB的响应优先级为0,串口的响应优先级为1,所以任何一个中断都不会影响另一个中断的运行。

最后是USB_Init()。第一句是将pInformation 指向Device_Info结构体;第三句是将pPropert指向Device_Property结构体;第四句将pUser_Standard_Requests指针指向User_Standard_Requests结构体。具体USB设备的枚举和功能实现就与这三个结构相关。最后一句实际上运行的是DEVICE_PROP中的Virtual_Com_Port_init()这个函数。这个函数通过查看可以看到几个函数:

_SerialNum(),可传变为Unicode字符串,这个是获取设备序列号。

On(),这个函数的作用是连接USB设备,但实质是为了让主机能够快速准确地检测到USB设备。

_Config_Default(),配置串口至缺省状态,波特率为9600,并且没有允许发送中断,允许了接收中断。

eState = UNCONNECTED,未连接状态。

16

河南城建学院本科毕业设计(论文) 第4章 虚拟串口的实现

到此初始化结束了。

在中断部分中,程序的串口的发送中断时为允许的,中断函数所定义的是串口的接收中断。那么数据是如何被串口发送的呢?可以用写寄存器方式来发送数据。只是写寄存器方式有很多缺点,有可能在传输的数据量过大时就会出现问题,主要是因为它没有办法判断发送缓冲是否为空。

串口接收中断调用的函数为USART_To_USB_Send_Data()。函数功能是为了USB端口能够从串口接收发送的数据。然后USB端口再把接收到的数据向主机发送,然后主机就可以和USB端口互相通信了。

在虚拟串口端还可以连接一个硬件,这样串口可以通过连接到的硬件给USB虚拟的串口处理器发送数据,数据发送完毕之后虚拟串口就可以通过设备的USB向主机发送数据。这样数据传输就完成了。USB设备对于主机而言就是一个串口设备,主机可以将USB串口设备当成一个COM来识别。这样我们就可以用串口调试助手查看接收到的数据。如果想要返回数据,也可以通过串口调试助手发送数据,并通过USB虚拟串口设备来返回该数据,这样就实现了双向通信。

17

河南城建学院本科毕业设计(论文) 第5章 结论

第5章 结论

在这个信息技术飞速发展的时代,USB接口通信技术也取得了飞速的发展。市面上所能见到的很多外设都开始使用USB接口进行数据通信。所以能够合理的实现运用USB的数据传输变得及其重要,USB通信的开发人员又将基于通信类的虚拟设备实现作为研究的重点。本论文对基于USB通信设备类的虚拟串口实现方案进行了研究,而且还研究了如何对虚拟串口驱动的加载、卸载及数据的高速传输和通信命令的转换等,基本实现了基于USB通信设备类虚拟串口驱动程序。该系统和与现有类似驱动程序相比具有符合通信设备类的高传输速度和抽象制模型等优点。此外该系统还具有相当好的兼容性,具有很大的应用前景。并且论文中对基于通信设备类的虚拟串口实现及对通信设备类的研究,对研究基于通信设备类的虚拟设备实现方案等设计人员具有很好的指导意义。

本论文主要完成以下工作:

1.通过认真阅读英文原版的Windows NT文件系统以及USB协议中的通信设备类的许多专业书籍,既学习了Windows驱动程序的一般简单的开发方法,又学习了符合USB协议的驱动程序的开发方法,并且对Windows驱动的工作原理进行了深入的研究;

2. 对虚拟串口技术实现技术做了深入的研究了,分析了那种实现方法好些,那种实现方法存在不足,并从中选择了通信设备类的抽象控制模型作为虚拟串口实现的理论依据,这样就解决了兼容性问题并且避免了重新设计USB转串口电路板,这使得虚拟串口驱动更高的通用性和更好的高效性,使得虚拟串口驱动有更广阔的应用前景;

3.对USB协议进行了认真的学习。分析和研究了USB通信设备类,并根据USB通信设备类中的各个模型的特点,将抽象控制模型确定为虚拟串口驱动所用的模型;按照设计目标,对虚拟串口驱动程序的总体结构和详细方案进行了认真的研究和分析,分析了虚拟串口驱动程序中的难点和重点问题进,优化了对问题的解决方法;

4.根据研究结果,实现了该驱动程序的演示版本,并对稳定性和兼容性进行了测试,通过测试总结出了系统中存在的不足之处,并对该系统的后续改进和完善做了许多工作。

18

河南城建学院本科毕业设计(论文) 参考文献

参考文献

[1]

Universal

Serial Bus Specification,Revision 2.0. Compaq,Hewlett-Packard,Intel,Lucent,Microsoft,NEC,Philips Inc[J],2000.

[2] 李肇庆,廖峰,刘建存.USB接口技术[M].北京:国防工业出版社,2004

[3] 刘荣.圈圈教你玩USB[M].北京:北京航空航天大学出版社,2009.1.

[4] 王成儒,李英伟.USB2.0原理与工程开发[M].北京:国防工业出版社,2004.

[5] 许永和.EZ-USB FX 系列单片机USB外围设备设计与应用[M].北京:北京航空航天大学出版社,2002.

[6] 周立功.USB2.0与OTG规范及开发指南[M].北京:北京航空航天大学出版社,2004.

[7] Walter Oney. Programming the Microsoft Windows Driver oft Press[J],2003.

[8] Chris g Windows WDM Device Drivers. Focal Press[J],1999.

[9] Jan Axelson. USB Complete: The Developer’s Guide[M]. Lakeview Research,2011.

[10] 肖踞雄,翁铁成,宋中庆.USB技术及应用设计[M].北京:清华大学出版社,2004.

19

河南城建学院本科毕业设计(论文) 致谢

致 谢

岁月如白驹过隙,一晃大学四年就这样匆匆而过,转眼间就快要毕业了,四年间疯过,笑过,有难忘的事,还有遗憾的事,不过大学四年过的很充实,很难忘。毕业论文也在我的认真学习和研究下,就要接近尾声了,在这里我要向所有给我帮助的人致以感谢,感谢给我指导、关心和支持的老师、同学,感谢远在家乡的亲人给我的关心和挂念。

首先,我要感谢我平易近人、知识渊博的侯宁老师。您治学严谨,高标准,严要求,对学术论文一丝不苟,对我的许多不懂的问题也是诲人不倦。我的理论学习和毕业论文能够顺利的完成,您的悉心指导和不断鼓励给了我非常大的帮助和动力。您知识渊博,对待生活积极乐观,在我毕业设计遇到阻碍时,您给予我鼓励,让我能够放轻松,积极乐观的去面对遇到的问题,真正的做到了师者:传道、授业、解惑。您在学习上给予我很多帮助,在毕业设计演示方面手把手教我调试助手工具的使用。您为人和蔼,处事沉着冷静,治学严谨,对知识的研究学习孜孜不倦的精神是我学习的良好榜样。在此向我敬爱的侯老师致以最衷心的感谢,祝福您身体健康、工作顺利、阖家欢乐、万事如意!

其次,感谢刘维同学,感谢你在软件使用和论文修改方面给予的支持和热情帮助。同时,感谢电气系所有的老师,您们的耐心教导让莘莘学子们能够学有所成,您们的谆谆教诲和渊博的专业知识让我获得了人生的一大笔财富——知识。感谢河南城建学院给予我这么好的学习环境和学习氛围,让我能够开开心心学知识,愉快的度过了大学四年的时光。

非常感激我的爸爸妈妈以及亲人,一直以来都是你们在默默地支持我、关心我、鼓励我,给了我无私的爱与感动。感谢我的父母,辛苦劳作换来我学习知识的机会,在我生活中遇到挫折的时候,是我的父母给我鼓励和支持,激励我勇敢向前,不怕失败和挫折,在父母的帮助和鼓励下,我跨过了生活中一道又一道的坎,让我如此的热爱生活。在未来的日子里,我会倍加努力,让自己成为你们的骄傲,让自己强大起来,是自己能够成为你们的依靠,来报答您们的含辛茹苦。

最后,感谢所有好朋友的帮助和关怀,希望大家能永远积极向上,工作顺利天天开心快乐!

20

河南城建学院本科毕业设计(论文) 附录

附录:

/* 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;

if(bDeviceState == CONFIGURED)

{

if(1 == Flag_USBSendOver && buff_ != 0) /*有数据需要USART_Rx_Buffer,USART_RX_DATA_SIZE); /*初始化接收循环队列*/

while (1){

21

河南城建学院本科毕业设计(论文) 附录

发送,上一次发送完成*/

{

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++)

UserToPMABufferCopy(USB_Tx_Buffer,

Queue_Read(&buff_in, &USB_Tx_Buffer[i]); /*读到发送缓冲区*/

ENDP1_TXADDR, 64); /*发送数据*/

SetEPTxCount(ENDP1,64);

SetEPTxValid(ENDP1);

}

else

{

temp = buff_; /*读取要发送的字节数*/

for(i=0;i!=temp;i++)

UserToPMABufferCopy(USB_Tx_Buffer,

Queue_Read(&buff_in, &USB_Tx_Buffer[i]); /*读到发送缓冲区*/

ENDP1_TXADDR, temp); /*发送数据*/

SetEPTxCount(ENDP1,temp);

SetEPTxValid(ENDP1);

22

河南城建学院本科毕业设计(论文) 附录

}

}

}

}

}

#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,

23

河南城建学院本科毕业设计(论文) 附录

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 */

24

河南城建学院本科毕业设计(论文) 附录

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 */

25

河南城建学院本科毕业设计(论文) 附录

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 */

26

河南城建学院本科毕业设计(论文) 附录

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 */

27

河南城建学院本科毕业设计(论文) 附录

#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*/

{

28

河南城建学院本科毕业设计(论文) 附录

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)

29

河南城建学院本科毕业设计(论文) 附录

|| (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;

30

河南城建学院本科毕业设计(论文) 附录

/* 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))

31

河南城建学院本科毕业设计(论文) 附录

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))

32

河南城建学院本科毕业设计(论文) 附录

{/*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);

}

33

河南城建学院本科毕业设计(论文) 附录

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);

}

}

34

河南城建学院本科毕业设计(论文) 附录

}

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)

35

河南城建学院本科毕业设计(论文) 附录

{

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

*pDesc)

{

uint32_t wOffset;

*Standard_GetDescriptorData(uint16_t Length, ONE_DESCRIPTOR

36

河南城建学院本科毕业设计(论文) 附录

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);

37

河南城建学院本科毕业设计(论文) 附录

}

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;

38

河南城建学院本科毕业设计(论文) 附录

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);

39

河南城建学院本科毕业设计(论文) 附录

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)

{

40

河南城建学院本科毕业设计(论文) 附录

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))

{

41

河南城建学院本科毕业设计(论文) 附录

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))

42

河南城建学院本科毕业设计(论文) 附录

}

}

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;

}

43

本文标签: 设备串口数据描述符虚拟