单片机学习小组
直播中

神船大幅

11年用户 514经验值
私信 关注

如何使用CH376控制U盘-读写文件?

如何使用CH376控制U盘-读写文件?

回帖(1)

李舒桀

2022-2-22 11:09:04
该项目通过STM32芯片的IO口模拟SPI接口操作CH376芯片完成对U盘的读写操作。

CH376芯片内置了文件管理系统,可以通过简洁的命令操作U盘,完成读写文件等各种常规的U盘操作,用户不需要考虑FAT文件系统的底层知识,只需要使用基本的命令就行。官方提供了大量的函数,如果只是对U盘进行基本的操作的话,可以直接使用各种函数,不需要详细解读手册。

一、硬件准备:


STM32F103:作为一个主控芯片使用。

CH376:接口芯片,用来控制U盘完成文件读写操作。

CH340:监控鼠标的传输过程。

若干杜邦线,以及U盘等等基本



三、code


1.进入官网,下载好EVT压缩包并且解压。





文件从上到下依次是:

.EXAM:操作U盘的各种例程。

.CH376DBG.EXE:上位机的串口操作CH376的软件,可以通过串口调试工具,通过该软件读写文件。可以用来检查使用CH376串口接口时的硬件是否完整。

.CH376EVT.PDF:CH376资料的一个说明。包括对EXAM里面资料的一个简要说明。

.CH376SCH.PDF:CH376评估板的一个原理图。

.CH376编程指南.PDF:讲解如何移植代码等等。

2.找一个STM32的基本工程,随便一个都可以。

如下图,这里我们找一个UART的例程。创建好CH376的文件夹,将相应的文件放进去。



为什么是上面这些文件,是因为在后面移植代码时,发现都需要包含这些文件。例如打开一个EXAM7例程的参考文件“CH376HFT.C”。发现这个例程中会包含这些文件。

/* C51   CH376HFT.C */
/* LX51  CH376HFT.OBJ */
/* OHX51 CH376HFT */

#include
#include
#include

#include "..HAL.H"
#include "..HAL_BASE.C"
#include "..DEBUG.H"
#include "..DEBUG.C"
#include "..PARA_HW.C"                /* 硬件总线并口连接方式 */
//#include "..PARA_SW.C"                /* 软件模拟并口连接方式 */
//#include "..SPI_HW.C"                /* 硬件SPI连接方式 */
//#include "..SPI_SW.C"                /* 软件模拟SPI方式 */
//#include "..UART_HW.C"                /* 硬件异步串口连接方式 */
#define                EN_DISK_QUERY                1        /* 启用磁盘查询 */
#include "..FILE_SYS.H"
#include "..FILE_SYS.C"

UINT8                idata        buf[64];

main( ) {
}

打开工程,将这些文件添加至工程里面,加好文件路径。

然后在主函数里面添加例程例程里面的代码。

主要是移植好接口函数,以及中断函数,所有的函数都是基于“xWriteCH376Cmd” “xWriteCH376Data” “xReadCH376Data” “Query376Interrupt”这几个函数实现的。所以在移植代码时,理论上只需要调通这几个代码即可


/* SPI片选无效,结束CH376命令,仅用于SPI接口方式 */
void        xEndCH376Cmd( void )      
{
    CH376T_CS_HIGH;
}

/**************************************************************************************************
** 函数名称: xWriteCH376Cmd
** 功能描述: 向CH376写命令操作
** 输   入: mCmd-发送的命令
** 输   出: 无
*******************************************************************************************************/
void        xWriteCH376Cmd( UINT8 mCmd )  /*  */
{
//        CH376T_CS_HIGH;
        mDelay0_5uS( );
        CH376T_CS_LOW;           //CH376_SPI_SCS = 0;  /* SPI片选有效 */
        Spi376OutByte( mCmd );   /* 发出命令码 */
        mDelay0_5uS( ); mDelay0_5uS( ); mDelay0_5uS( );  /* 延时1.5uS确保读写周期大于1.5uS,或者用上面一行的状态查询代替 */
}

/**************************************************************************************************
** 函数名称: xWriteCH376Data
** 功能描述: 向CH376写数据操作
** 输   入: mData-发送的数据
** 输   出: 无
*******************************************************************************************************/
void        xWriteCH376Data( UINT8 mData )  /* 向CH376写数据 */
{
        Spi376OutByte( mData );
        mDelay0_5uS( );  /* 确保读写周期大于0.6uS */
}

/**************************************************************************************************
** 函数名称: xReadCH376Data
** 功能描述: 读取CH376的数据
** 输   入: 无
** 输   出: CH376返回的数据
*******************************************************************************************************/
UINT8        xReadCH376Data( void )  /* 从CH376读数据 */
{
        UINT8 s;
        mDelay0_5uS( );  /* 确保读写周期大于0.6uS */
        CH376T_CS_LOW;
        s  = Spi376InByte();
        mDelay0_5uS();
        return( s );
}

