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

📄 ch375.c

📁 文件系统,运行硬件环境:单片机,软件环境:keilc
💻 C
字号:
/* 2004.03.05
****************************************
**                                    **
**                                    **
****************************************
**  USB 1.1 Host Examples for CH375   **
**  KC7.0@MCS-51                      **
****************************************
*/
/* CH375作为USB主机接口的程序示例 */

/* MCS-51单片机C语言的示例程序, U盘数据读写 */

#include "CH375.H"

UINT8  volatile xdata    CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */
UINT8  volatile xdata    CH375_DAT_PORT _at_ 0xBCF0; /* CH375数据端口的I/O地址 */
sbit  CH375_INT_WIRE  = 0xB0^2;             /* P3.2, INT0, 连接CH375的INT#引脚,用于查询中断状态 */

#define mDelay1uS( )            /* 对于MCS51单片机,通常不需要1uS延时 */

/* 延时2微秒,请根据单片机速度 */
void    mDelay2uS( )
{
    UINT8 i;
    for ( i = 2; i != 0; i -- );
}

/* 向CH375命令端口写命令数据 */
void CH375_CMD_PORT_d_out( UINT8 d_out )
{
    mDelay1uS( );
    CH375_CMD_PORT=d_out;
    mDelay2uS( );  /* 至少延时2uS */
}

/* 向CH375数据端口写数据 */
void CH375_DAT_PORT_d_out( UINT8 d_out )
{
    CH375_DAT_PORT=d_out;
    mDelay1uS( );
}

/* 从CH375命令端口读数据 */
UINT8 CH375_DAT_PORT_in( )
{
    mDelay1uS( );
    return( CH375_DAT_PORT );
}

/* 延时毫秒,不精确 */
void DelayMs(UINT8 nFactor)
{
    UINT8 i;
    UINT16 j;
    for(i=0; i<nFactor; i++) 
        for(j=0;j<1000;j++) 
            j=j;
}

/* 等待CH375中断并获取状态 */
UINT8   mWaitInterrupt( )
{
    UINT8 c;
    while ( CH375_INT_WIRE );  /* 如果CH375的中断引脚输出高电平则等待 */
    CH375_CMD_PORT_d_out( CMD_GET_STATUS);  /* 获取当前中断状态 */
    c = CH375_DAT_PORT_in();  /* 返回中断状态 */
    return( c );
}

/* 设置CH375为USB主机方式 */
UINT8 mCH375Init( )
{
    UINT8 i;
    CH375_CMD_PORT_d_out( CMD_GET_IC_VER);  /* 获取芯片及固件版本 */
    i = CH375_DAT_PORT_in( );  /* 版本 */
    if ( i < 0xA2 ) 
        return CH_ERROR;  /* 不支持该芯片 */
    CH375_CMD_PORT_d_out( CMD_SET_USB_MODE);  /* 设置USB工作模式 */
    CH375_DAT_PORT_d_out( 6);  /* 模式代码,自动检测USB设备连接 */
    for ( i = 0xff; i != 0; i -- ) {  /* 等待操作成功,通常需要等待10uS-20uS */
        if ( CH375_DAT_PORT_in() == CMD_RET_SUCCESS ) 
            return CH_OK;  /* 操作成功 */
    }
    return CH_ERROR;  /* CH375出错,例如芯片型号错或者处于串口方式或者不支持 */
}

/* 初始化磁盘 */
UINT8   mInitDisk( )
{
    UINT8 mIntStatus;
    CH375_CMD_PORT_d_out( CMD_DISK_INIT);  /* 初始化USB存储器 */
    mIntStatus = mWaitInterrupt( );  /* 等待中断并获取状态 */
    if ( mIntStatus == USB_INT_SUCCESS ) 
        return CH_OK;  /* U盘已经成功初始化 */
    return CH_ERROR;  /* 出现错误 */
}


