⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch375ev4.lst

📁 超精简的读写u盘程序
💻 LST
字号:
C51 COMPILER V7.07   CH375EV4                                                              03/09/2005 12:39:49 PAGE 1   


C51 COMPILER V7.07, COMPILATION OF MODULE CH375EV4
OBJECT MODULE PLACED IN CH375EV4.OBJ
COMPILER INVOKED BY: d:\Keil\C51\BIN\C51.EXE CH375EV4.C BROWSE DEBUG OBJECTEXTEND

stmt level    source

   1          /* 该程序用180行C代码就能够读取FAT16文件系统U盘的根目录,可以看到根目录下的文件名,并可显示首文件内容 */
   2          /* 注意,该程序很不严谨,也没有任何错误处理,对U盘兼容性较差,只是用于简单试验,作为参考 */
   3          /* 单片机读写U盘的程序分为4层: 硬件USB接口层, BulkOnly传输协议层, RBC/SCSI命令层, FAT文件系统层 */
   4          
   5          #include <stdio.h>
   6          #include "CH375INC.H"           /* 定义CH375命令代码及返回状态 */
   7          #include <reg51.h>                      /* 以下定义适用于MCS-51单片机,其它单片机参照修改 */
   8          #define UINT8           unsigned char
   9          #define UINT16          unsigned short
  10          #define UINT32          unsigned long
  11          #define UINT8X          unsigned char xdata
  12          #define UINT8VX         unsigned char volatile xdata
  13          UINT8VX         CH375_CMD_PORT _at_ 0xBDF1;     /* CH375命令端口的I/O地址 */
  14          UINT8VX         CH375_DAT_PORT _at_ 0xBCF0;     /* CH375数据端口的I/O地址 */
  15          #define         CH375_INT_WIRE          INT0    /* P3.2, 连接CH375的INT#引脚,用于查询中断状态 */
  16          UINT8X          DISK_BUFFER[512*32] _at_ 0x0000;        /* 外部RAM数据缓冲区的起始地址,长度不少于一次读写的数据长度 */
  17          
  18          UINT32  DiskStart;              /* 逻辑盘的起始绝对扇区号LBA */
  19          UINT8   SecPerClus;             /* 逻辑盘的每簇扇区数 */
  20          UINT8   RsvdSecCnt;             /* 逻辑盘的保留扇区数 */
  21          UINT16  FATSz16;                /* FAT16逻辑盘的FAT表占用的扇区数 */
  22          
  23          /* ********** 硬件USB接口层,无论如何这层省不掉,单片机总要与CH375接口吧 ***********************************
             -************************* */
  24          
  25          void    mDelaymS( UINT8 delay ) {               /* 以毫秒为单位延时,不精确,适用于24MHz时钟MCS51 */
  26   1              UINT8   i, j, c;
  27   1              for ( i = delay; i != 0; i -- ) {
  28   2                      for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
  29   2                      for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
  30   2              }
  31   1      }
  32          
  33          void CH375_WR_CMD_PORT( UINT8 cmd ) {   /* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 */
  34   1              CH375_CMD_PORT=cmd;
  35   1              for ( cmd = 2; cmd != 0; cmd -- );      /* 发出命令码前后应该各延时2uS,对于MCS51可以不需要延时 */
  36   1      }
  37          void CH375_WR_DAT_PORT( UINT8 dat ) {   /* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 */
  38   1              CH375_DAT_PORT=dat;                                     /* 因为MCS51单片机较慢所以实际上无需延时 */
  39   1      }
  40          UINT8 CH375_RD_DAT_PORT( void ) {               /* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
  41   1              return( CH375_DAT_PORT );                       /* 因为MCS51单片机较慢所以实际上无需延时 */
  42   1      }
  43          UINT8 mWaitInterrupt( void ) {  /* 等待CH375中断并获取状态,主机端等待操作完成,返回操作状态 */
  44   1              while( CH375_INT_WIRE );  /* 查询等待CH375操作完成中断(INT#低电平) */
  45   1              CH375_WR_CMD_PORT( CMD_GET_STATUS );  /* 产生操作完成中断,获取中断状态 */
  46   1              return( CH375_RD_DAT_PORT( ) );
  47   1      }
  48          
  49          /* ********** BulkOnly传输协议层,被CH375内置了,无需编写单片机程序 ****************************************
             -******************** */
  50          
  51          /* ********** RBC/SCSI命令层,虽然被CH375内置了,但是要写程序发出命令及收发数据 ****************************
             -******************************** */
  52          
