单片机读写U盘资料

a66886527 2005-04-18 05:58:57

www.8dragon.com

龙人课堂
在做这个项目之前,我想提醒大家,硬件不怎么难,关键是软件的问题。所以大家只要努力,多用时间调试,最后就一定能够走通。我这里只是向大家指条好路,记住千万不要直接COPY,否则学不到什么东西,什么事情,亲自动手后,然后搞定后者提问才是最好的办法。另外,我想说明的是,我在这里讲的一般代码,大概最后速度有几十K,龙人最核心的800多K的东西,需要一定的板子费才给大家,龙人有现成的板子优惠提供给大家点击看看http://www.8dragon.com (插播的广告^_^)。希望大家能够理解。不罗嗦了,进入正题。
一、硬件选材
硬件选用最常见的8位51系列或者16位的也可以。主控芯片当然用sl811host。然后要有扩展内存,32K(62256就可以了)反向器,811的晶体最好用48M有源的,为了调试方便设置几个必要的LED,为了在电脑上仿真,接个232口,好了硬件选材基本就是这些。
二、必要工具:
开关电源(最好选用纹波少点的,否则容易读写出错)示波器、仿真器。我讲讲整个项目开发的流程,不熟悉的人可以快去补补相关东西。
首先当然是画原理图(我上面说的器件)做PCB。然后开始看USB1.1协议中的主机部分,811数据手册,SCSI协议(BULK),看FAT文件协议(有条件的可以看点U盘开发资料)等心中有个数后就可以开始投入写代码和调试了。这个软件分为3大层次来写。一是811和CPU的通信编写,就是读和写,注意811和周边外围器件的地址分配;二就是811实现USB数据流的转换,完成对USB的配置,为U盘设备设置通信地址。在这个USB流传送中主要是用了CONTROL传输。这个东西CYPRESS有完全的代码可以参考(提供链接在我们的网上下载),只需要修改一下地址或者不用修改就能直接运行,建议最好把查询方式改成中断方式,这样有利于提高CPU效率。三是对U盘枚举和设置了,根据SCSI协议只有对U盘进行设置和配置后才是可用的。到这里就可以完成对U盘的读写了,不过此时你读写的数据流,可能什么作用也不起,因为你没有文件系统,在WINDOWS里,你看不见任何东西,必须做一个事实的文件系统来管理具体的数据。

xdata BYTE SL811_ADDR_PORT _at_ 0x8000;
xdata BYTE SL811_DATA_PORT _at_ 0x8100;
extern unsigned char xdata DBUF[BUFFER_LENGTH];
unsigned char SL811Read(unsigned char idata a)
{

SL811_ADDR_PORT=a;
return (SL811_DATA_PORT);
}
void SL811Write(unsigned char idata a, unsigned char idata d)
{
/
SL811_ADDR_PORT = a;
SL811_DATA_PORT = d;
}
void SL811BufRead(unsigned char addr, unsigned char *s, unsigned char c)
{

unsigned char idata i=c;
SL811_ADDR_PORT = addr;
while (i--)
{
*s = SL811_DATA_PORT;
s++;
}
}
void SL811BufWrite(unsigned char addr, unsigned char *s, unsigned char c)
{
unsigned char idata i=c;
SL811_ADDR_PORT = addr;
while (i--)
{
SL811_DATA_PORT = *s;
s++;
}
}


桃龙源 龙人提供
技术论坛www.8dragon.com
...全文
811 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
a66886527 2005-04-18
  • 打赏
  • 举报
回复
需要开发板,请联系QQ37201600
a66886527 2005-04-18
  • 打赏
  • 举报
