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

📄 main.c

📁 单片机读写usb、sd卡技术参考资料
💻 C
字号:
#include <iom8v.h>
#include <macros.h>

#define PB375_VER				0x30	/* 当前模块版本 */

/* ********************************************************************************************************************* */
/* 返回的操作状态码 */
/* 以下是事件通知状态码,检测到当前U盘已经连接或者已经断开,可以作为最终状态码 */
#define	ERR_USB_CONNECT			0x15	/* 检测到USB设备连接事件,磁盘已经连接 */
#define ERR_DISK_DISCON			0x82	/* 检测到USB设备连接事件,磁盘已经断开,或者磁盘尚未连接 */
/* 代码0XH用于USB设备方式的操作状态代码,由PB375返回,是USB设备模式的中断状态 */
#define	ERR_USB_DAT_DOWN		0x02	/* USB设备模式: 数据下传成功,上位机下传的数据已经在模块中 */
#define	ERR_USB_DAT_UP			0x0A	/* USB设备模式: 数据上传成功,模块中的上传数据已经被上位机取走 */


/* 最终状态码 */
#define ERR_SUCCESS				0x00	/* 操作成功 */
#define ERR_PB375_ERROR			0x81	/* PB375硬件错误,可能需要复位PB375 */
#define ERR_STATUS_ERR			0x83	/* 磁盘状态错误,可能正在连接或者断开磁盘 */
#define ERR_MBR_ERROR			0x91	/* 磁盘的主引导记录无效,可能磁盘尚未分区或者尚未格式化 */
#define ERR_TYPE_ERROR			0x92	/* 磁盘分区类型不支持,只支持FAT12/FAT16/BigDOS/FAT32,需要由磁盘管理工具重新分区 */
#define ERR_BPB_ERROR			0xA1	/* 磁盘尚未格式化,或者参数错误,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_TOO_LARGE			0xA2	/* 磁盘非正常格式化并且容量大于4GB,或者容量大于250GB,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_FAT_ERROR			0xA3	/* 磁盘的文件系统不支持,只支持FAT12/FAT16/FAT32,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_DISK_FULL			0xB1	/* 磁盘文件太满,剩余空间太少或者已经没有,需要磁盘整理 */
#define ERR_FDT_OVER			0xB2	/* 目录内文件太多,没有空闲的目录项,FAT12/FAT16根目录下的文件数应该少于500个,需要磁盘整理 */
#define ERR_MISS_DIR			0xB3	/* 指定路径的某个子目录没有找到,可能是目录名称错误 */
#define ERR_FILE_CLOSE			0xB4	/* 文件已经关闭,如果需要使用,应该重新打开文件 */
#define ERR_OPEN_DIR			0x41	/* 指定路径的目录被打开 */
#define ERR_MISS_FILE			0x42	/* 指定路径的文件没有找到,可能是文件名称错误 */
#define ERR_FOUND_NAME			0x43	/* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中,如果需要使用,应该打开该文件 */
#define	ERR_USB_DISK_ERR		0x1F	/* USB存储器操作失败,在初始化时可能是USB存储器不支持,在读写操作中可能是磁盘损坏或者已经断开 */
/* 其余错误代码未定义,可以发出命令CMD_QueryStatus查询模块状态并分析 */

/* ********************************************************************************************************************* */
/* 磁盘及文件状态,适用于CMD_PARAM.Status.mDiskStatus */
#define DISK_UNKNOWN			0x00	/* 尚未初始化,未知状态 */
#define DISK_DISCONNECT			0x01	/* 磁盘没有连接或者已经断开 */
#define DISK_CONNECT			0x02	/* 磁盘已经连接,但是尚未初始化或者无法识别该磁盘 */
#define DISK_MOUNTED			0x03	/* 磁盘已经初始化成功,但是尚未分析文件系统或者文件系统不支持 */
#define DISK_READY				0x10	/* 已经分析磁盘的文件系统并且能够支持 */
#define DISK_OPEN_ROOT			0x12	/* 已经打开根目录,扇区模式,只能以扇区为单位读写目录的内容,使用后必须关闭,注意FAT12/FAT16根目录是固定长度 */
#define DISK_OPEN_DIR			0x13	/* 已经打开子目录,扇区模式,只能以扇区为单位读写目录的内容 */
#define DISK_OPEN_FILE			0x14	/* 已经打开文件,扇区模式,可以以扇区为单位进行数据读写 */
#define DISK_OPEN_FILE_B		0x15	/* 已经打开文件,字节模式,可以以字节为单位进行数据读写 */