C51 COMPILER V7.07   CH375EV4                                                              03/09/2005 12:39:49 PAGE 2   

  53          UINT8   mInitDisk( void ) {     /* 初始化磁盘 */
  54   1              UINT8 Status;
  55   1              CH375_WR_CMD_PORT( CMD_GET_STATUS );  /* 产生操作完成中断, 获取中断状态 */
  56   1              Status = CH375_RD_DAT_PORT( );
  57   1              if ( Status == USB_INT_DISCONNECT ) return( Status );  /* USB设备断开 */
  58   1              CH375_WR_CMD_PORT( CMD_DISK_INIT );  /* 初始化USB存储器 */
  59   1              Status = mWaitInterrupt( );  /* 等待中断并获取状态 */
  60   1              if ( Status != USB_INT_SUCCESS ) return( Status );  /* 出现错误 */
  61   1              CH375_WR_CMD_PORT( CMD_DISK_SIZE );  /* 获取USB存储器的容量 */
  62   1              Status = mWaitInterrupt( );  /* 等待中断并获取状态 */
  63   1              if ( Status != USB_INT_SUCCESS ) {  /* 出错重试 */
  64   2      /* 对于CH375A芯片,建议在此执行一次CMD_DISK_R_SENSE命令 */
  65   2                      mDelaymS( 250 );
  66   2                      CH375_WR_CMD_PORT( CMD_DISK_SIZE );  /* 获取USB存储器的容量 */
  67   2                      Status = mWaitInterrupt( );  /* 等待中断并获取状态 */
  68   2              }
  69   1              if ( Status != USB_INT_SUCCESS ) return( Status );  /* 出现错误 */
  70   1              return( 0 );  /* U盘已经成功初始化 */
  71   1      }
  72          
  73          UINT8   mReadSector( UINT32 iLbaStart, UINT8 iSectorCount, UINT8X *oDataBuffer ) {              /* 从U盘读取数据块到缓冲
             -区 */
  74   1      /* iLbaStart 起始扇区号, iSectorCount 扇区数, oDataBuffer 缓冲区起址 */
  75   1              UINT16  mBlockCount;
  76   1              UINT8   c;
  77   1              CH375_WR_CMD_PORT( CMD_DISK_READ );  /* 从USB存储器读数据块 */
  78   1              CH375_WR_DAT_PORT( (UINT8)iLbaStart );  /* LBA的最低8位 */
  79   1              CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 8 ) );
  80   1              CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 16 ) );
  81   1              CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 24 ) );  /* LBA的最高8位 */
  82   1              CH375_WR_DAT_PORT( iSectorCount );  /* 扇区数 */
  83   1              for ( mBlockCount = iSectorCount * 8; mBlockCount != 0; mBlockCount -- ) {  /* 数据块计数 */
  84   2                      c = mWaitInterrupt( );  /* 等待中断并获取状态 */
  85   2                      if ( c == USB_INT_DISK_READ ) {  /* 等待中断并获取状态,USB存储器读数据块,请求数据读出 */
  86   3                              CH375_WR_CMD_PORT( CMD_RD_USB_DATA );  /* 从CH375缓冲区读取数据块 */
  87   3                              c = CH375_RD_DAT_PORT( );  /* 后续数据的长度 */
  88   3                              while ( c -- ) *oDataBuffer++ = CH375_RD_DAT_PORT( );  /* 根据长度读取数据并保存 */
  89   3                              CH375_WR_CMD_PORT( CMD_DISK_RD_GO );  /* 继续执行USB存储器的读操作 */
  90   3                      }
  91   2                      else break;  /* 返回错误状态 */
  92   2              }
  93   1              if ( mBlockCount == 0 ) {
  94   2                      c = mWaitInterrupt( );  /* 等待中断并获取状态 */
  95   2                      if ( c== USB_INT_SUCCESS ) return( 0 );  /* 操作成功 */
  96   2              }
  97   1              return( c );  /* 操作失败 */
  98   1      }
  99          
 100          /* ********** FAT文件系统层,这层程序量实际较大,不过,该程序仅演示极简单的功能,所以精简 ********************
             -**************************************** */
 101          
 102          UINT16  mGetPointWord( UINT8X *iAddr ) {        /* 获取字数据,因为MCS51是大端格式,U盘FAT通常是小端格式,所以转换 */
 103   1              return( iAddr[0] | (UINT16)iAddr[1] << 8 );
 104   1      }
 105          
 106          UINT8   mIdenDisk( void ) {             /* 识别分析当前逻辑盘 */
 107   1              UINT8   Status;
 108   1              DiskStart = 0;  /* 以下是非常简单的FAT文件系统的分析,正式应用绝对不应该如此简单,否则兼容性和容错性差 */
 109   1              Status = mReadSector( 0, 1, DISK_BUFFER );  /* 读取逻辑盘引导信息 */
 110   1              if ( Status != 0 ) return( Status );
 111   1              if ( DISK_BUFFER[0] != 0xEB && DISK_BUFFER[0] != 0xE9 ) {  /* 不是逻辑引导扇区 */
 112   2                      DiskStart = DISK_BUFFER[0x1C6] | (UINT16)DISK_BUFFER[0x1C7] << 8 | (UINT32)DISK_BUFFER[0x1C8] << 16 | (U
C51 COMPILER V7.07   CH375EV4                                                              03/09/2005 12:39:49 PAGE 3   

             -INT32)DISK_BUFFER[0x1C9] << 24;
 113   2                      Status = mReadSector( DiskStart, 1, DISK_BUFFER );  /* 根据新的起始扇区号读取逻辑盘引导信息 */
 114   2                      if ( Status != 0 ) return( Status );
 115   2              }
 116   1              SecPerClus = DISK_BUFFER[0x0D];  /* 每簇扇区数 */
 117   1              RsvdSecCnt = DISK_BUFFER[0x0E];  /* 逻辑盘的保留扇区数 */
 118   1              FATSz16 = mGetPointWord( &DISK_BUFFER[0x16] );  /* FAT表占用扇区数 */
 119   1              return( 0 );  /* 成功 */
 120   1      }
 121          
 122          UINT16  mLinkCluster( UINT16 iCluster ) {       /* 获得指定簇号的链接簇 */
 123   1      /* 输入: iCluster 当前簇号, 返回: 原链接簇号, 如果为0则说明错误 */
 124   1              UINT8   Status;
 125   1              Status = mReadSector( DiskStart + RsvdSecCnt + iCluster / 256, 1, DISK_BUFFER );  /* 读取簇号所在的FAT扇

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -