C51+CH375 USB disk reading example

Publisher:Ziyu2022Latest update time:2016-11-14 Source: eefocusKeywords:C51  CH375 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

I found a ready-made example. For reading and writing USB flash drives, the file system is a big problem. I still haven't figured it out yet. I'll save this program first and study it slowly later.

     The author's programming standards are good, with rich comments, and are worth learning.

#include  
#include "CH375INC.H" 
#include /* The following definitions are applicable to MCS-51 MCU */ 
#define UINT8 unsigned char 
#define UINT16 unsigned short 
#define UINT32 unsigned long 
#define UINT8X unsigned char xdata 
#define UINT8VX unsigned char volatile xdata 
UINT8VX CH375_CMD_PORT _at_ 0xBDF1; /* I/O address of CH375 command port */ 
UINT8VX CH375_DAT_PORT _at_ 0xBCF0; /* I/O address of CH375 data port */ 
#define CH375_INT_WIRE INT0 /* P3.2, connected to INT# pin of CH375, used to query 
interrupt  status */
UINT8X DISK_BUFFER[512*32] _at_ 0x0000; /* The starting address of the external RAM data buffer */ 

UINT32 DiskStart; /* The starting absolute sector number LBA of the logical disk */ 
UINT8 SecPerClus; /* The number of sectors per cluster of the logical disk */ 
UINT8 RsvdSecCnt; /* The number of reserved sectors of the logical disk */ 
UINT16 ; FATSz16; /* The number of sectors occupied by the FAT table of the FAT16 logical disk */  


/* ********** Hardware USB interface layer, this layer cannot be omitted anyway, the microcontroller must always interface with 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 ) { /* Write command to the command port of CH375 */ 
  CH375_CMD_PORT=cmd; 
  for ( cmd = 2; cmd != 0; cmd -- ); /* There should be a delay of 2uS before and after issuing the command code */ 

void CH375_WR_DAT_PORT( UINT8 dat ) { /* Write data to the data port of CH375 */ 
  CH375_DAT_PORT=dat; /* Because the MCS51 microcontroller is slow, there is actually no need for delay */

UINT8 CH375_RD_DAT_PORT( void ) { /* Read data from the data port of CH375 */ 
  return( CH375_DAT_PORT ); /* Because the MCS51 microcontroller is slow, there is actually no need for delay */ 

UINT8 mWaitInterrupt( void ) { /* Wait for CH375 interrupt and get status, return operation status */ 
  while( CH375_INT_WIRE ); /* Query and wait for CH375 operation completion interrupt (INT# low level) */ 
  CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* Generate operation completion interrupt, get interrupt status */ 
  return( CH375_RD_DAT_PORT() ); 


/* ********** BulkOnly transmission protocol layer, built-in by CH375, no need to write MCU program */ 

/* ********** RBC/SCSI command layer, although built-in by CH375, but need to write program to issue commands and send and receive data   
*/ 

UINT8 mInitDisk( void ) { /* Initialize disk */ 
  UINT8 Status; 
  CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* Generate operation completion interrupt, get interrupt status */ 
  Status = CH375_RD_DAT_PORT() ); 
  if ( Status == USB_INT_DISCONNECT ) return( Status ); /* USB device disconnected */ 
  CH375_WR_CMD_PORT( CMD_DISK_INIT ); /* Initialize USB storage */ 
  Status = mWaitInterrupt( ); /* Wait for interrupt and get status */ 
  if ( Status != USB_INT_SUCCESS ) return(Status ); /* Error occurred */ 
  CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* Get the capacity of USB storage */ 
  Status = mWaitInterrupt( ); /* Wait for interrupt and get status */ 
  if ( Status != USB_INT_SUCCESS ) { /* Retry if error occurs */ 
/* For CH375A chip, it is recommended to execute CMD_DISK_R_SENSE command once here */ 
    mDelaymS( 250 ); 
    CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* Get the capacity of USB storage */ 
    Status = mWaitInterrupt() ); /* Wait for interrupt and get status */ 
  } 
  if ( Status != USB_INT_SUCCESS ) return( Status ); /* Error occurred */ 
  return( 0 ); /* USB disk has been successfully initialized */ 
}  


UINT8 mReadSector( UINT32 iLbaStart, UINT8 iSectorCount, UINT8X *oDataBuffer )  

  UINT16 mBlockCount; 
  UINT8 c; 
  CH375_WR_CMD_PORT( CMD_DISK_READ ); /* Read data block from USB storage */ 
  CH375_WR_DAT_PORT( (UINT8)iLbaStart ); /* The lowest 8 bits of LBA */ 
  CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 8 ) ); 
  CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 16 ) ); 
  CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 24 ) ); /* LBA highest 8 bits */ 
  CH375_WR_DAT_PORT( iSectorCount ); /* Number of sectors */ 
  for ( mBlockCount = iSectorCount * 8; mBlockCount != 0; mBlockCount -- ) { 
    c = mWaitInterrupt() ); /* Wait for interrupt and get status */ 
    if ( c == USB_INT_DISK_READ ) { /* Wait for interrupt and get status, request data read */ 
      CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* Read data block from CH375 buffer */ 
      c = CH375_RD_DAT_PORT() ); /* Length of subsequent data */ 
      while ( c -- ) *oDataBuffer++ = CH375_RD_DAT_PORT( ); 
      CH375_WR_CMD_PORT( CMD_DISK_RD_GO ); /* Continue to execute the read operation of USB storage */ 
    } 
    else break; /* Return error status */ 
  } 
  if ( mBlockCount == 0 ) { 
    c = mWaitInterrupt( ); /* Wait for interrupt and get status*/ 
    if ( c== USB_INT_SUCCESS ) return( 0 ); /* Operation successful */ 
  } 
  return( c ); /* Operation failed */ 
}  


