基于单片机的USB接口的设计.docx
《基于单片机的USB接口的设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的USB接口的设计.docx(11页珍藏版)》请在冰豆网上搜索。
基于单片机的USB接口的设计
单片机原理及系统课程设计
专业:
电气工程及其自动化
班级:
电气093
姓名:
马国祥
学号:
指导教师:
徐金阳
评语:
平时(40)
修改(30)
报告(30)
总成绩
兰州交通大学自动化与电气工程学院
2012年7月1日
1引言
本课程设计是在学习必修课《单片机原理与系统设计》之后,为加强对系统设计和应用能力的培养而开设的综合设计。
本课程设计的题目为基于单片机的USB接口的设计。
2设计方案
USB是近年来发展起来的一种快速、灵活的总线接口。
它最大的特点是易于使用,可热插拔,接口连接灵活,并且能够提供外设电源[4],在嵌入式系统及智能仪表中获得广泛的应用。
因此用51系列单片机实现USB主机接口,进而实现对USB外设的控制,对提高整个系统的数据存储、数据传输、设备控制等性能都有很大的作用。
本文论述的方案基于压强测试仪的应用环境,在开发压强测试仪的过程中根据实际的需求,要求能够存储大量数据,以往的解决方案是RS232C接口,但由于传输速度慢,在高速采样系统容易导致数据丢失,而且必须有上位机的参与,这对于室外作业很不方便。
测试仪器可以把采集到的数据保存到U盘,工作人员可以随时取下U盘,将数据拿到异地进行分析,另外笔者还开发了读写U盘的文件系统,存储的数据可以直接在PC机上打开,不需要编写其它的分析软件。
3硬件设计
3.1SL811HS概述
SL811HS是具有主/从两种工作模式的USB控制器[4],遵循USB1.1规范;可自动检测总线速率,支持全速12Mbps和低速1.5Mbps设备;具有8位双向的数据总线,易与单片机连接;片内256字节的SRAM(其中16字节为工作寄存器),用于数据传输;可自动产生SOF和CRC5/16,简化软件工作量;片内有根Hub;支持挂起/唤醒工作模式,减少功耗;支持地址自动加1功能,在连续读写过程中,只设置一次地址,其内部寄存器地址自动增加,在大容量数据通讯中非常必要的。
3.2单片机与SL811HS接口设计
图3.1所示是AT89C51与SL811HS的硬件连接电路。
在本设计中,由于所选用的单片机AT89C51及其外围元件的工作电压为5V,而SL811HS的工作电压为3.3V,所以系统应提供5V电压同时要进行电压转换。
虽然SL811HS可以使用12MHZ晶振,但在实际使用过程中,如果晶振质量不太好,电路稳定性就会比较差,因此,设计时推荐使用48MHZ有源晶振。
SL811HS的中断请求输出的是高电平,因此需要用反向器把它变换成低电平以满足AT89C51中断输入要求。
此外,应注意SL811HS是低电平复位。
为了便于调试,系统扩展了液晶显示器。
硬件完成后要进行测试,先向SL811HS寄存器中写入数据,之后读出数据并在液晶显示器上显示,如果和写入的数据相同,说明SL811HS与单片机连接正确。
再用示波器观察有源晶振是否起振,一切正常后便进入软件调试。
图3.1SL811HS与单片机的硬件连接图
4软件设计
4.1.USB枚举过程:
USB总线一般包含四种基本数据传输类型:
控制传输、中断传输、批传输以及同步传输,本系统使用的是控制传输和批量传输[3]。
最基本的函数就是对SL811HS寄存器的读写,代码可参照参考文献[5]。
读单个寄存器:
BYTESL811Read(BYTEa)
{SL811H_ADDR=a;
return(SL811H_DATA);
}
写单个寄存器:
voidSL811Write(BYTEa,BYTEd)
{SL811H_ADDR=a;
SL811H_DATA=d;
}
连续读SL811HS寄存器:
voidSL811BufRead(BYTEaddr,BYTE*s,BYTEc)
{BYTEc;
SL811H_ADDR=addr;
while(c--)
*s++=SL811H_DATA;
}
连续写SL811HS寄存器:
voidSL811BufWrite(BYTEaddr,BYTE*s,BYTEc)
{BYTEc;
SL811H_ADDR=addr;
while(c--)
SL811H_DATA=*s++;
}
读写寄存器正常以后,便进入SL811HS底层函数的编写,具体的函数可参照CYPRESS公司提供的代码修改。
在对U盘读写之前需正确配置SL811HS芯片,这部分工作通过枚举[3]来完成。
枚举是对USB接口正确配置的过程,包括获取设备描述符、配置描述符、接口描述符、端点描述符,以及对接口、端点正确配置。
请求设备描述符的setup数据包[5]为80h06000100001200,通过读取设备描述符,可获得设备的子类。
请求配置描述符的setup数据包为80h06000100000900,对于请求配置描述符,可以先进行首次请求,要求数据包长为9。
接收到设备返回的数据,获得此描述符的总长,然后再发二次请求,获得全部描述符数据。
第二次发送的setup数据包内容为80h06000100002Eh00
此时返回数据包括设备配置、接口、端点的全部描述信息。
枚举过程见图4.1。
图4.1枚举过程
设备刚插入时SL811HS是通过中断方式通知主机的,主机通过查询SL811HS中断寄存器的值判断引起中断的原因,如果是由于设备插入引起的原因,主机接下来要对设备进行配置,首先要获得设备描述符,以判别设备是哪一类设备,此时USB设备默认地址为0,通讯采用控制传输,接下来主机对USB设备分配地址,地址从1到127可根据系统需要任意选择,在以后的与USB设备通讯时就用此地址,然后获取有关设备配置的描述符,获取此描述符要进行两次请求,第一次是试探性的,以便得到相关数据的具体长度,第二次才返回接口以及端点的全部信息。
最后按照得到的数据对USB设备进行正确的配置,至此USB枚举过程结束。
软件流程如图4.1所示。
4.2.U盘的读写及FAT16文件系统[2]:
U盘属于大容量存储设备,当U盘枚举成功后,主机与USB设备通过BULK-ONLY传输方式传输数据,所有的通讯数据都通过BULK-IN和BULK-OUT端点传输。
在这种传输方式下,有三种类型的数据在USB和设备之间传送,CBW、CSW和普通数据[3]。
CBW(CommandBlockWrapper,即命令块包)是从USBHost发送到设备的命令,命令格式遵从接口bInterfaceSubClass中所指定的命令块,这里为SCSI传输命令集。
USB设备需要将SCSI命令从CBW中提取出来,执行相应的命令,完成以后,向Host发出反映当前命令执行状态的CSW(CommandStatusWrapper),Host根据CSW来决定是否继续发送下一个CBW或是数据。
Host要求USB设备执行的命令可能为发送数据,则此时需要将特定数据传送出去,完毕后发出CSW,以使Host进行下一步的操作。
U盘一般支持FAT16文件系统,它可以分成4个部分,即保留区,FAT区,根目录区,数据区。
保留区的第一个扇区也叫引导扇区,它含有对文件系统识别的关键信息。
根目录区存放目录项,每个目录项为32个字节,记录一个文件或目录的信息。
FAT区即文件分配表,操作系统分配磁盘空间按簇来分配的。
同一个文件的数据并不一定完整地存放在磁盘的一个连续的区域内,而往往会分成若干段,像一条链子一样存放。
这种存储方式称为文件的链式存储。
为实现文件的链式存储,硬盘上必须准确地记录哪些簇已经被文件占用,还必须为每个已经占用的簇指明存储后继内容的下一个簇的簇号,对一个文件的最后一簇,则要指明本簇无后继簇。
这些都是由FAT表来保存的,FAT表的对应表项中记录着它所代表的簇的有关信息:
诸如是否空,是否是坏簇,是否已经是某个文件的尾簇等。
目录项的所占的最后一个扇区之后,便是真正存放文件数据的位置了。
最后按照得到的数据对USB设备进行正确的配置,至此USB枚举过程结束。
USB总线一般包含四种基本数据传输类型:
控制传输、中断传输、批传输以及同步传输,本系统使用的是控制传输和批量传输。
写U盘的流程图如图4.2所示。
图4.2写U盘的流程图
5总结
本文介绍的USB主机接口不同于以往的USB设备接口[6],在USB系统设计中,USB主机接口的设计一直是其难点所在。
它能主动发出命令,USB外设通过解析命令数据包然后执行相应的命令。
通过USB主机接口的控制,不仅提高了数据传输的稳定性,而且能够对采集过程中出现的错误及时进行处理。
本方案已成功实现了对U盘的读写,在实际的应用中,读写数据稳定可靠,可兼容市场上绝大多数U盘。
遗憾的是没能实现仿真。
本设计的另一优点是成本低廉,可应用于各种智能仪器及嵌入式设备中,实现对海量数据的存储。
参考文献
[1]Cypresssemiconductorcorporation.SL811HSdatesheet[z].2002.
[2]Microsoftcorporation.FATFileSystemSpecification[z].1999.
[3]Compaq,Inter,Microsoft,NEC.UniversalSerialBusSpecification(Revision1.1).1998.
[4]史波,田凯.通用串行总线USB技术概述[J].信息技术.2001(4).
[5]冉光志,赵明生.基于SL811HST和S3C4510B的嵌入式USB主机与设备的设计.微计算机信息.2005,(11)
[6]路永坤.基于USB接口的数据采集模块的设计与实现[J].自动化仪表.2005,
(2)
附录
org0000h
sjmpstart
org0030h
start:
mov30h,#00h
mov31h,#00h
mova,30h
movdptr,#ddss
movcA,@a+dptr
cpla
movp0,a
mova,31h
movca,@a+dptr
cpla
movp2,a
main:
jbp1.0,m0
lcalldely0
jbp1.0,m0
lcalldely1
lcallz0
m0:
jbp1.1,m1
lcalldely0
jbp1.1,m1
lcalldely1
lcallz1
m1:
jbp1.2,m2
lcalldely0
jbp1.2,m2
lcalldely1
lcalldely1
lcallz2
m2:
jbp1.3,m3
lcalldely0
jbp1.3,m3
lcalldely1
lcallz3
m3:
ljmpmain
dely0:
movr7,#100
dly0:
movr6,#98
nop
dly1:
djnzr6,dly1
djnzr7,dly0
ret
z0:
inc30h
mova,30h
cjnea,#0ah,abc0
mov30h,#00h
abc0:
mova,30h
movdptr,#ddss
movca,@a+dptr
cpla
movp0,a
ret
z1:
inc31h
mova,31h
cjnea,#0ah,abc1
mov31h,#00h
abc1:
movdptr,#ddss
mova,31h
movca,@a+dptr
cpla
movp2,a
ret
z2:
movr5,#00h
movr4,#0ffh
movdptr,#ddss
z21:
incr4
lcalldely1
cjner4,#10,z22
movr4,#0
incr5
cjner5,#10,z22
ret
z22:
mova,r5
movca,@a+dptr
cpla
movp2,a
mova,r4
movca,@a+dptr
cpla
movp0,a
ljmpz21
z3:
movscon,#50h
movtcon,#20h
movth1,#0d9h
movtl1,#0d9h
mova,30h
movsbuf,a
wait0:
jbcti,wait1
sjmpwait0
wait1:
mova,31h
movsbuf,a
wait2:
jbcti,next
sjmpwait2
next:
nop
ret
dely1:
movr7,#250
dly2:
movr6,#250
nop
dly3:
djnzr6,dly3
djnzr7,dly2
ret
ddss:
db3fh,06h,5bh,4fh,66h
db6dh,7dh,07h,7fh,6fh
end