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 );
}
}
Previous article:I2C bus (main) C51 source program
Next article:C51 PID Program
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Keysight Technologies Helps Samsung Electronics Successfully Validate FiRa® 2.0 Safe Distance Measurement Test Case
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- EEWORLD University Hall----Live Replay: HARTING- How to quickly and cost-effectively install cables in electrical control cabinets
- Introduction to Machine Vision Technology
- 【RT-Thread Reading Notes】1. RT-Thread RTOS Preface
- I would like to ask about an EXCEL curve fitting formula. I cannot get the value of Y by substituting the values of X (0, 150, 300). The value of Y is not correct.
- EEWORLD University ---- Sensors and Testing Technology
- The first question after the New Year is how dare I use this IGBT driving current.
- Bluetooth module interfaces
- Five factors to consider when designing a fixed wireless access (FWA) system
- Weak Bluetooth signal strength and excessive static power consumption of the product
- Analysis of the circuit diagram of infrared pair tube. Can someone please help me analyze it?