打印

CH376大家有用过使用U盘写文件的吗?

[复制链接]
4193|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangjiahao88|  楼主 | 2016-10-14 12:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
wangjiahao88|  楼主 | 2016-10-14 12:58 | 只看该作者
/*******************************************************************************
* 函  数  名      : CH376DeviceInit
* 描      述      : CH376初始化子程序.
* 输      入      : 无.
* 返      回      : FALSE:
*                   无中断.
*                   TRUE:
*                   有中断.
*******************************************************************************/
void        CH376DeviceInit( void )
{
        UINT8 i;

        xWriteCH376Cmd( CMD_SET_USB_MODE );
        xWriteCH376Data( 2 );                                                                                                                                  /* 设置为使用内置固件的USB设备方式 */
        for ( i = 100; i != 0; i-- )
        {
                if ( xReadCH376Data( ) == CMD_RET_SUCCESS ) break;                                                          /* 等待操作成功,通常需要等待10uS-20uS */
        }
        xEndCH376Cmd( );                                                                                                                                          /* 结束CH376命令,仅用于SPI接口方式 */

使用特权

评论回复
板凳
wangjiahao88|  楼主 | 2016-10-14 12:58 | 只看该作者

/* 下面启用USB中断,CH376的INT#引脚可以连接到单片机的中断引脚,中断为低电平有效或者下降沿有效,
   如果不使用中断,那么也可以用查询方式,由单片机程序查询CH376的INT#引脚为低电平 */
        IT0 = 0;                                                                                                                                                          /* 置外部信号为低电平触发 */
        IE0 = 0;                                                                                                                                                          /* 清中断标志 */
        EX0 = 1;                                                                                                                                                          /* 允许CH376中断,假定CH376的INT#引脚连接到单片机的INT0 */
}
/************************************ End *************************************/       

使用特权

评论回复
地板
wangjiahao88|  楼主 | 2016-10-14 12:59 | 只看该作者
/*******************************************************************************
* 函  数  名      : mCh376Interrupt( )
* 描      述      : CH376中断服务程序,使用寄存器组1.
* 输      入      : 无.
* 返      回      : 无.
*******************************************************************************/
void        mCh376Interrupt( ) interrupt 0 using 1
{
        unsigned char InterruptStatus;
        unsigned char i, length;
        unsigned char data buffer[ 64 ];

        xWriteCH376Cmd( CMD_GET_STATUS );                                                                                                          /* 获取中断状态并取消中断请求 */
        InterruptStatus = xReadCH376Data( );                                                                                                  /* 获取中断状态 */
        xEndCH376Cmd( );                                                                                                                                          /* 结束CH376命令,仅用于SPI接口方式 */
        switch ( InterruptStatus )                                                                                                                         /* 分析中断状态处理 */
        {  
                case USB_INT_EP2_OUT:                                                                                                                         /* 批量端点下传成功 */               
                {  
                        xWriteCH376Cmd( CMD_RD_USB_DATA );                                                                                  /* 从当前USB中断的端点缓冲区读取数据块,并释放缓冲区 */
                        length = xReadCH376Data( );                                                                                                  /* 首先读取后续数据长度 */
                        for ( i = 0; i < length; i ++ )
                        {
                                buffer[ i ] = xReadCH376Data( );                                                                                  /* 接收数据包 */
                        }
                        xEndCH376Cmd( );                                                                                                                          /* 结束CH376命令,仅用于SPI接口方式 */
                        /* 测试数据正确性,将接收到的命令包数据取反后返回给PC机 */
                        xWriteCH376Cmd( CMD_WR_USB_DATA7 );                                                                                  /* 向USB端点2的发送缓冲区写入数据块 */
                        xWriteCH376Data( length );                                                                                                  /* 首先写入后续数据长度 */
                        for ( i = 0; i < length; i ++ )
                        {
                                xWriteCH376Data( ~ buffer[ i ] );                                                                                  /* 数据取反后返回,由计算机应用程序测试数据是否正确 */                               
                        }
                        xEndCH376Cmd( );                                                                                                                          /* 结束CH376命令,仅用于SPI接口方式 */
                        break;
                }
                case USB_INT_EP2_IN:                                                                                                                         /* 批量数据发送成功 */
                {  
                        xWriteCH376Cmd( CMD_UNLOCK_USB );                                                                                          /* 释放当前USB缓冲区,收到上传成功中断后,必须解锁USB缓冲区,以便继续收发 */
                        xEndCH376Cmd( );                                                                                                                          /* 结束CH376命令,仅用于SPI接口方式 */
                        break;
                }
                case  USB_INT_EP1_IN:                                                                                                                          /* 中断数据发送成功,本程序未用到 */
                {  
                        xWriteCH376Cmd( CMD_UNLOCK_USB );                                                                                          /* 释放当前USB缓冲区 */
                        xEndCH376Cmd( );                                                                                                                          /* 结束CH376命令,仅用于SPI接口方式 */
                        break;
                }       
        }
}