/* 外部命令码 */
#define	CMD_DiskQuery			0x61	/* 查询磁盘信息 */
#define	CMD_FileOpen			0x64	/* 打开文件 */
#define	CMD_FileCreate			0x65	/* 新建文件并打开,如果文件已经存在则先删除后再新建 */
#define	CMD_FileErase			0x66	/* 删除文件并关闭 */
#define	CMD_FileClose			0x67	/* 关闭当前文件 */
#define	CMD_ByteLocate			0x7A	/* 以字节为单位移动当前文件指针 */
#define	CMD_ByteRead			0x7B	/* 以字节为单位从当前文件读取数据块 */
#define	CMD_ByteWrite			0x7C	/* 以字节为单位向当前文件写入数据块 */
#define	CMD_DiskReady			0x71	/* 查询磁盘是否准备好 */
#define CMD_RESET               0x7D    /*复位*/                


/*
  CS------PC0
  SCK-----PC1
  SDI-----PC3
  SDO-----PC2
*/

#define  PB375_CS_SET     PORTC |=  (1<<PC0)
#define  PB375_CS_CLR     PORTC &= ~ (1<<PC0)
#define  PB375_SCK_SET    PORTC |= (1<<PC1)
#define  PB375_SCK_CLR    PORTC &= ~(1<<PC1)
#define  PB375_SDI_SET    PORTC |= (1<<PC2)
#define  PB375_SDI_CLR    PORTC &= ~(1<<PC2)
#define  PB375_SDO        (PINC &(1<<PC3))

#define  MAXBUFLEN   128

//发送缓冲区
unsigned char sendBuff[MAXBUFLEN];
//接收缓冲区
unsigned char recBuff[MAXBUFLEN];



//初始化IO口  设置CS  SCK  SDI 为输出   SDO为输入
void initPort()
{
   PORTC |= 0x07;
   DDRC |= 0x07;
   DDRC &= 0xF7;
}


/* 以毫秒为单位延时,适用于24MHz时钟 */
void	mDelaymS( unsigned char delay )
{
	unsigned char	i, j, c;
	for ( i = delay; i != 0; i -- ) 
	{
		for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
		for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
	}
}


/* 发送一个字节数据给PB375模块,同时接收一个字节,以SPI模式0方式(SPI_SCK默认为0) */
unsigned char	mSpiExchange( unsigned char c )
{
	unsigned char	i, d;
	d = 0;
	PB375_SCK_CLR;
	for ( i = 8; i != 0; i -- ) {  /* 8个位 */
		if ( c & 0x80 ) 
		   PB375_SDI_SET;  /* 向模块的SDI输入引脚输出数据 */
		else 
		   PB375_SDI_CLR;
		d <<= 1;
		if ( PB375_SDO ) 
		 d++;  /* 如果模块的SDO输出引脚为高电平则输入位1 PB375_SDO */
		mDelaymS(1);                     
		PB375_SCK_SET;  /* SPI时钟上升沿,模块接收数据并输出数据 */
		c <<= 1;
		mDelaymS(1);                      
		PB375_SCK_CLR;
	}
	return( d );
}



