单片机读写U盘的接口
- 格式:doc
- 大小:61.50 KB
- 文档页数:6
对USB接口芯片CH375的功能、原理做了较详细的介绍,并给出了在单片机读写U盘中的实例及注意事项。
随着计算机技术的快速发展,USB移动存储设备的使用已经非常普遍,因此在一些需要转存数据的设备、仪器上使用USB移动存储设备接口的芯片便相继产生了,CH375就是其中之一,它是一个USB总线的通用接口芯片,支持HOST主机方式和SLAVE设备方式。
在本地端,CH375具有8位数据总线和读、写、片选控制线以及中断输出,可以方便地挂接到单片机/DS P/MCU等控制器的系统总线上。
在USB主机方式下,CH375还提供了串行通信方式,通过串行输入、串行输出和中断输出与单片机/DSP/MCU等相连接。
CH375的USB主机方式支持各种常用的USB全速设备,外部单片机/DSP/MCU可以通过CH375按照相应的USB协议与USB设备通信。
CH375芯片内部结构1 内部结构CH375芯片内部集成了PLL倍频器、主从USB接口SIE、数据缓冲区、被动并行接口、异步串行接口、命令解释器、控制传输的协议处理器、通用的固件程序等。
CH375芯片引脚排列如图1所示。
2 内部物理端点CH375芯片内部具有7个物理端点。
端点0 是默认端点,支持上传和下传,上传和下传缓冲区各是8B;端点1包括上传端点和下传端点,上传和下传缓冲区各是8B,上传端点的端点号是81H,下传端点的端点号是01H;端点2包括上传端点和下传端点,上传和下传缓冲区各是64B,上传端点的端点号是82H,下传端点的端点号是02H。
主机端点包括输出端点和输入端点,输出和输入缓冲区各是64B,主机端点与端点2合用同一组缓冲区,主机端点的输出缓冲区就是端点2的上传缓冲区,主机端点的输入缓冲区就是端点2的下传缓冲区。
其中,CH375的端点0、端点1、端点2只用于USB设备方式,在USB主机方式下只需要用到主机端点。
软件接口对于USB存储设备的应用,CH375直接提供了数据块的读写接口,以512b的物理扇区为基本读写单位,从而将USB存储设备简化为一种外部数据存储器,单片机可以自由读写USB存储设备中的数据,也可以自由定义其数据结构。
/*******************************************************/#include"reg52.h"#include"stdio.h"#include "string.h"#include "intrins.h"#include"CH375INC.H"/*******************************************************/#define uchar unsigned char#define uint unsigned int/*******************************************************/sbit CH375_INT=P3^3;sbit CH375_A0=P3^4;sbit CH375_RD=P3^5;sbit CH375_WR=P3^6;sbit CH375_CS=P3^7;/*******************************************************/uchar xdata my_buf[512];/*******************************************************/void uart_init(){TMOD=0X20;TH1=TL1=0XFD;TR1=1;REN=1;SM0=0;SM1=1;EA=1;ES=1;}/*******************************************************/void uart_send_pc(uchar *s) //串口监视//void uart_send_pc(uchar a[20]) { //{uchar len=strlen(s); // uchar i;uchar i; // for(i=0;i<20;i++)for(i=0;i<len;i++) // {{ // ES=0;ES=0; // SBUF=a[i];SBUF=s[i]; // while(!TI);while(!TI); // TI=0;TI=0; // ES=1;ES=1; // }} //}}/*******************************************************/void Delay2us() //@11.0592MHz{unsigned char i;_nop_();_nop_();i = 2;while (--i);}//********************1ms延时函数*************void delay1ms(unsigned int z){unsigned int x,y;for(x=z;x>0;x--)for(y=845;y>0;y--);}/*******************************************************/ void ch375_write_datcmd(uchar dat_cmd,uchar k) //写数据、命令{Delay2us();CH375_CS=0;CH375_A0=k; // 0:data 1:cmdP2=dat_cmd;CH375_WR=0;CH375_WR=1;CH375_CS=1;CH375_A0=1;Delay2us();}uchar ch375_read_dat() //读数据{uchar dat;CH375_CS=0;CH375_A0=0;P2=0XFF;CH375_RD=0;// P2=0XFF;dat=P2;CH375_RD=1;CH375_CS=1;CH375_A0=1;return dat;}/************************等待获取状态并取消中断操作*******************************/uchar ch375_wait_int(){CH375_INT=1;while(CH375_INT);ch375_write_datcmd(CMD_GET_STATUS,1); //获取状态并取消中断return ch375_read_dat();}/************************获取U盘容量操作*******************************/ unsigned long* get_volume(){unsigned long volume[2];uchar status,i;ch375_write_datcmd(CMD_DISK_SIZE,1);status=ch375_wait_int();if(status==USB_INT_SUCCESS){ch375_write_datcmd(CMD_RD_USB_DA TA,1);i=ch375_read_dat();for(i=0;i<4;i++){volume[0]=volume[0]<<8;volume[0]=volume[0]+ch375_read_dat();delay1ms(1);}for(i=0;i<4;i++){volume[1]=volume[1]<<8;volume[1]=volume[1]+ch375_read_dat();delay1ms(1);}}return volume;}/************************U盘初始化操作*******************************/uchar ch375_init(){uchar status;// uart_send_pc("请插入U盘:\n");status=ch375_wait_int(); //等待插入,并获取状态if(status!=USB_INT_CONNECT){uart_send_pc("U盘插入错误!\n");}else{// uart_send_pc("U盘已插入!\n");}ch375_write_datcmd(CMD_DISK_INIT,1); //磁盘初始化status=ch375_wait_int();if(status!=USB_INT_SUCCESS){uart_send_pc("磁盘初始化失败!\n");}else{// uart_send_pc("磁盘初始化成功!\n");}return 0;}/*******************************************************//**********************读扇区操作*********************************/uchar read_section(unsigned long addr){uchar i,k,status,length;ch375_write_datcmd(CMD_DISK_READ,1); //发送读扇区命令ch375_write_datcmd(addr,0);ch375_write_datcmd(addr>>8,0);ch375_write_datcmd(addr>>16,0);ch375_write_datcmd(addr>>24,0); //发送地址,先低后高ch375_write_datcmd(1,0); //送入读取扇区数for(i=0;i<8;i++) //缓冲区为64个字节,512/64=8,所以要读8次{status=ch375_wait_int(); //等待,并获取状态if(status==USB_INT_DISK_READ) //读数据块{ch375_write_datcmd(CMD_RD_USB_DA TA,1);length=ch375_read_dat();for(k=0;k<length;k++){my_buf[k+i*64]=ch375_read_dat(); //每次获取length个数ES=0; // SBUF=a[i];SBUF=my_buf[k+i*64]; // while(!TI);while(!TI); // TI=0;TI=0; // ES=1;ES=1;}}ch375_write_datcmd(CMD_DISK_RD_GO,1);}status=ch375_wait_int();if(status!=USB_INT_SUCCESS){return status;}return 0;}/*******************************************************/void main(){uart_init();delay1ms(40);ch375_write_datcmd(CMD_SET_USB_MODE,1); //设置USB模式ch375_write_datcmd(0x07,0); //自检测,复位usb总线delay1ms(1);ch375_write_datcmd(CMD_SET_USB_MODE,1); //设置USB模式ch375_write_datcmd(0x06,0); //自检测,并且产生sop包if(ch375_init()==0){// uart_send_pc("初始化完成!\n");}delay1ms(1);if(read_section(96+0x3a19)==0){// uart_send_pc("已读到扇区!\n");}while(1){}}void t1() interrupt 4{RI=0; }。
单片机USB模拟U盘源码虽然现在成品U盘的成本已经非常低,但是单片机系统中模拟U盘还是有些场景会应用到,比如:①代替传统光盘,为用户提供说明书、驱动软件等(直接存储在产品中)②U盘数据监控、截取和加密等(定制U盘)③采集数据暂存,方便传输给主机下文是根据masstorage和Bulk-Only传输协议,使用CH559实现模拟U盘的功能(容量大小由选择的外部存储芯片决定),用以实现数据转存或定制U盘功能。
关键点在于USB 设备模式初始化、扇区读写和外部存储芯片的操作。
一、总体概述模拟U盘关键功能部件包括以下几点:(1)、具有USB设备功能的MCU或接口芯片,此例中CH559有2个USB主机接口和1个USB设备接口。
(2)、根据实际需要或者接口选择合适的外部存储来作为U盘的存储空间,比如SPI的串行Flash、E2PROM,甚至是Nand Flash等。
以上准备完毕整体的操作流程如下所示:二、硬件电路CH559模拟U盘使用的SPI接口的串行Flash,硬件如下图:CH559是增强型51内核的单片机,内置晶振,所以芯片外围也足够简洁。
芯片资源如下图:三、软件编写软件主要包括以下方面:(1)、USB设备模式初始化(2)、存储芯片接口初始化(3)Bulk_Only传输CBW包:CSW包:四、可拓展功能(1)、其他存储介质:除了以上提到的SPI接口的串行Flash,也可以替换成E2PROM或者Nand falsh等。
(2)、数据来源可以随意指定,比如串口数据流,并口数据流,甚至其他温湿度传感器设备等。
(3)、CH559+SPI串行Flash模拟U盘测试参数CH563模拟U盘源码.rar559模拟U盘源码.rar五、源码分享CH559模拟U 盘的源代码(C 语言):CH563模拟U 盘的源代码(C 语言):。
单片机中的USB接口设计原理及应用分析USB(Universal Serial Bus)是一种用于电脑与外围设备之间进行通信和数据传输的标准接口。
它具有简化连接过程、高速传输能力和广泛的应用范围等优点,因此在现代电子设备中得到了广泛应用。
本文将介绍单片机中的USB接口设计原理及其应用分析。
一、USB接口设计原理1.1 USB接口的基本原理USB接口由主机(Host)和设备(Device)组成。
主机负责控制和管理通信过程,而设备则执行主机的指令。
USB接口采用了一种主从式架构,主机为USB控制器,设备为USB设备。
数据通过USB总线进行传输。
1.2 USB接口的硬件设计USB接口的硬件设计主要包括物理层和电气层。
物理层主要涉及连接器的设计和布线,电气层则规定了电压、电流和信号传输的规范。
物理层设计包括USB连接器的选型和布线方式。
USB接口常用的连接器有A 型、B型、C型等。
布线方式主要包括了信号线的长度控制和阻抗匹配等。
在布线中要尽量避免串扰和干扰,以保证数据的完整性和可靠性。
电气层设计包括了供电电源的选择和数据信号的传输规范。
USB接口规定了数据传输的速率和电平,一般有低速、全速、高速和超速四种传输速率。
同时还规定了电压和电流的规范,以及USB总线上的阻抗等。
1.3 USB接口的协议设计USB接口通信采用了一种特定的协议,包括传输层和报文层。
传输层负责数据的传输和流控,报文层则负责数据的封装和解封装。
传输层设计了数据的传输方式,包括同步传输和异步传输。
同步传输适用于大容量的数据传输,而异步传输适用于低速的数据传输。
流控机制可以控制数据的传输速率,以避免数据的丢失和错误。
报文层设计了数据的封装和解封装方式,包括数据的格式和差错检测。
USB接口规定了数据的格式和帧结构,以在有效载荷中传输数据。
同时还采用了差错检测机制,以保证数据的完整性。
二、USB接口的应用分析2.1 USB接口在嵌入式系统中的应用USB接口在嵌入式系统中得到了广泛的应用,例如智能家居、工业控制、智能穿戴设备等。
USB接口在单片机系统中的应用实践与优化USB(Universal Serial Bus)(通用串行总线)接口是一种用于计算机和外部设备之间进行数据传输和通信的标准接口。
在单片机系统中,USB接口的应用逐渐得到广泛应用并快速发展。
本文将介绍USB接口在单片机系统中的应用实践以及针对其优化的一些方法和技巧。
USB接口的应用实践起初主要是在个人计算机和外部设备之间进行数据传输,然而,随着单片机内部资源的不断增加和成本的不断降低,USB接口在单片机系统中的应用逐渐增多。
在实践中,USB接口在单片机系统中的应用主要体现在以下几个方面:1. 数据传输:单片机经过USB接口与外部设备进行数据传输,可以实现快速、稳定的数据传输。
例如,可以通过USB接口将单片机与电脑连接,实现数据的读取和写入,用于程序的下载、数据的采集等。
2. 外设控制:USB接口可以连接各种外部设备,如键盘、鼠标、打印机等。
通过单片机与USB接口的结合,可以实现对这些外部设备的控制。
例如,可以通过单片机控制USB接口与打印机进行数据传输,实现打印功能。
3. 通信功能:USB接口支持实时数据传输,可以方便地实现与其他设备之间的通信。
单片机可以通过USB接口与其他设备进行通信,如与传感器进行数据交互、与上位机进行通讯等。
针对USB接口在单片机系统中的应用,我们可以采取一些优化方法和技巧,以提高系统的性能和稳定性。
下面是一些常见的优化方法:1. 选用合适的USB芯片:不同的USB芯片有不同的性能和功能特点,选用合适的USB芯片对系统的性能和稳定性有着重要的影响。
在选择USB芯片时,需要考虑芯片的数据传输速度、功耗和支持的USB协议等因素。
2. 合理设计电路:USB接口涉及到电路设计,合理的电路设计可以提高系统的抗干扰能力和稳定性。
例如,可以采用差分线传输方式来减小传输的干扰和噪声。
3. 优化软件设计:软件部分也是需要优化的关键点。
通过合理的软件设计,可以提高系统的性能。
ch375读写u盘C51示例源程序/* 以下定义的详细说明请看CH375HF9.H文件 */#define LIB_CFG_FILE_IO 1 /* 文件读写的数据的复制方式,0为\外部子程序\为\内部复制\#define LIB_CFG_INT_EN 1 /* CH375的INT#引脚连接方式,接s3c44b0x外部中断2引脚\/* 单片机的RAM有限,其中CH375子程序用512字节,剩余RAM部分可以用于文件读写缓冲 */ #define FILE_DATA_BUF_LEN 0x2000 /* 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度 */#include \#define CH375Cmd *(volatile U8 *)(0x4000001) /*总线方式*/ #defineCH375Dat *(volatile U8 *)(0x4000000) extern U32 MCLK;/* CH375 主机文件系统接口*/ /* 支持: FAT12/FAT16/FAT32 *//* ARM单片机C语言的U盘文件读写示例程序 *//* 该程序将U盘中的/C51/CH375HFT.C文件中的小写字母转成大写字母后, 写到新建的文件NEWFILE.TXT中,如果找不到原文件CH375HFT.C, 那么该程序将显示C51子目录下所有以CH375开头的文件名, 并新建NEWFILE.TXT文件并写入提示信息,如果找不到C51子目录, 那么该程序将显示根目录下的所有文件名, 并新建NEWFILE.TXT文件并写入提示信息 *//* CH375的INT#引脚采用查询方式处理, 数据复制方式为\内部复制\本程序适用于s3c44b0x单片机, 串口0输出监控信息,57600bps */ /* ENDIAN = \void mDelay1_2uS( ) /* 至少延时1.2uS,根据单片机主频调整 */ { UINT32 i;for ( i = 30; i != 0; i -- ); }void __irq CH375Interrupt( void ) /* CH375中断服务程序,由CH375的INT#的低电平或者下降沿触发单片机中断 */ {rEXTINTPND=0xf; //clear EXTINTPND reg.rI_ISPC=BIT_EINT2; //clear pending_bitxWriteCH375Cmd( CMD_GET_STATUS ); /* 获取中断状态并取消中断请求 */CH375IntStatus = xReadCH375Data( ); /* 获取中断状态 */if ( CH375IntStatus == USB_INT_DISCONNECT ) CH375DiskStatus =DISK_DISCONNECT; /* 检测到USB设备断开事件 */else if ( CH375IntStatus == USB_INT_CONNECT ) CH375DiskStatus =DISK_CONNECT; /* 检测到USB设备连接事件 */ }extern void CH375Interrupt( void ); void CH375_PORT_INIT( ) /*初始化 */ {rINTCON=0x5;rINTMOD=0x0; //All=IRQ mode rPDATG=0xff; rPCONG=0xffff;rPUPG=0x0; //should be enabled rEXTINT=0x0;pISR_EINT2 = (unsigned)CH375Interrupt;rINTMSK=~(BIT_GLOBAL|BIT_EINT2); //start INT }void xWriteCH375Cmd( UINT8 mCmd ) /* 外部定义的被CH375程序库调用的子程序,向CH375写命令 */ {mDelay1_2uS( ); mDelay1_2uS( ); /* 至少延时1uS */ CH375Cmd = mCmd;mDelay1_2uS( ); mDelay1_2uS( ); /* 至少延时2uS */ }void xWriteCH375Data( UINT8 mData ) /* 外部定义的被CH375程序库调用的子程序,向CH375写数据 */ {CH375Dat = mDatamDelay1_2uS( ); /* 至少延时1.2uS */ }UINT8 xReadCH375Data( void ) /* 外部定义的被CH375程序库调用的子程序,从CH375读数据 */ {UINT8 mData;mDelay1_2uS( ); /* 至少延时1.2uS */mData = (UINT8)CH375Dat;return( mData ); }/* 延时指定毫秒时间,根据单片机主频调整,不精确 */ void mDelaymS( UINT32 ms ) { UINT32 i;while ( ms -- ) for ( i = 25000; i != 0; i -- ); }/* 检查操作状态,如果错误则显示错误代码并停机 */ void mStopIfError( UINT8 iError ) {if ( iError == ERR_SUCCESS ) return; /* 操作成功 */ printf( \/* 显示错误*/ while ( 1 ) {mDelaymS( 100 ); } }/* 为printf和getkey输入输出初始化串口 */ void mInitSTDIO( ) { }U16 SERIAL_BAUD = 57600;char table_begin[] = \void ShowSysClock(int argc, char *argv[]) {printf(\ystem is running @%dHz\\n\ }int Main(void) {unsigned char t; UINT8 i, c, SecCount;UINT16 NewSize, count; /* 因为RAM容量有限,所以NewSize限制为16位,实际上如果文件较大,应该分几次读写并且将NewSize改为UINT32以便累计 */ UINT8*pCodeStr; ChangePllValue(24, 6, 1); Port_Init();console_init(57600);next_line(); puts(table_begin);puts(\ShowSysClock(0, NULL);printf(\next_line(); puts(table_begin);puts(\mDelaymS( 50 ); /* 延时100毫秒 */ printf( \测试CH375是否正常\\n\mDelaymS(60 ); /* 延时50ms */ printf(\完成!!\i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i );/* 其它电路初始化 */ CH375_PORT_INIT( ); while ( 1 ) {printf( \请插入U盘!\\n\while ( CH375DiskStatus != DISK_CONNECT ) /* 查询CH375中断并更新中断状态,等待U盘插入 */mDelaymS( 10 );/* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */ for ( i = 0; i < 10; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */printf( \if ( CH375DiskReady( ) == ERR_SUCCESS ) break; /* 查询磁盘是否准备好 */ }/* 查询磁盘物理容量 */ printf( \i = CH375DiskSize( );mStopIfError( i );printf( \/* 读取原文件 */ printf( \strcpy( (char *)mCmdParam.Open.mPathName, \/* 文件名,该文件在C51子目录下*/ i = CH375FileOpen( ); /* 打开文件 */if ( i == ERR_MISS_DIR || i == ERR_MISS_FILE ) { /* 没有找到文件 */ /* 列出文件 */if ( i == ERR_MISS_DIR ) pCodeStr = (UINT8 *)\/* C51子目录不存在则列出根目录下的文件 */ else pCodeStr = (UINT8 *)\/* CH375HFT.C文件不存在则列出\\C51子目录下的以CH375开头的文件 */printf( \for ( c = 0; c < 255; c ++ ) { /* 最多搜索前255个文件 */strcpy( (char *)mCmdParam.Open.mPathName, (char *)pCodeStr ); /* 搜索文件名,*为通配符,适用于所有文件或者子目录 */i = strlen( (char const *)mCmdParam.Open.mPathName ); /* 计算文件名长度,以处理文件名结束符 */ mCmdParam.Open.mPathName[ i ] = c; /* 根据字符串长度将结束符替换为搜索的序号,从0到255 */ i = CH375FileOpen( ); /* 打开文件,如果文件名中含有通配符*,则为搜索文件而不打开 */ if ( i == ERR_MISS_FILE ) break; /* 再也搜索不到匹配的文件,已经没有匹配的文件名 */if ( i == ERR_FOUND_NAME ) { /* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中 */printf( \match file d#: %s\\n\/* 显示序号和搜索到的匹配文件名或者子目录名*/continue; /* 继续搜索下一个匹配的文件名,下次搜索时序号会加1 */ }else { /* 出错 */ mStopIfError( i ); break; } }pCodeStr = (UINT8 *)\找不到/C51/CH375HFT.C文件\\xd\\n\for ( i = 0; i != 255; i ++ ) {if ( ( FILE_DATA_BUF = *pCodeStr ) == 0 ) break; pCodeStr++; }NewSize = i; /* 新文件的长度 */SecCount = 1; /* (NewSize+511)/512, 计算文件的扇区数,因为读写是以扇区为单位的 */ }else { /* 找到文件或者出错 */ mStopIfError( i ); /* printf( \i = CH375FileQuery( ); 查询当前文件的信息感谢您的阅读,祝您生活愉快。
C8051F320及其USB接口应用C8051F320是由美国Cygnal公司推出的C8051F系列单片机中的一款小型单片机。
它是集成的混合信号片上系统SOC(System on chip),具有与MCS-51核及指令集完全兼容的微控制器,除了具有标准8051的数字外设部件之外,片还集成了数据采集和控制系统中常用的模拟部件和其它数字外设及功能部件。
部Flash存储器可实现在系统编程,既可作程序存储器也可作非易失性数据存储。
片JTAG仿真电路提供全速的电路仿真,不占用片用户资源。
支持断点、单步、观察点、运行和停止等调试命令,并支持存储器和寄存器校验和修改。
C8051F320片自带有USB收发器和控制处理器是它区别与同一系列产品的一大特点。
用C8051F320来进行USB技术开发既方便又快捷。
C8051F320单片机简介1 功能部件及特点1.模拟外设 10位的ADC(±1LSB INL):其最大可编程转换速率可达200kbps,可多达17个外部输入,可编程为单端输入或差分输入,置一个温度传感器(±3℃);2个模拟比较器;2.4V的部电压基准;精确的Vdd 监视器和欠压检测器。
B 功能控制模块满足USB2.0协议;可在全速(12 Mbps)或低速(1.5Mbps)下运行;集成有一个时钟恢复源,对于全速或低速传输均可不用外部晶振;支持8个灵活通用的端点;置一个1K的USB专用缓冲存储器;集成了一个USB接收器,不需要外部电阻。
3.片调试模块片调试电路提供全速、非侵入式的在系统调试(不需仿真器);支持端点、单步、观察点、堆栈监视器;可以观察/修改存储器和寄存器;比使用仿真芯片、目标仿真头和仿真插座的仿真系统有更好的性能。
4.工作温度围:0~70℃5.高速8051微控制器核采用流水线指令结构,其70%的指令的执行时间为一个或两个系统时钟周期;速度可达25 MIPS(时钟频率为25MHz时)。
常用USB芯片介绍(转串口、SPI、单片机读写U盘)USB1.1:CH375 有HOST和SLAVE两种方式,即可以当主机去控制别的USB设备,如U盘等,又可以被PC控制。
CH372 只有设备模式,不能控制别的USB设备USB2.0:内部不含单片机核的USB芯片:CY7C68001 CYPRESSFT245BM FTDI内部含有单片机核的USB芯片:CY7C68013 CYPRESS 有3种(56针,100针,128针)USB OTG:CY7C67200、CY7C67300, 内含16位的RISC MCU,输出16位的数据。
为全速的USB接口TD1120 集成全速主机高速从机,TransDimension公司生产GL824 没有下到DATASHEET,不过网上都有资料,应该是高速的USB HUB:AT43301 一个上行4个下行,为USB1.1接口GL850A 一个上行4个下行,为USB2.0接口以下这些HUB是网上弄来的,还没有查过,有要用到的去查查看吧:Alcor Micro AU2916,AU9412AtmEl AT43301,AT43311FDTI FT8U2100AXIntel 8x930Hx,8x931HxKC TecHnology KC82C160,KC82C169Motorola MC141555,MC141556PHilips PDIUSBH11,PDIUSBH12Sola Electronics MSE9701,MSE9712TI TUSB204613USAR Systems UR3HCGNHWinbond W81C180,W82C620PS:1、USB协议规USB通信遵守严格的主从模式,即必须是主-从,不能主-主或从-从。
(很多人都知道,但考虑设计的时候没有注意到)2、USB HUB是USB设备,只能接USB主机,比如以上的OTG 的芯片,不能接非USB主机的芯片,比如CY7C68013.但是HUB接主机芯片以后,该芯片直接确定为主机模式,不能再设为从机。
USB接口芯片CH375的原理及应用对USB接口芯片CH375的功能、原理做了较详细的介绍,并给出了在单片机读写U盘中的实例及注意事项。
随着计算机技术的快速发展,USB移动存储设备的使用已经非常普遍,因此在一些需要转存数据的设备、仪器上使用USB移动存储设备接口的芯片便相继产生了,CH375就是其中之一,它是一个USB总线的通用接口芯片,支持HOST主机方式和SLAVE设备方式。
在本地端,CH375具有8位数据总线和读、写、片选控制线以及中断输出,可以方便地挂接到单片机/DSP/MCU等控制器的系统总线上。
在USB主机方式下,CH375还提供了串行通信方式,通过串行输入、串行输出和中断输出与单片机/DSP/MCU等相连接。
CH375的USB主机方式支持各种常用的USB全速设备,外部单片机/DSP/MCU可以通过CH375按照相应的USB协议与USB设备通信。
CH375芯片内部结构1 内部结构CH375芯片内部集成了PLL倍频器、主从USB接口SIE、数据缓冲区、被动并行接口、异步串行接口、命令解释器、控制传输的协议处理器、通用的固件程序等。
CH375芯片引脚排列如图1所示。
2 内部物理端点CH375芯片内部具有7个物理端点。
端点0是默认端点,支持上传和下传,上传和下传缓冲区各是8B;端点1包括上传端点和下传端点,上传和下传缓冲区各是8B,上传端点的端点号是81H,下传端点的端点号是01H;端点2包括上传端点和下传端点,上传和下传缓冲区各是64B,上传端点的端点号是82H,下传端点的端点号是02H。
主机端点包括输出端点和输入端点,输出和输入缓冲区各是64B,主机端点与端点2合用同一组缓冲区,主机端点的输出缓冲区就是端点2的上传缓冲区,主机端点的输入缓冲区就是端点2的下传缓冲区。
其中,CH375的端点0、端点1、端点2只用于USB设备方式,在USB主机方式下只需要用到主机端点。
软件接口对于USB存储设备的应用,CH375直接提供了数据块的读写接口,以512b 的物理扇区为基本读写单位,从而将USB存储设备简化为一种外部数据存储器,单片机可以自由读写USB存储设备中的数据,也可以自由定义其数据结构。
CH375是USB总线的通用接口芯片,支持HOST主机方式和SLAVE设备方式。
MCS-51单片机读写U盘的电路原理图,CH375芯片的TXD引脚接高电平,工作于串口方式。
在串口方式下,CH375只需要与单片机/DSP/MCU连接3个信号线,TXD引脚、RXD引脚以及INT#引脚,其他引脚都可以悬空。
除了连接线较少之外,其他外围电路与并口方式基本相同。
由于INT#引脚和TXD 引脚在C H375复位期间只能提供微弱的高电平输出电流,在进行较远距离的连接时,为了避免INT#或者TXD在CH3 75复位期间受到干扰而导致单片机误操作,可以在INT#引脚或者TXD引脚上加阻值为1~5kΩ的上拉电阻,以维持较稳定的高电平。
在CH375芯片复位完成后,INT#引脚和TXD引脚将能够提供5mA的高电平输出电流或者5mA的低电平吸入电流。
单片机读写U盘的接口由于CH375内置了处理Mass-Storage海量存储设备的专用通信协议的固件,所以嵌入式系统的单片机可以通过CH375将U盘(USB闪存盘、USB外置硬盘)作为可移动的大容量存储器。
数据读写只需要几条指令,而不需要详细了解USB通信协议。
如果嵌入式系统需要将USB存储设备组织为文件系统,可调用CH375文件级子程序库提供的接口API,由子程序库处理文件系统。
MCS-51单片机读写U盘范例源程序如下:#include#include "CH375INC.H"#include /* 以下定义适用于MCS-51单片机 */#define UINT8 unsigned char#define UINT16 unsigned short#define UINT32 unsigned long#define UINT8X unsigned char xdata#define UINT8VX unsigned char volatile xdataUINT8VX CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */UINT8VX CH375_DAT_PORT _at_ 0xBCF0; /* CH375数据端口的I/O地址 */#define CH375_INT_WIRE INT0 /* P3.2, 连接CH375的INT#引脚,用于查询中断状态 */UINT8X DISK_BUFFER[512*32] _at_ 0x0000; /* 外部RAM数据缓冲区的起始地址 */UINT32 DiskStart; /* 逻辑盘的起始绝对扇区号LBA */UINT8 SecPerClus; /* 逻辑盘的每簇扇区数 */UINT8 RsvdSecCnt; /* 逻辑盘的保留扇区数 */UINT16 ; FATSz16; /* FAT16逻辑盘的FAT表占用的扇区数 *//* ********** 硬件USB接口层,无论如何这层省不掉,单片机总要与CH375接口吧 */void mDelaymS( UINT8 delay ) {UINT8 i, j, c;for ( i = delay; i != 0; i -- ) {for ( j = 200; j != 0; j -- ) c += 3;for ( j = 200; j != 0; j -- ) c += 3;}}void CH375_WR_CMD_PORT( UINT8 cmd ) { /* 向CH375的命令端口写入命令 */CH375_CMD_PORT=cmd;for ( cmd = 2; cmd != 0; cmd -- ); /* 发出命令码前后应该各延时2uS */}void CH375_WR_DAT_PORT( UINT8 dat ) { /* 向CH375的数据端口写入数据 */CH375_DAT_PORT=dat; /* 因为MCS51单片机较慢所以实际上无需延时 */}UINT8 CH375_RD_DAT_PORT( void ) { /* 从CH375的数据端口读出数据 */return( CH375_DAT_PORT ); /* 因为MCS51单片机较慢所以实际上无需延时 */ }UINT8 mWaitInterrupt( void ) { /* 等待CH375中断并获取状态,返回操作状态 */while( CH375_INT_WIRE ); /* 查询等待CH375操作完成中断(INT#低电平) */CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断,获取中断状态 */return( CH375_RD_DAT_PORT( ) );}/* ********** BulkOnly传输协议层,被CH375内置了,无需编写单片机程序 *//* ********** RBC/SCSI命令层,虽然被CH375内置了,但是要写程序发出命令及收发数据*/UINT8 mInitDisk( void ) { /* 初始化磁盘 */UINT8 Status;CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */Status = CH375_RD_DAT_PORT( );if ( Status == USB_INT_DISCONNECT ) return( Status ); /* USB设备断开 */CH375_WR_CMD_PORT( CMD_DISK_INIT ); /* 初始化USB存储器 */Status = mWaitInterrupt( ); /* 等待中断并获取状态 */if ( Status != USB_INT_SUCCESS ) return(Status ); /* 出现错误 */CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* 获取USB存储器的容量 */Status = mWaitInterrupt( ); /* 等待中断并获取状态 */if ( Status != USB_INT_SUCCESS ) { /* 出错重试 *//* 对于CH375A芯片,建议在此执行一次CMD_DISK_R_SENSE命令 */mDelaymS( 250 );CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* 获取USB存储器的容量 */Status = mWaitInterrupt( ); /* 等待中断并获取状态 */}if ( Status != USB_INT_SUCCESS ) return( Status ); /* 出现错误 */return( 0 ); /* U盘已经成功初始化 */}UINT8 mReadSector( UINT32 iLbaStart, UINT8 iSectorCount, UINT8X *oDataBuffer ) {UINT16 mBlockCount;UINT8 c;CH375_WR_CMD_PORT( CMD_DISK_READ ); /* 从USB存储器读数据块 */CH375_WR_DAT_PORT( (UINT8)iLbaStart ); /* LBA的最低8位 */CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 8 ) );CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 16 ) );CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 24 ) ); /* LBA的最高8位 */CH375_WR_DAT_PORT( iSectorCount ); /* 扇区数 */for ( mBlockCount = iSectorCount * 8; mBlockCount != 0; mBlockCount -- ) {c = mWaitInterrupt( ); /* 等待中断并获取状态 */if ( c == USB_INT_DISK_READ ) { /* 等待中断并获取状态,请求数据读出 */CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 从CH375缓冲区读取数据块 */c = CH375_RD_DAT_PORT( ); /* 后续数据的长度 */while ( c -- ) *oDataBuffer++ = CH375_RD_DAT_PORT( );CH375_WR_CMD_PORT( CMD_DISK_RD_GO ); /* 继续执行USB存储器的读操作 */}else break; /* 返回错误状态 */}if ( mBlockCount == 0 ) {c = mWaitInterrupt( ); /* 等待中断并获取状态*/if ( c== USB_INT_SUCCESS ) return( 0 ); /* 操作成功 */}return( c ); /* 操作失败 */}/* ********** FAT文件系统层,这层程序量实际较大,不过,该程序仅演示极简单的功能,所以精简 */UINT16 mGetPointWord( UINT8X *iAddr ) { /* 获取字数据,因为MCS51是大端格式 */ return( iAddr[0] | (UINT16)iAddr[1] << 8 );}UINT8 mIdenDisk( void ) { /* 识别分析当前逻辑盘 */UINT8 Status;DiskStart = 0; /* 以下是非常简单的FAT文件系统的分析,正式应用绝对不应该如此简单 */Status = mReadSector( 0, 1, DISK_BUFFER ); /* 读取逻辑盘引导信息 */if ( Status != 0 ) return( Status );if ( DISK_BUFFER[0] != 0xEB && DISK_BUFFER[0] != 0xE9 ) { /* 不是逻辑引导扇区 */DiskStart = DISK_BUFFER[0x1C6] | (UINT16)DISK_BUFFER[0x1C7] << 8| (UINT32)DISK_BUFFER[0x1C8] << 16 | (UINT32)DISK_BUFFER[0x1C9] << 24; Status = mReadSector( DiskStart, 1, DISK_BUFFER );if ( Status != 0 ) return( Status );}SecPerClus = DISK_BUFFER[0x0D]; /* 每簇扇区数 */RsvdSecCnt = DISK_BUFFER[0x0E]; /* 逻辑盘的保留扇区数 */FATSz16 = mGetPointWord( &DISK_BUFFER[0x16] ); /* FAT表占用扇区数 */return( 0 ); /* 成功 */}UINT16 mLinkCluster( UINT16 iCluster ) { /* 获得指定簇号的链接簇 *//* 输入: iCluster 当前簇号, 返回: 原链接簇号, 如果为0则说明错误 */UINT8 Status;Status = mReadSector( DiskStart + RsvdSecCnt + iCluster / 256, 1,DISK_BUFFER );if ( Status != 0 ) return( 0 ); /* 错误 */return( mGetPointWord( &DISK_BUFFER[ ( iCluster + iCluster ) & 0x01FF ] ) ); }UINT32 mClusterToLba(UINT16 iCluster ) { /* 将簇号转换为绝对LBA扇区地址 */ return( DiskStart + RsvdSecCnt + FATSz16 * 2 + 32 + ( iCluster - 2 ) *SecPerClus );}void mInitSTDIO( void ) { /* 仅用于调试用途及显示内容到PC机,与该程序功能完全无关 */SCON = 0x50; PCON = 0x80; TMOD = 0x20; TH1 = 0xf3; TR1=1; TI=1; /* 24MHz, 9600bps */}void mStopIfError( UINT8 iErrCode ) { /* 如果错误则停止运行并显示错误状态 */ if ( iErrCode == 0 ) return;printf( "Error status, %02X", (UINT16)iErrCode );}main( ) {UINT8 Status;UINT8X *CurrentDir;UINT16 Cluster;mDelaymS( 200 ); /* 延时200毫秒 */mInitSTDIO( );CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); /* 初始化CH375,设置USB工作模式 */CH375_WR_DAT_PORT( 6 ); /* 模式代码,自动检测USB设备连接 */while ( 1 ) {printf( "Insert USB disk" );while ( mWaitInterrupt( ) != USB_INT_CONNECT ); /* 等待U盘连接 */mDelaymS( 250 ); /* 延时等待U盘进入正常工作状态 */Status = mInitDisk( ); /* 初始化U盘,实际是识别U盘的类型,必须进行此步骤 */ mStopIfError( Status );Status = mIdenDisk( ); /* 识别分析U盘文件系统,必要操作 */mStopIfError( Status );Status = mReadSector( DiskStart + RsvdSecCnt + FATSz16 * 2, 32,DISK_BUFFER );mStopIfError( Status ); /* 读取FAT16逻辑盘的根目录,通常根目录占用32个扇区*/for ( CurrentDir = DISK_BUFFER; CurrentDir[0] != 0; CurrentDir += 32 ) {if ( ( CurrentDir[0x0B] & 0x08 ) == 0 && CurrentDir[0] != 0xE5 ) {CurrentDir[0x0B] = 0; /* 为了便于显示,设置文件名或者目录名的结束标志 */ printf( "Name: %s", CurrentDir ); /* 通过串口输出显示 */}} /* 以上显示根目录下的所有文件名,以下打开第一个文件,如果是C文件的话 */if ( (DISK_BUFFER[0x0B]&0x08)==0 && DISK_BUFFER[0]!=0xE5 && DISK_BUFFER[8] =='C' ) {Cluster = mGetPointWord( &DISK_BUFFER[0x1A] ); /* 文件的首簇 */while ( Cluster < 0xFFF8 ) { /* 文件簇未结束 */if ( Cluster == 0 ) mStopIfError( 0x8F ); /* 对于首簇,可能是0长度文件*/Status = mReadSector( mClusterToLba( Cluster ), SecPerClus,DISK_BUFFER );mStopIfError( Status ); /* 读取首簇到缓冲区 */DISK_BUFFER[30] = 0; printf( "Data: %s", DISK_BUFFER ); /* 显示首行*/Cluster = mLinkCluster( Cluster ); /* 获取链接簇,返回0说明错误 */}}while ( mWaitInterrupt( ) != USB_INT_DISCONNECT ); /* 等待U盘拔出 */mDelaymS( 250 );}}该程序可以支持WINDOWS按FAT16格式化的U盘__________________________。