使用特权

评论回复
5
wangjiahao88|  楼主 | 2016-10-14 13:00 | 只看该作者
/*******************************************************************************
* 函  数  名      : main
* 描      述      : 主程序.
* 输      入      : 无.
* 返      回      : 无.
*******************************************************************************/
void main( )
{
        mDelaymS( 50 );                                                                                                                                                /* 延时等待CH375初始化完成,如果单片机由CH375提供复位信号则不必延时 */
        mInitSTDIO();                                                                                                                                                /* 初始化串口 */
        CH376_PORT_INIT();                                                                                                                                        /* 端口初始化 */
        CH376DeviceInit( );                                                                                                                                  /* 初始化CH376为设备模式 */       
        EA = 1;                                                                                                                                                          /* 允许中断 */
        printf("Wait INT \n");
        while ( 1 );                                                                                                                                                  /* 以下指令开始工作循环,等待PC机命令进行操作 */
}
/************************************ End *************************************/

使用特权

评论回复
6
wangjiahao88|  楼主 | 2016-10-14 13:01 | 只看该作者
* 描      述      : CH376芯片MCS-51单片机C语言的U盘文件读写示例程序.
*                   本程序演示字节读写,文件枚举,文件复制, 用于将U盘中的
*                   /C51/CH376HFT.C文件中的小写字母转成大写字母后, 写到新建的文件
*                   NEWFILE.TXT中,如果找不到原文件CH376HFT.C, 那么该程序将显示C51
*                   子目录下所有以CH376开头的文件名, 并新建NEWFILE.TXT文件并写入提
*                   示信息,如果找不到C51子目录, 那么该程序将显示根目录下的所有文件
*                   名, 并新建NEWFILE.TXT文件并写入提示信息.

使用特权

