USB(CH376)使用笔记-U盘的数据读写

  • 使用USB的数据导出功能,一种方式直接使用MCU的USB外设(且具有USB HOST)功能,MCU作为主机读取从机U盘;另一种方式,使用一个外置芯片,类似CH376这种(SPI接口或串口),芯片集成了文件系统和磁盘驱动,直接实现对U盘或SD卡的文件读写。

一、概述

  • CH376 是文件管理控制芯片,用于单片机系统读写 U 盘或者 SD 卡中的文件。
    同时可以使用 CH376 操作 USB 键盘鼠标,以及打印机等各种 USB 设备。
  • CH376 支持三种通讯接口:8 位并口,SPI 接口或者异步串口;

二、原理电路

USB(CH376)使用笔记-U盘的数据读写_第1张图片

三、步骤

  • 芯片相关初始化和使用的例程参照沁恒官方例程即可(推荐使用VS Code打开工程),移植根目录的.c.h文件(SPI_SW.C/H、FILE_SYS.C/H、CH376INC.H…)到自己的工程中。更多具体操作参照CH376编程指南。
  • https://download.csdn.net/download/Davidysw/16754214
    USB(CH376)使用笔记-U盘的数据读写_第2张图片

1、要使用芯片,首先就得做好通讯驱动,做好SPI的相关引脚初始化和INT引脚初始化。这里使用的是软件模拟SPI。程序里需要对5个引脚初始化,首先是SPI引脚(数据输入SDO,数据输出SDI,时钟SCK,片选SCS)初始化,其次是产生中断信号的INT引脚。

void CH376_PORT_INIT( void )  /* 由于使用软件模拟SPI读写时序,所以进行初始化 */
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH|RCC_AHB1Periph_GPIOI, ENABLE);  

    GPIO_InitStructure.GPIO_Pin = CH376_SCS_PIN;	   //CS
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//设置引脚的输出类型为推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(CH376_SCS_GPIO, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = CH376_SDI_PIN ;	  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//设置引脚的输出类型为推挽输出	 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(CH376_SDI_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = CH376_SCK_PIN;	  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	//设置引脚的输出类型为推挽输出	 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(CH376_SCK_GPIO, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = CH376_SDO_PIN ;	  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;  
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;	//设置引脚不上拉也不下拉
    GPIO_Init(CH376_SDO_GPIO, &GPIO_InitStructure);
		
	GPIO_InitStructure.GPIO_Pin = CH376_INT_PIN;	  // 6 INT
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;  	  //输入
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	
    GPIO_Init(CH376_INT_GPIO, &GPIO_InitStructure);
   
}

2、初始化引脚后需要先测试一下通讯是否成功,这是后续对U盘操作的关键之一,通讯必须要稳定。
USB(CH376)使用笔记-U盘的数据读写_第3张图片

UINT8	mInitCH376Host( void )  /* 初始化CH376 */
{
	UINT8	res;

	CH376_PORT_INIT( );  /* 接口硬件初始化 */

	xWriteCH376Cmd( CMD11_CHECK_EXIST );  /* 测试单片机与CH376之间的通讯接口 */
	xWriteCH376Data( 0x65 );
	res = xReadCH376Data( );
	xEndCH376Cmd();
   
	if ( res != 0x9A )
	{
			rt_kprintf("CH376 Int Failed\r\n");
			return( ERR_USB_UNKNOWN );  /* 通讯接口不正常,可能原因有:接口连接异常,其它设备影响(片选不唯一),串口波特率,一直在复位,晶振不工作 */
	}
	rt_kprintf("CH376 Int Success\r\n");
	xWriteCH376Cmd( CMD11_SET_USB_MODE );  /* 设备USB工作模式 */
	xWriteCH376Data( 0x06 );
	CH376DelaymS( 20 );
	res = xReadCH376Data( );
	xEndCH376Cmd();
	}

3、关键点二注意修改根据自己的工程环境修改延时函数mDelay0_5uS();
在这里插入图片描述
4、SPI通讯速率过快可适当减慢速度,硬件SPI直接配置相关寄存器即可,软件则加个延时。然后对应到CH376的SPI读写函数
USB(CH376)使用笔记-U盘的数据读写_第4张图片
USB(CH376)使用笔记-U盘的数据读写_第5张图片

5、现在就可以插上U盘进行测试了(自己尝试编写),调用FILE.C中的函数和CH376参考编程手册。FILE.C中的函数一般都有返回值,可以根据返回值来判断是否执行成功,或者没执行成功返回的错误码是什么,可以在CH376INC.H中查看。

USB(CH376)使用笔记-U盘的数据读写_第6张图片
举个例子,操作CH376读写U盘文件,错误返回值是0x22,根据查找是“获取中断状态并取消中断请求 ”,这肯定就与读写函数相关(产生中断信号),因此就注意查找读写函数哪部分是自己需要编写的内容(因为原厂提供的一般不会出错),只有延时函数是自己编写的,最初我只用了一个for循环简单模拟了一下延时,延时太短就产生了这个错误。

USB(CH376)使用笔记-U盘的数据读写_第7张图片
USB(CH376)使用笔记-U盘的数据读写_第8张图片
6、检测U盘是否连接、文件的创建、关闭,顺序写入都比较容易;开发过程中碰到比较费事的问题是,在原有文件中插入新的数据,经过测试发现插入新的数据如果与原有位置的数据量不同,这样就会覆盖后面的内容,因此要插入数据前需要先读后面的数据到缓冲区,插入完毕后,再向文件重新写入后面的数据(也可能有现成的插入数据函数,我没找到)。
7、开发过程中在文件的打开关闭中也遇到过问题,文件名要全大写,打开的文件名最好加上根目录(省去不必要开发过程中的错误)。

uint8_t FileName[] = {"/VI.CSV"};//不支持小写,需要加上绝对路径,不然关闭后再打开找不到文件

你可能感兴趣的:(stm32)