/* ********** FAT file system layer, this layer of program volume is actually larger, but this program only demonstrates very simple functions, 
so it  is simplified */

UINT16 mGetPointWord( UINT8X *iAddr ) { /* Get word data, because MCS51 is big endian format */ 
  return( iAddr[0] | (UINT16)iAddr[1] << 8 ); 


UINT8 mIdenDisk( void ) { /* Identify and analyze the current logical disk */ 
  UINT8 Status; 
  DiskStart = 0; /* The following is a very simple analysis of the FAT file system. The official application should not be so 
simple  */
  Status = mReadSector( 0, 1, DISK_BUFFER ); /* Read the logical disk boot information */ 
  if ( Status != 0 ) return( Status ); 
  if ( DISK_BUFFER[0] != 0xEB && DISK_BUFFER[0] != 0xE9 ) { /* Not a logical boot 
sector  */
    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]; /* Number of sectors per cluster */ 
  RsvdSecCnt = DISK_BUFFER[0x0E]; /* Number of reserved sectors of the logical disk */ 
  FATSz16 = mGetPointWord( &DISK_BUFFER[0x16] ); /* Number of sectors occupied by the FAT table */ 
  return( 0 ); /* Success */ 


UINT16 mLinkCluster( UINT16 iCluster ) { /* Get the link cluster of the specified cluster number */ 
/* Input: iCluster current cluster number, Return: original linked cluster number, if it is 0, it means error */ 
  UINT8 Status; 
  Status = mReadSector( DiskStart + RsvdSecCnt + iCluster / 256, 1,  
DISK_BUFFER ); 
  if ( Status != 0 ) return( 0 ); /* Error */ 
  return( mGetPointWord( &DISK_BUFFER[ ( iCluster + iCluster ) & 0x01FF ] ) ); 


UINT32 mClusterToLba(UINT16 iCluster ) { /* Convert cluster number to absolute LBA sector address */ 
  return( DiskStart + RsvdSecCnt + FATSz16 * 2 + 32 + ( iCluster - 2 ) *  
SecPerClus ); 
}  


void mInitSTDIO( void ) { /* It is only used for debugging and displaying content to the PC, and 
has nothing to do with  */
  SCON = 0x50; PCON = 0x80; TMOD = 0x20; TH1 = 0xf3; TR1=1; TI=1; /* 24MHz,  
9600bps */ 

void mStopIfError( UINT8 iErrCode ) { /* If an error occurs, stop running and display the error status */ 
  if ( iErrCode == 0 ) return; 
  printf( "Error status, %02X 
", (UINT16)iErrCode ); 


main() { 
  UINT8 Status; 
  UINT8X *CurrentDir; 
  UINT16 Cluster; 
  mDelaymS( 200 ); /* Delay 200 milliseconds */ 
  mInitSTDIO( ); 
  CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); /* Initialize CH375 and set USB working mode */ 
  CH375_WR_DAT_PORT( 6 ); /* Mode code, automatically detect USB device connection */ 
  while ( 1 ) { 
    printf( "Insert USB disk 
" ); 
    while ( mWaitInterrupt() != USB_INT_CONNECT ); /* Wait for USB disk connection */ 
    mDelaymS( 250 ); /* Delay waiting for USB disk to enter normal working state */ 
    Status = mInitDisk() ); /* Initialize USB disk, actually identify the type of USB disk, this step must be performed */ 
    mStopIfError( Status ); 
    Status = mIdenDisk() ); /* Identify and analyze USB disk file system, necessary operation */ 
    mStopIfError( Status ); 
    Status = mReadSector( DiskStart + RsvdSecCnt + FATSz16 * 2, 32,  
DISK_BUFFER ); 
    mStopIfError( Status ); /* Read the root directory of the FAT16 logical disk. Usually the root directory occupies 32 sectors  
*/ 
    for ( CurrentDir = DISK_BUFFER; CurrentDir[0] != 0; CurrentDir += 32 ) { 
      if ( ( CurrentDir[0x0B] & 0x08 ) == 0 && CurrentDir[0] != 0xE5 ) { 
        CurrentDir[0x0B] = 0; /* For easy display, set the end mark of the file name or directory name */ 
        printf( "Name: %s 
", CurrentDir ); /* Display through serial port output */ 
      } 
    } /* The above displays all file names in the root directory. The following opens the first file if it is C file */
    if ( (DISK_BUFFER[0x0B]&0x08)==0 && DISK_BUFFER[0]!=0xE5 && DISK_BUFFER[8] 
=='C' ) { 
      Cluster = mGetPointWord( &DISK_BUFFER[0x1A] ); /* First cluster of the file */ 
      while ( Cluster < 0xFFF8 ) { /* File cluster is not over */ 
        if ( Cluster == 0 ) mStopIfError( 0x8F ); /* For the first cluster, it may be a zero-length file  
*/ 
        Status = mReadSector( mClusterToLba( Cluster ), SecPerClus,  
DISK_BUFFER ); 
        mStopIfError( Status ); /* Read the first cluster into the buffer */ 
        DISK_BUFFER[30] = 0; printf( "Data: %s
", DISK_BUFFER ); /* Display the first line  
*/ 
        Cluster = mLinkCluster( Cluster ); /* Get the link cluster, return 0 to indicate an error */ 
      } 
    } 
    while ( mWaitInterrupt() != USB_INT_DISCONNECT ); /* Wait for the USB flash drive to be unplugged */ 
    mDelaymS( 250 ); 
  } 

Keywords:C51  CH375 Reference address:C51+CH375 USB disk reading example

Previous article:I2C bus (main) C51 source program
Next article:C51 PID Program

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号