/* 从U盘中读取多个扇区的数据块到缓冲区中 */
UINT8 RBC_Read(UINT32 iLbaStart, UINT8 iSectorCount,UINT8 xdata *mBufferPoint)
/* iLbaStart 是读取的线起始性扇区号, iSectorCount 是读取的扇区数 */
{
    UINT8 mIntStatus;
    UINT16  mBlockCount;
    UINT8 mLength;
    CH375_CMD_PORT_d_out(CMD_DISK_READ);  /* 从USB存储器读数据块 */
    CH375_DAT_PORT_d_out((UINT8)iLbaStart);  /* LBA的最低8位 */
    CH375_DAT_PORT_d_out((UINT8)(iLbaStart >> 8 ));
    CH375_DAT_PORT_d_out((UINT8)(iLbaStart >> 16 ));
    CH375_DAT_PORT_d_out((UINT8)( iLbaStart >> 24 ));  /* LBA的最高8位 */
    CH375_DAT_PORT_d_out( iSectorCount);  /* 扇区数 */
    for ( mBlockCount = iSectorCount * CH375_BLK_PER_SEC; mBlockCount != 0; mBlockCount -- ) {  /* 数据块计数 */
        mIntStatus = mWaitInterrupt( );  /* 等待中断并获取状态 */
        if ( mIntStatus == USB_INT_DISK_READ ) {  /* USB存储器读数据块,请求数据读出 */
            CH375_CMD_PORT_d_out(CMD_RD_USB_DATA);  /* 从CH375缓冲区读取数据块 */
            mLength = CH375_DAT_PORT_in();  /* 后续数据的长度 */
            /* 通常数据长度是64,有些U盘要求单片机必须在2mS之内取走64字节数据,否则U盘可能数据丢失 */
            /* 建议优化下面的循环程序,确保单片机在1mS之内完成64字节的数据传输 */
            if ( mLength ) {  /* 根据长度读取数据 */
                do {  // 对于C51,这个DO+WHILE结构效率高,速度快
                    *mBufferPoint = CH375_DAT_PORT_in();  /* 读出数据并保存 */
                    mBufferPoint ++;
                } while ( -- mLength );
            }
            CH375_CMD_PORT_d_out( CMD_DISK_RD_GO);  /* 继续执行USB存储器的读操作 */
        }
        else break;  /* 返回错误状态 */
    }
    if ( mBlockCount == 0 ) {
        mIntStatus = mWaitInterrupt( );  /* 等待中断并获取状态 */
        if ( mIntStatus == USB_INT_SUCCESS ) return CH_OK;  /* 操作成功 */
    }
    return CH_ERROR;  /* 操作失败 */
}

/* 将缓冲区中的多个扇区的数据块写入U盘 */
UINT8   RBC_Write( UINT32 iLbaStart, UINT8 iSectorCount,UINT8 xdata *mBufferPoint )
/* iLbaStart 是写入的线起始性扇区号, iSectorCount 是写入的扇区数 */
{
    UINT8 mIntStatus;
    UINT16  mBlockCount;
    UINT8 mLength;
    CH375_CMD_PORT_d_out( CMD_DISK_WRITE);  /* 向USB存储器写数据块 */
    CH375_DAT_PORT_d_out((UINT8)iLbaStart);  /* LBA的最低8位 */
    CH375_DAT_PORT_d_out((UINT8)( iLbaStart >> 8 ));
    CH375_DAT_PORT_d_out((UINT8)( iLbaStart >> 16 ));
    CH375_DAT_PORT_d_out((UINT8)( iLbaStart >> 24 ));  /* LBA的最高8位 */
    CH375_DAT_PORT_d_out(iSectorCount);  /* 扇区数 */
    //mBufferPoint = &DATA_BUFFER;  /* 指向缓冲区起始地址 */
    for ( mBlockCount = iSectorCount * CH375_BLK_PER_SEC; mBlockCount != 0; mBlockCount -- ) {  /* 数据块计数 */
        mIntStatus = mWaitInterrupt( );  /* 等待中断并获取状态 */
        if ( mIntStatus == USB_INT_DISK_WRITE ) {  /* USB存储器写数据块,请求数据写入 */
            CH375_CMD_PORT_d_out( CMD_WR_USB_DATA7);  /* 向CH375缓冲区写入数据块 */
            mLength = CH375_BLOCK_SIZE;
            CH375_DAT_PORT_d_out(mLength);  /* 后续数据的长度 */
            /* 通常数据长度是64,有些U盘要求单片机必须在2mS之内写入64字节数据,否则U盘可能数据丢失 */
            /* 建议优化下面的循环程序,确保单片机在1mS之内完成64字节的数据传输 */
            do {  // 对于C51,这个DO+WHILE结构效率高,速度快
                CH375_DAT_PORT_d_out(*mBufferPoint);  /* 将数据写入 */
                mBufferPoint ++;
            } while ( -- mLength );
            CH375_CMD_PORT_d_out( CMD_DISK_WR_GO);  /* 继续执行USB存储器的写操作 */
        }
        else break;  /* 返回错误状态 */
    }
    if ( mBlockCount == 0 ) {
        mIntStatus = mWaitInterrupt( );  /* 等待中断并获取状态 */
        if ( mIntStatus == USB_INT_SUCCESS ) return CH_OK;  /* 操作成功 */
    }
    return CH_ERROR;  /* 操作失败 */
}

⌨️ 快捷键说明

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