评论回复
7
wangjiahao88|  楼主 | 2016-10-14 13:01 | 只看该作者
/*******************************************************************************
* 函  数  名      : CopyAndConvertFile
* 描      述      : 文件复制,以字节方式复制,缓冲区越大速度越快.
* 输      入      : PUINT8 SrcFileName:
*                   源文件名,支持路径分隔符和多级目录,字符串必须存放于RAM中
*                   PUINT8 TarFileName
*                   目标文件名,支持路径分隔符和多级目录,字符串必须存放于RAM中
* 返      回      : 无.
*******************************************************************************/
UINT8        CopyAndConvertFile( PUINT8 SrcFileName, PUINT8 TarFileName )
{
        UINT8        s;
        UINT16        ThisLen, cnt;
        UINT32        FileSize, ByteCount = 0;
        UINT8        TarName;
        UINT32        TarUpDirClust;       
       
        do
        {
                printf( "OpenSrc \n" );                                                         /* 注意打印输出会浪费时间,减低平均复制速度 */
                s = CH376FileOpenPath( SrcFileName );                                           /* 打开多级目录下的文件,输入缓冲区必须在RAM中 */
                if ( s != USB_INT_SUCCESS )
                {
                    return( s );
                }
               
                if ( ByteCount == 0 )                                                           /* 首次 */
                {  
                        FileSize = CH376GetFileSize( );                                             /* 读取当前文件长度 */                       
                        printf( "SrcFileSz=%ld\n", FileSize );
                }
                else                                                                            /* 再次进入 */
            {  
                        s = CH376ByteLocate( ByteCount );                                           /* 以字节为单位移动当前文件指针到上次复制结束位置 */
                       
                        if ( s != USB_INT_SUCCESS )
                        {
                            return( s );   
                        }
                }
               
                printf( "Read\n" );
                s = CH376ByteRead( buf, sizeof( buf ), &ThisLen );                              /* 以字节为单位从当前位置读取数据块,请求长度同缓冲区大小,返回实际长度在ThisLen中 */
                if ( s != USB_INT_SUCCESS )
                {
                    return( s );
                }

                for ( cnt = 0; cnt < ThisLen; cnt++ )                                           /* 将缓冲区中的小写字符转换为大写 */
                {  
                        s = buf[ cnt ];
                        if ( s >= 'a' && s <= 'z' )
                        {
                            buf[ cnt ] = s - ( 'a' - 'A' );
                        }
                }

                if ( ByteCount == 0 )                                                           /* 首次,目标文件尚未存在 */
                {  
                        printf( "CreateTar\n" );
                        TarName = CH376SeparatePath( TarFileName );                                 /* 从路径中分离出最后一级文件名或目录名,返回最后一级文件名或目录名的偏移 */
                        if ( TarName )                                                              /* 是多级目录 */
                        {  
                                s = CH376FileOpenDir( TarFileName, TarName );                           /* 打开多级目录下的最后一级目录,即打开新建文件的上级目录 */
                                if ( s != ERR_OPEN_DIR )                                                /* 因为是打开上级目录,所以,如果不是成功打开了目录,那么说明有问题 */
                                {  
                                        if ( s == USB_INT_SUCCESS )
                                        {
                                            return( ERR_FOUND_NAME );                                       /* 中间路径必须是目录名,如果是文件名则出错 */
                                        }
                                        else if ( s == ERR_MISS_FILE )
                                        {
                                            return( ERR_MISS_DIR );                                         /* 中间路径的某个子目录没有找到,可能是目录名称错误 */
                                        }
                                        else
                                        {
                                            return( s );                                                    /* 操作出错 */
                                        }
                                }
                                TarUpDirClust = CH376ReadVar32( VAR_START_CLUSTER );                    /* 上级目录的起始簇号 */
                        }
                        else
                        {
                            TarUpDirClust = 0;                                                      /* 默认是根目录的起始簇号 */
                        }
/* 在当前目录下进行文件新建或者打开操作,比全路径多级目录下的文件新建或者打开操作的速度快,
   所以目标文件的新建或者打开采用此法处理(本程序源文件是直接打开全路径多级目录下的文件,为提高速度,也可参照此法加快文件打开),
   为了实现当前目录下的文件新建或者打开操作,参考上面几行代码,
   首先,要获得文件所在的上级目录的起始簇号,相当于打开上级目录,通过CH376FileOpenPath打开上级目录获得,
   其次,要获得文件的直接短文件名(去掉上级目录名,不含任何路径分隔符,保留最后一级文件名),通过CH376SeparatePath分析目标文件名获得 */
                        s = CH376FileCreate( &TarFileName[TarName] );                               /* 在根目录或者当前目录下新建文件,如果文件已经存在那么先删除 */
                        if ( s != USB_INT_SUCCESS )
                    {
                        return( s );
                    }
                }
                else                                                                            /* 再次进入,目标文件已存在 */
                {  
                        printf( "OpenTar\n" );
                        CH376WriteVar32( VAR_START_CLUSTER, TarUpDirClust );                        /* 将目标文件所在的上级目录的起始簇号设置为当前簇号,相当于打开上级目录 */
                        s = CH376FileOpen( &TarFileName[TarName] );                                 /* 打开文件 */
                        if ( s != USB_INT_SUCCESS )
                        {
                            return( s );
                        }
                       
                        s = CH376ByteLocate( ByteCount );                                           /* 以字节为单位移动当前文件指针到上次复制结束位置 */
                        if ( s != USB_INT_SUCCESS )
                        {
                            return( s );
                        }
                }
               
                printf( "Write\n" );
                s = CH376ByteWrite( buf, ThisLen, NULL );                                       /* 以字节为单位向当前位置写入数据块,除非没有磁盘空间,否则返回实际长度总是与ThisLen相等 */
                if ( s != USB_INT_SUCCESS )
                {
                    return( s );
                }
                printf( "CloseTar\n" );
               
                s = CH376FileClose( TRUE );                                                     /* 关闭文件,对于字节读写建议自动更新文件长度 */
                if ( s != USB_INT_SUCCESS )
                {
                    return( s );
                }
               
                ByteCount += ThisLen;
               
                if ( ThisLen < sizeof( buf ) )                                                  /* 实际读出字节数小于请求读出字节数,说明原文件结束 */
                {  
                        if ( ByteCount != FileSize )
                        {
                            printf( "Error on SourceFile reading" );
                        }
                        break;
                }
               
        } while( ByteCount < FileSize );
       
        return( USB_INT_SUCCESS );
}