回复
811和CPU通信的代码是最底层的东西,新手在这个地方一定要注意地址的定义,不要^_^!这个东西有些新人肯定不懂。操作811之类的东西最好用地址来操作,速度快。不要用位控,速度慢,并且时序控制起来也烦人。大家不要嫌我罗嗦这个东西可是最基本的,到这里来的我希望都是新人,我讲的知识也是针对新人,所以应该基础一点。你在自己制作811的时候函数可以就用这个了,但是地址可以根据具体情况换成响应的就可已了。还不明白的把电路贴到www.8dragon.com 论坛中来,龙人和桃龙源的网友们帮你算。
三、811如何把数据流转成USB的数据流,使其能和主机通信。
先说说大的流程根据我自己编写的软件件,其实也和CYPRESS提供的那个差不多,只是把它的查询方式改成了中断方式) U盘一插上后,CPU是怎么知道有设备接入的?这是通过811的中断告诉CPU的,同时当U盘拔 出去时也是通过中断告诉CPU的。那CPU是怎么判断是插入还是拔出呢?可以通过读函数SL811Read(IntStatus)读取中断寄存器的值(注意,在 读中断寄存器的值必须对811进行初始化,SL811Write(IntEna,0x20);SL811Write(IntStatus,INT_CLEAR);SL811Write(cSOFcnt,0xae);初始中断寄存器,然后清0,打开SOF可以开始传输数据流)根据值我们就可以来控制软件的流程:1,如果是插入盘,那么就可以给U盘分配地址,获取配置描述符中的具体数据,然后根据数据来设置实际的U盘包端点大小。最后根据具体设备类来设置配置值,然后配置接口。到此时,整个USB枚举配置就完成了。给个配置的大体框架流程就是,希望大家不要深究具体的细节要宏观上把握,这样布局好了,即使不对改也好改,加也好加。鉴于这些代码CUPYESS都有所以我就不贴了,我只是点一下流程。流程只要不对第一步的USB枚举就一定能通过^_^可以使用仿真器观察一下内存变量的值(搞单片机一定得有有个仿真器)如果通不过,设下断点看停在那里。根据我的经验只要你不抄错CYPRESS的代码就一定通过,当然也有通不过的,怎么办?找龙人呀!首先单独测试你的读写函数(几十次)看有没有错,确保最底层的东西。如果不正确, 那么就出在你的硬件了,别慌,不要乱改硬件,新手们注意一下看自己的读写地址设置正确了没有,如果确保没错,那么就是硬件了。经验之一,用示波器看看SOF是不是1MS,如果不是注意晶 体了,问题多半在他。如果不是,那么检查数据地址线,看有没有断路的,烦人!(^__^龙人最讨厌折腾班子了)。如果前面的工序都检查完了,那么问题还没有解决,赶快到龙人论坛www.8dragon.com提问,最好贴出你的代码,龙人和桃龙源的网友一起帮你解决。提醒大家抄CYPRSS代码的时候最好仔细点,我发觉好多人都粗心的,最后好我一看就是很简单的错误。今天讲到这,由于大家都有CPYRESS的代码,龙人也是抄它的,所以就不贴出了。要想学东西,赶快动手自己写一面,然后运行调试,看看结果。哇,结果正确!龙人恭喜你了!失望,结果不正确呀,我们都是学生,从头来呀,没什么的,坚持坚持!我相信高手就是从这里开始有分水岭了。失望透顶,还是解决不了,没关系,不要忘记了还有桃龙源www.8dragon.com呀,龙人一定会帮你的!^__^!
unsigned char EnumUsbDev(unsigned char usbaddr)
{
uDev.wPayLoad[0] = 64;
wPayload=64;
if(usbaddr == 1)
USBReset();
DelayMs(50);
pDev =(pDevDesc)DBUF;
usbaddr=uAddr;
setup.wvalue=DEVICE;
setup.wIndex=0;
setup.wLength=18;
buffer=DBUF;
if (!GetDesc())
{
return FALSE;
}
wPayload=pDev->bMaxPacketSize0;
DEV.wPayLoad[0]=pDev->bMaxPacketSize0;
if (!SetAddress(usbaddr))
return FALSE;
uAddr = usbaddr;
pDev =(pDevDesc)DBUF;
usbaddr=uAddr;
setup.wLength=pDev->bLength;
setup.wvalue=DEVICE;
setup.wIndex=0;
buffer=DBUF;
if (!GetDesc())
return FALSE;
uDev.wVID = pDev->idVendor;
uDev.wPID = pDev->idProduct;
uDev.iMfg = pDev->iManufacturer;
uDev.iPdt = pDev->iProduct;
if (!GetDesc())
return FALSE;
if (!Set_Configuration())
return F
if (!Set_Interface())
return FALSE;
GetDesc()
return FALSE;
pIfc = (pIntfDesc)(DBUF + 9);
Set_Configuration()
Set_Interface()
return TRUE;
}
前面讲完了2章,3章,我主要是讲,在你对USB数据配置完备之后,你怎么对U盘操作。U盘只是USB设备的一种。前面的配置只是一个总的配置,对所有USB都实用。现在要对具体的U盘能够操作和控制,所有必须还得对它进枚举。U盘是利用SCSI协议完成的,所以主机要完成对它的枚举也主要是对一些SCSI协议的应用。U盘是SCISI下mass storage类,该类主要是应用于磁盘接口。该类对应的宏定义(根据协议)为bInterfaceClass为0X08。那么该类的是通过什么来实现的呢?of course 是一些命令,专门的命令。在bInterFaceSUBclass类下有UFI命令,主要用于对磁盘进行操作,通过它可以完成。UFI宏值是0X04。ufi下有一些必要的命令。利用这些命令就可以完成对U盘的配置和操作。0x12:查询设备信息。0x5主机请求设备参数。0x03:主机判别参数,0X00:查询设备是否准备好。0X28,0XA8读数据。0X25读容量。0X2B寻赤道。0X2A,0XAA写数据。够了利用这些东西可以完成枚举和读写U盘了。那么如何够造包,如何把数据发出呢?通过什么样的数据结果把这些命令发给811呢。请看下面讲解。今天中午偷点空所以写了个开头。接下来补上,学生朋友门快去看点协议,然后理解一下,按这个方向编电码,改天,我再讲如何写 _^___^
在做底层通信的时候,应要明白一个道理。大家都知道一个HUB最多可以挂127个USB设备,也就是主机最多能控制和管理这么多设备。127个设备就有127个地址,HOST要和设备通信是通过地址来完成的,就象电话号码一样。地址分配很简单127个,所以可按(1-127)来定义就OK了。在此要注意0地址不能用,因为这是每一个HOST第一次识别设备时自动默认使用的地址,通过这个地址可以完成对某个具体设备的识别,获取设备的具体特征,记住它,然后再重新为设备分配一个地址,建立正式的身份关系,以后要对设备的控制都是通个这个身份来完成。地址分配好后,就能完事了吗?不是的!USB 设备上还有不同的端点(设备接口地址,厂家自己定义的,换话句话说就是就象你开了一个东西,设定好了一个地址给别人,他必须按这个地址才能和你联系)但是这里大家同样要注意0端点地址要保留,和设备地址一样,因为host第一次通信时会自动默认使用这个端点地址。其它端点的地址就随便做USB设备的人员根据自己的实际硬件情况来指定了。HOST回在第一次通过0设备地址和0端点地址,来获取其它端点的地址以及其它想要的东西。到这里大家一个明白一个关键东西了,那就是HOST要和设备交往必须要一个设备地址+设备上的端点地址。USB的数据传输是按包来传送的,什么TOKEN,ack等。但总体来看,我们可以把传输事情分为三类,第一类完成配置,这是操作任何一个USB设备都避免不了的。第二类就是HOST向设备发数据,还有一类就是HOST从设备收数据。所以要做的工做是就是实现这三类。在协议里有专门的PID标志来区别这三类(pid_setup,pid_in,pid_out),你要发送或者收取什么信息,必须需要先以PID开头,通知设备,现在开始的什么操作,它好向你反映。要注意的是setup,只能用一次,识别设备和配置它时使用,后两种你可以根据具体情况,要发的使用OUT,想获取的时候用IN。总体逻辑思想通了过后,剩下的事情无非就是在具体芯片的寄存里填几个数字而已,它们就会知道怎么去做 。

桃龙源 龙人提供
技术论坛www.8dragon.com

21,619

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