/* 执行命令 */
unsigned char	ExecCommand( unsigned char cmd, unsigned char len )
{
	unsigned char		i, j, status;
	PB375_CS_CLR;  /* 产生SPI片选 */
	mSpiExchange( cmd );  /* 写入命令码 */
	mSpiExchange( len );  /* 写入后续参数的长度 */
	if ( len ) {  /* 有参数 */
		for ( i = 0; i != len; i ++ ) mSpiExchange( sendBuff[ i ] );  /* 依次写入参数 */
	}
	PB375_CS_SET;  /* 结束SPI片选 */
	while ( 1 ) {  /* 处理数据传输,直到操作完成才退出 */

		PB375_CS_CLR;  /* 产生SPI片选 */
		status = mSpiExchange( 0xFF );  /* 写入0xFF作为无效命令码(不应该写其它值),返回模块操作状态 */
		if ( status == 0xFF ) {  /* 模块操作尚未完成,也就是INT#没有中断产生 */
			PB375_CS_SET;  /* 结束SPI片选 */
			mDelaymS( 1 );
			continue;  /* 继续等待模块完成操作 */
		}

		if ( status == ERR_SUCCESS )  /* 操作成功 */ 
		{  
			i = mSpiExchange( 0 );  /* 返回结果数据的长度,写入0没有意义,可以是任何值 */
			if ( i ) {  /* 有结果数据 */
				j = 0;
				do {  /* 使用do+while结构是因为其效率高于for */
					recBuff[ j ] = mSpiExchange( 0 );  /* 接收结果数据并保存到参数结构中,写入0没有意义 */
					j ++;
				} while ( -- i );
			}
			PB375_CS_SET;  /* 结束SPI片选 */
			break;  /* 操作成功返回 */
		}
		else   /* 操作失败 */ 
		{  
			PB375_CS_SET;  /* 结束SPI片选 */
			if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT ) mDelaymS( 100 );  /* U盘刚刚连接或者断开,应该延时几十毫秒再操作 */
			break;  /* 操作失败返回 */
		}
		PB375_CS_SET;  /* 结束SPI片选 */
	}
	return( status );
}




/*
  主程序

*/
void main( ) 
{
	unsigned char	i;
		
	initPort();
	mDelaymS( 500 );  /* 延时500毫秒,PB375模块上电后需要500毫秒左右的复位时间 */
	for ( i = 0; i < 5; i ++ ) 
	{
		mDelaymS( 100 );
		if ( ExecCommand( CMD_DiskReady, 0 ) == ERR_SUCCESS ) 
			break;  /* 查询磁盘是否准备好 */
	}

         //在文件末尾追加数据
	     /*
		 sendBuff[0] = 92;
		 sendBuff[1] = 0x52;
		 sendBuff[2] = 0x41;
		 sendBuff[3] = 0x42;
		 sendBuff[4] = 0x43;
		 sendBuff[5] = 0x35;
		 sendBuff[6] = 0x36;
		 sendBuff[7] = 0x4C;
		 sendBuff[8] = 0x2e;
		 sendBuff[9] = 0x54;
		 sendBuff[10] = 0x58;
		 sendBuff[11] = 0x54;
		 sendBuff[12] = 0;
		
		 
		 sendBuff[0] = 92;
		 sendBuff[1] = 0x42;
		 sendBuff[2] = 0x4F;
		 sendBuff[3] = 0x44;
		 sendBuff[4] = 0x59;
		 sendBuff[5] = 0x44;
		 //sendBuff[6] = 0x41;
		 //sendBuff[7] = 0x54;
		 //sendBuff[8] = 0x41;
		 sendBuff[6] = 0x2E;
		 sendBuff[7] = 0x54;
		 sendBuff[8] = 0x58;
		 sendBuff[9] = 0x54;
		 sendBuff[10] = 0;
		 */
		  sendBuff[0] = 92;
	     strcpy(sendBuff+1,"BLUEFIVE.TXT");		     
	     if ( ExecCommand( CMD_FileOpen, 14 ) == ERR_SUCCESS )
	     {
	       //加一个字节定位
		   sendBuff[0] = 0xff;
		   sendBuff[1] = 0Xff;
		   sendBuff[2] = 0Xff;
		   sendBuff[3] = 0Xff;
		   
		   if ( ExecCommand( CMD_ByteLocate, 4 ) == ERR_SUCCESS )
		   {
		     sendBuff[0] = 10;//写入文件字节大小
		     strcpy(sendBuff+1,"11111111111111111111");
		     if ( ExecCommand( CMD_ByteWrite, 21 ) == ERR_SUCCESS )
		        ExecCommand( CMD_FileClose, 1 );
		   }
		   
	     }
	     else
	     {
	       //操作失败
	     }
	 
	while ( 1 ) 
	{  
	   /* 主循环 */	
	   mDelaymS( 100 );
	}
	
}

⌨️ 快捷键说明

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