10899 views|19 replies

1379

Posts

0

Resources
The OP
 

MCS-51 microcontroller reads and writes USB flash drive (CH375 chip) [Copy link]

CH375 is a universal interface chip for USB bus, supporting HOST mode and SLAVE mode.
The schematic diagram of the circuit for MCS-51 microcontroller to read and write USB flash disk, the TXD pin of CH375 chip is connected to high level, and it works in serial port mode. In serial port mode, CH375 only needs to connect 3 signal lines with microcontroller/DSP/MCU, TXD pin, RXD pin and INT# pin, and other pins can be left floating. Except for fewer connection lines, other peripheral circuits are basically the same as parallel port mode. Since INT# pin and TXD pin can only provide weak high-level output current during CH375 reset, when making a long-distance connection, in order to avoid INT# or TXD being disturbed during CH375 reset and causing MCU misoperation, a pull-up resistor with a resistance of 1~5kΩ can be added to INT# pin or TXD pin to maintain a relatively stable high level. After the reset of CH375 chip is completed, INT# pin and TXD pin will be able to provide 5mA high-level output current or 5mA low-level sink current.

MCS

Since CH375 has built-in firmware
for processing Mass-Storage mass storage device's dedicated communication protocol, the embedded system's microcontroller can use the USB disk (USB flash drive, USB external hard disk) as a removable large-capacity storage device through CH375. Data reading and writing only requires a few instructions, without the need to understand the USB communication protocol in detail.
If the embedded system needs to organize the USB storage device into a file system, the interface API provided by the CH375 file-level subroutine library can be called, and the subroutine library will handle the file system.

The source code of the MCS-51 microcontroller reading and writing USB disk example is as follows:

#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; /* Starting address of external RAM data buffer*/

UINT32 DiskStart; /* The absolute starting 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; /* 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 is built into CH375, no need to write MCU program*/