使用特权

评论回复
8
wangjiahao88|  楼主 | 2016-10-14 13:02 | 只看该作者
/*******************************************************************************
* 函  数  名      : main
* 描      述      : 主程序.
* 输      入      : 无.
* 返      回      : 无.
*******************************************************************************/
void         main( )
{
        UINT8 i, s;
        P_FAT_DIR_INFO        pDir;
        UINT8        xdata        SrcName[64];
        UINT8        xdata        TarName[64];
       
        P35        = 1;                                                                                                                                                        /* 复位 */
        mDelaymS( 20 );
        P35        = 0;                                                                                                                                                        /* 禁止复位 */
        mDelaymS( 100 );                                                                    /* 延时100毫秒 */
        mInitSTDIO( );                                                                      /* 为了让计算机通过串口监控演示过程 */
        printf( "Start\n" );
        s = mInitCH376Host( );                                                              /* 初始化CH376 */
        mStopIfError( s );
        while ( 1 )
        {
                printf( "Wait Disk\n" );
                while ( CH376DiskConnect( ) != USB_INT_SUCCESS )                                /* 检查U盘是否连接,等待U盘插入,对于SD卡,可以由单片机直接查询SD卡座的插拔状态引脚 */
                {  
                        mDelaymS( 100 );
                }
                mDelaymS( 200 );                                                                /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */
/* 对于检测到USB设备的,最多等待100*50mS,主要针对有些MP3太慢,对于检测到USB设备并且连接DISK_MOUNTED的,最多等待5*50mS,主要针对DiskReady不过的 */
               
                for ( i = 0; i < 100; i ++ )                                                    /* 最长等待时间,100*50mS */
                {  
                        mDelaymS( 50 );
                        printf( "Ready ?\n" );
                        s = CH376DiskMount( );                                                      /* 初始化磁盘并测试磁盘是否就绪 */
                        if ( s == USB_INT_SUCCESS )                                                 /* 准备好 */
                        {
                            break;                                          
                        }
                        else if ( s == ERR_DISK_DISCON )                                            /* 检测到断开,重新检测并计时 */
                    {
                        break;  
                    }
                        if ( CH376GetDiskStatus( ) >= DEF_DISK_MOUNTED && i >= 5 )                  /* 有的U盘总是返回未准备好,不过可以忽略,只要其建立连接MOUNTED且尝试5*50mS */
                        {
                            break;           
                        }
                }
               
                if ( s == ERR_DISK_DISCON )                                                     /* 检测到断开,重新检测并计时 */
                {  
                        printf( "Device gone\n" );
                        continue;
                }
               
                if ( CH376GetDiskStatus( ) < DEF_DISK_MOUNTED )                                 /* 未知USB设备,例如USB键盘、打印机等 */
                {  
                        printf( "Unknown device\n" );
                        goto UnknownUsbDevice;
                }
               
                i = CH376ReadBlock( buf );                                                      /* 如果需要,可以读取数据块CH376_CMD_DATA.DiskMountInq,返回长度 */
                if ( i == sizeof( INQUIRY_DATA ) )                                              /* U盘的厂商和产品信息 */
            {  
                        buf[ i ] = 0;
                        printf( "UdiskInfo: %s\n", ((P_INQUIRY_DATA)buf) -> VendorIdStr );
                }

        /******************************* 读取原文件 ***********************************/
                strcpy( SrcName, "\\C51\\CH376HFT.C" );                                         /* 源文件名,多级目录下的文件名和路径名必须复制到RAM中再处理,而根目录或者当前目录下的文件名可以在RAM或者ROM中 */
                strcpy( TarName, "\\NEWFILE.TXT" );                                             /* 目标文件名 */
                printf( "Open\n" );
                s = CH376FileOpenPath( SrcName );                                               /* 打开文件,该文件在C51子目录下 */
                if ( s == ERR_MISS_DIR || s == ERR_MISS_FILE )                                  /* 没有找到目录或者没有找到文件 */
                {  
            /* 列出文件,完整枚举可以参考EXAM13全盘枚举 */
                        if ( s == ERR_MISS_DIR )
                        {
                            strcpy( buf, "\\*" );                                                   /* C51子目录不存在则列出根目录下的文件 */
                        }
                        else
                    {
                        strcpy( buf, "\\C51\\CH376*" );                                         /* CH376HFT.C文件不存在则列出\C51子目录下的以CH376开头的文件 */
                    }
                       
                        printf( "List file %s\n", buf );
                        s = CH376FileOpenPath( buf );                                               /* 枚举多级目录下的文件或者目录,输入缓冲区必须在RAM中 */
                        while ( s == USB_INT_DISK_READ )                                            /* 枚举到匹配的文件 */
                        {  
                                CH376ReadBlock( buf );                                                  /* 读取枚举到的文件的FAT_DIR_INFO结构,返回长度总是sizeof( FAT_DIR_INFO ) */
                                pDir = (P_FAT_DIR_INFO)buf;                                             /* 当前文件目录信息 */
                                if ( pDir -> DIR_Name[0] != '.' )                                       /* 不是本级或者上级目录名则继续,否则必须丢弃不处理 */
                                {  
                                        if ( pDir -> DIR_Name[0] == 0x05 )
                                        {
                                            pDir -> DIR_Name[0] = 0xE5;                                     /* 特殊字符替换 */
                                        }
                                        pDir -> DIR_Attr = 0;                                               /* 强制文件名字符串结束以便打印输出 */
                                        printf( "*** EnumName: %s\n", pDir -> DIR_Name );                   /* 打印名称,原始8+3格式,未整理成含小数点分隔符 */
                                }
                       
                                xWriteCH376Cmd( CMD0H_FILE_ENUM_GO );                                   /* 继续枚举文件和目录 */
                                xEndCH376Cmd( );
                                s = Wait376Interrupt( );
                        }
                       
                        if ( s != ERR_MISS_FILE )                                                   /* 操作出错 */
                        {
                            mStopIfError( s );  
                        }
                       
                        printf( "Create\n" );
                        s = CH376FileCreatePath( TarName );                                                                                  /* 新建多级目录下的文件,支持多级目录路径,输入缓冲区必须在RAM中 */
                        mStopIfError( s );
                       
                        printf( "Write\n" );
                        strcpy( buf, "找不到/C51/CH376HFT.C文件\xd\n" );
                        s = CH376ByteWrite( buf, strlen(buf), NULL );                               /* 以字节为单位向当前位置写入数据块 */
                        mStopIfError( s );
                        printf( "Close\n" );
                       
                        s = CH376FileClose( TRUE );                                                 /* 关闭文件,对于字节读写建议自动更新文件长度 */
                        mStopIfError( s );
                       
                }
                else                                                                            /* 找到文件或者出错 */
            {  
                        mStopIfError( s );
                        s = CopyAndConvertFile( SrcName, TarName );                                 /* 文件复制 */
                        mStopIfError( s );
                }

                printf( "DiskQuery: " );                                                                                                                /* 检查U盘或者SD卡的剩余空间 */
                s = CH376DiskQuery( (PUINT32)buf );                                                                                                /* 查询磁盘剩余空间信息,扇区数 */
                mStopIfError( s );
                printf( "free cap = %ld MB\n", *(PUINT32)buf / ( 1000000 / DEF_SECTOR_SIZE ) );

UnknownUsbDevice:                                                                                                                                                /* 未知设备 */
   
                printf( "Take out\n" );
                while ( CH376DiskConnect( ) == USB_INT_SUCCESS )                                /* 检查U盘是否连接,等待U盘拔出 */
                {  
                        mDelaymS( 100 );
                }
                mDelaymS( 200 );
        }
}