/* 查询CH376中断(INT#低电平) */
UINT8        Query376Interrupt( void )
{
#ifdef        CH376_INT_WIRE
        return( CH376_INT_WIRE ? FALSE : TRUE );  /* 如果连接了CH376的中断引脚则直接查询中断引脚 */
#else
        return( CH376_SPI_SDO ? FALSE : TRUE );  /* 如果未连接CH376的中断引脚则查询兼做中断输出的SDO引脚状态 */
#endif
}
Spi376OutByte函数是使用SPI输出一个字节的数据。

Spi376InByte函数是使用SPI读取一个字节的数据。

因为是模拟的SPI主机所以就是IO口直接拉的电平。

/**************************************************************************************************
** 函数名称: Spi376OutByte
** 功能描述: 模拟SPI输出8位数据
** 输   入: d-SPI发送的数据
** 输   出: 无
*******************************************************************************************************/
void        Spi376OutByte( UINT8 d )
{
        UINT8        i;
        for ( i = 0; i < 8; i ++ ) {
                CH376T_SCK_LOW;        //CH376_SPI_SCK = 0;
                if ( d & 0x80 )
                {
                        CH376T_SDI_HIGH;   //CH376_SPI_SDI = 1;
                }      
                else CH376T_SDI_LOW;   //CH376_SPI_SDI = 0;
                d <<= 1;               /* 数据位是高位在前 */
                CH376T_SCK_HIGH;       //CH376_SPI_SCK = 1;  /* CH376在时钟上升沿采样输入 */
      
        }
}

/**************************************************************************************************
** 函数名称: Spi376InByte
** 功能描述: 模拟SPI输入8位数据
** 输   入: 无
** 输   出: SPI接收的数据
*******************************************************************************************************/
UINT8        Spi376InByte( void )
{
        UINT8        i, d;
        d = 0;
        for ( i = 0; i < 8; i ++ ) {
                CH376T_SCK_LOW;          //CH376_SPI_SCK = 0;  /* CH376在时钟下降沿输出 */
                d <<= 1;                 /* 数据位是高位在前 */
                if ( GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) ) d ++;
//                delay_us(2);
                CH376T_SCK_HIGH;         //CH376_SPI_SCK = 1;
//                delay_us(2);
        }
        return( d );
}


主函数里面的代码如下,功能是,向U盘创建一个“ABC.TXT”的文件,并写入“hello world!!”。

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "HAL.H"
#include "FILE_SYS.H"

UINT8        TEST_BUFF[] =
{
        "hello world!!"
};
/**************************************************************************************************
** 函数名称: mStopIfError
** 功能描述: 检查函数是否操作成功,返回值为USB_INT_SUCCESS则操作成功,其他值则操作失败
** 输   入: iError-需要检查的参数
** 输   出: 无
*******************************************************************************************************/
void        mStopIfError( UINT8 iError )
{
    if ( iError == USB_INT_SUCCESS ) return;  /* 操作成功 */
    printf( "Error: %02Xn", (UINT16)iError );  /* 显示错误 */
    while ( 1 ) {
        ;
    }
}
int main(void)
{               
        UINT8 s;
        delay_init();                     //延时函数初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        uart_init(115200);         //串口初始化为115200
        printf("CH376_UDisk_TESTrn");

        while ( 1 )
        {
                printf( "Wait Udisk/SDn" );
                while ( CH376DiskConnect( ) != USB_INT_SUCCESS ) /* 检查U盘是否连接,等待U盘插入,对于SD卡,可以由单片机直接查询SD卡座的插拔状态引脚 */
                {  
                        mDelaymS( 100 );
                }
                mDelaymS( 200 );  /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */

                /* 对于检测到USB设备的,最多等待10*50mS */
                for ( s = 0; s < 10; s ++ )
                {
                        mDelaymS( 50 );
                        printf( "Ready ?n" );
                        if ( CH376DiskMount( ) == USB_INT_SUCCESS ) break;  /* 初始化磁盘并测试磁盘是否就绪 */
                }
               
        s = CH376FileCreate("/ABC.TXT");
                mStopIfError( s );
                CH376ByteWrite( TEST_BUFF, sizeof(TEST_BUFF), NULL );
                s = CH376FileClose( TRUE );
                mStopIfError( s );

                printf( "Take outn" );
                while ( CH376DiskConnect( ) == USB_INT_SUCCESS ) {  /* 检查U盘是否连接,等待U盘拔出 */
                        mDelaymS( 100 );
                }
                mDelaymS( 200 );
        }         
}

         
到此代码部分调试完成,剩下就是连接好硬件部分,进行测试。

四、硬件连接


使用的是SPI接口时需要注意,SPI的MOSI对应的CH376的SDI,MISO对应的SDO。

在芯片主控上面对应是

        PB10                 INT
        PB12                 SCS
        PB13                 SCK
        PB14                 SDO
        PB15                 SDI

举报

更多回帖

发帖
×
20
完善资料,
赚取积分