/* ********** RBC/SCSI command layer, although built into CH375, but need to write a 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(

This post is from 51mcu

Latest reply

I am learning this chip, and now the program stops at while ( mWaitInterrupt() != USB_INT_CONNECT ); What is the problem? There is no interrupt return.   Details Published on 2014-7-31 18:52
 

1379

Posts

0

Resources
2
 
= Status ); /* Error occurred*/ CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* Get the capacity of the USB storage*/ Status = mWaitInterrupt( ); /* Wait for interrupt and get status*/ if ( Status != USB_INT_SUCCESS ) { /* Retry if error*/ /* For CH375A chip, it is recommended to execute the CMD_DISK_R_SENSE command once here*/ mDelaymS( 250 ); CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* Get the capacity of the USB storage*/ Status = mWaitInterrupt( ); /* Wait for interrupt and get status*/ } if ( Status != USB_INT_SUCCESS ) return( Status ); /* Error occurred*/ return( 0 ); /* The 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 ) ); /* The highest 8 bits of LBA*/ 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 USB storage read operation*/ } else break; /* Return error status*/ } if ( mBlockCount == 0 ) { c = mWaitInterrupt( ); /* Wait for interrupt and get status
This post is from 51mcu
 
 
 

1379

Posts

0

Resources
3
 
*/ if ( c== USB_INT_SUCCESS ) return( 0 ); /* Operation successful*/ } return( c ); /* Operation failed*/ } /* ********** FAT file system layer. The program size of this layer is actually relatively large. However, this program only demonstrates very simple functions, so it is concise*/ UINT16 mGetPointWord( UINT8X *iAddr ) { /* Get word data, because MCS51 is in 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 definitely not be so simple*/ Status = mReadSector( 0, 1, DISK_BUFFER ); /* Read the boot information of the logical disk*/ 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 linked 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(
This post is from 51mcu
 
 
 

1379

Posts

0

Resources
4
 
UINT16 iCluster ) { /* Convert cluster number to absolute LBA sector address*/ return( DiskStart + RsvdSecCnt + FATSz16 * 2 + 32 + ( iCluster - 2 ) * SecPerClus ); } void mInitSTDIO( void ) { /* Only for debugging purposes and displaying content to the PC, completely irrelevant to the function of this program*/ SCON = 0x50; PCON = 0x80; TMOD = 0x20; TH1 = 0xf3; TR1=1; TI=1; /* 24MHz, 9600bps */ } void mStopIfError( UINT8 iErrCode ) { /* Stop running and display error status if error occurs*/ if ( iErrCode == 0 ) return; printf( "Error status, %02X\n", (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, set USB working mode*/ CH375_WR_DAT_PORT( 6 ); /* Mode code, automatically detect USB device connection*/ while ( 1 ) { printf( "Insert USB disk\n" ); while ( mWaitInterrupt( ) != USB_INT_CONNECT ); /* Wait for USB disk to connect*/ 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 the USB file system, necessary operations*/ 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\n", CurrentDir );&n
This post is from 51mcu
 
 
 

1379

Posts

0

Resources
5
 
bsp; /* Display through serial port output*/ } } /* The above shows all file names in the root directory. The following opens the first file if it is a 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 to the buffer*/ DISK_BUFFER[30] = 0; printf( "Data: %s\n", 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 ); } } This program can support USB flash drives formatted in FAT16 by WINDOWS.
This post is from 51mcu
 
 
 

213

Posts

0

Resources
6
 
Thank you for your hard work!!!!!!!!!!!!!!!!!!!!!!!!
This post is from 51mcu
 
 
 

526

Posts

0

Resources
7
 
Good stuff, but the program uses this format, which looks a bit difficult. http://www.daxia.com/list_1700.shtml The code here is also OK [ This post was last edited by springvirus on 2009-4-24 13:53 ]
This post is from 51mcu

Comments

I am learning about this chip. Now the program stops at while ( mWaitInterrupt() != USB_INT_CONNECT ); What is the problem? There is no interrupt return.  Details Published on 2014-7-31 18:52
 
 
 

213

Posts

0

Resources
8
 
Good stuff, let’s take a look!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
This post is from 51mcu
 
 
 

213

Posts

0

Resources
9
 
Good stuff. Check it out! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! 1
This post is from 51mcu
 
 
 

213

Posts

0

Resources
10
 
Good stuff, but the program uses this format, which looks a bit difficult
This post is from 51mcu
 
 
 

35

Posts

0

Resources
11
 
Thank you, OP
This post is from 51mcu
 
 
 

29

Posts

0

Resources
12
 
Good stuff, but the program uses this format, which looks a bit difficult
This post is from 51mcu
 
 
 

1729

Posts

0

Resources
13
 
Learn more!
This post is from 51mcu
 
 
 

1469

Posts

0

Resources
14
 

Very good, very practical, maybe I will use it in the future, thanks

This post is from 51mcu
 
 
 

23

Posts

1

Resources
15
 
Is it more efficient to write in assembly?
This post is from 51mcu
 
 
 

3

Posts

0

Resources
16
 
This post will be popular
This post is from 51mcu
 
 
 

21

Posts

0

Resources
17
 
Thank you for your hard work!!!!!!!!!!!!!!!!!!!!!!!!
This post is from 51mcu
 
 
 

15

Posts

0

Resources
18
 
Learn! Thank you
This post is from 51mcu
 
 
 

21

Posts

0

Resources
19
 
Not bad
This post is from 51mcu
 
 
 

4

Posts

0

Resources
20
 
springvirus posted on 2009-4-24 13:38 Good stuff, but the program uses this format, which looks a bit difficult. http://www.daxia.com/list_1700.shtml Here is the code...
I am learning this chip, and now the program stops at while ( mWaitInterrupt() != USB_INT_CONNECT ); What is the problem? There is no interrupt return.
This post is from 51mcu
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list