使用特权

评论回复
9
merry_zsp| | 2016-10-15 21:24 | 只看该作者
需要移植一个文件系统的。比如fatfs。

使用特权

评论回复
10
mdk55555| | 2016-10-18 22:09 | 只看该作者
CH376是什么芯片呢?没有用过

使用特权

评论回复
11
wangjiahao88|  楼主 | 2016-10-19 17:10 | 只看该作者
这个 不需要移植什么系统的。。。就是 片内集成的。

使用特权

评论回复
12
haokeer| | 2016-10-19 20:16 | 只看该作者
CH376 是文件管理控制芯片,用于单片机系统读写U 盘或者SD 卡中的文件

使用特权

评论回复
13
xiaolong12| | 2016-10-19 21:56 | 只看该作者
haokeer 发表于 2016-10-19 20:16
CH376 是文件管理控制芯片,用于单片机系统读写U 盘或者SD 卡中的文件

为什么不能直接访问呢?直接访问也不需要这个额外的芯片吧?

使用特权

评论回复
14
wangjiahao88|  楼主 | 2016-10-21 15:14 | 只看该作者
不需要额外的芯片的!内部集成了 fatfs文件系统!

使用特权

评论回复
15
rmbass| | 2016-10-21 16:22 | 只看该作者
即使内部集成了fatfs文件系统,那软件移植和硬件集成有区别吗?

使用特权

评论回复
16
yysforever| | 2016-10-22 16:08 | 只看该作者
rmbass 发表于 2016-10-21 16:22
即使内部集成了fatfs文件系统,那软件移植和硬件集成有区别吗?

好多事情硬件干了,软件上的功夫就少了。

使用特权

评论回复
17
冰是睡着的冰| | 2016-10-22 17:42 | 只看该作者
官方应该会提供移植的例程了吧,直接移植就OK啦。

使用特权

评论回复
18
jouney316| | 2016-10-22 21:06 | 只看该作者
mdk55555 发表于 2016-10-18 22:09
CH376是什么芯片呢?没有用过

CH376 是文件管理控制芯片,用于单片机系统读写U 盘或者SD 卡中的文件

使用特权

评论回复
19
Dennis-Zhou| | 2016-10-23 22:17 | 只看该作者
没有用过,直接用芯片自带的usb接口,又方便又省事。

使用特权

评论回复
20
wangjiahao88|  楼主 | 2016-10-25 16:27 | 只看该作者
CH376 是文件管理控制芯片,用于单片机系统读写U 盘或者SD 卡中的文件

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

473

主题

7517

帖子

30

粉丝