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

📄 main._c

📁 AVR单片机制作U盘的源码
💻 _C
字号:
/*
name:main.c
writer:xiaowu
date:2009/1/6
****************************************
**  Copyright  (C)  fifth  2008-2009   **
**  Web:  http://www.chinamcu.com  **
****************************************
**  USB Host File Module      @PB375  **
**  AVR ATMega32             **
**  深圳第五元素科技有限公司  **
**  联系方式:0755-29739852
**  技术email:xiaowuyeah@163.com  **
discription:

 U盘文件读写模块, 连接方式: 软件模拟SPI时序+查询 
 AVR单片机C语言示例程序 

 以字节为单位进行U盘文件读写,单片机的RAM只需要几十个字节,不需要外部RAM 
*********************************************
*/


#include <iom16v.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	/* 查询磁盘是否准备好 */


/*
  CS------PB0
  SCK-----PB1
  SDI-----PB2
  SDO-----PB3
*/

#define  PB375_CS_SET   PORTB |= (1<<PB0)
#define  PB375_CS_CLR   PORTB &= ~(1<<PB0)
#define  PB375_SCK_SET    PORTB |= (1<<PB1)
#define  PB375_SCK_CLR    PORTB &= ~(1<<PB1)
#define  PB375_SDI_SET    PORTB |= (1<<PB2)
#define  PB375_SDI_CLR    PORTB &= ~(1<<PB2)
#define  PB375_SDO    (PINB &(1<<PB3))

#define  MAXBUFLEN   128

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



//初始化IO口  设置CS  SCK  SDI 为输出   SDO为输入
void initPort()
{
   PORTB |= 0x07;
   DDRB |= 0x07;
   DDRB &= 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 */
		PB375_SCK_SET;  /* SPI时钟上升沿,模块接收数据并输出数据 */
		c <<= 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	mStopIfError( unsigned char iError )
{
	unsigned char	led;
	if ( iError == ERR_SUCCESS ) return;  /* 操作成功 */
	led=0;
	while ( 1 ) {
		//LED_OUT = led&1;  /* LED闪烁 */
		mDelaymS( 100 );
		//led^=1;
	}
}


/*
  主程序

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

    //各种操作的代码
    oprCode = 5;
	switch(oprCode)
	{
	 case 1:   //删除文件
  	     sendBuff[0] = 92;
	     strcpy(sendBuff+1,"1.DAT");		     
	     if ( ExecCommand( CMD_FileErase, 7 ) == ERR_SUCCESS )
	     {
	       //操作成功
	     }
	     else
	     {
	       //操作失败
	     }
	     break;
	 case 2://写入数据到文件
	     sendBuff[0] = 92;
	     strcpy(sendBuff+1,"1.DAT");		     
	     if ( ExecCommand( CMD_FileOpen, 7 ) == ERR_SUCCESS )
	     {
	       //加一个字节定位
		   sendBuff[0] = 0;
		   sendBuff[1] = 0;
		   sendBuff[2] = 0;
		   sendBuff[3] = 0;
		   
		   if ( ExecCommand( CMD_ByteLocate, 4 ) == ERR_SUCCESS )
		   {
		     sendBuff[0] = 19;//写入文件字节大小
		     strcpy(sendBuff+1,"111111111111111111111111111111111111");
		     if ( ExecCommand( CMD_ByteWrite, 20 ) == ERR_SUCCESS )
		        ExecCommand( CMD_FileClose, 1 );
		   }
		   
	     }
	     else
	     {
	       //操作失败
	     }
	     break;
	 case 3://读取文件
	     sendBuff[0] = 92;
	     strcpy(sendBuff+1,"1.DAT");		     
	     if ( ExecCommand( CMD_FileOpen, 11 ) == ERR_SUCCESS )
	     {
		   sendBuff[0] = 11;//读取的字节数量
		   if (ExecCommand( CMD_ByteRead, 1 ) == ERR_SUCCESS )
		       ExecCommand( CMD_FileClose, 1 );//读取数据保持在recBuf[]
		   
	     }
	     else
	     {
	       //操作失败
	     }
	     break;	 	 
	  case 5://创建文件
		sendBuff[0] = 92;
		strcpy(sendBuff+1,"12345.DAT");		     
		if ( ExecCommand( CMD_FileCreate, 11 ) == ERR_SUCCESS )
		{
		   sendBuff[0] = 19;//写入文件字节大小
		   strcpy(sendBuff+1,"shenzhen diwuyuansu ");
		   if ( ExecCommand( CMD_ByteWrite, 20 ) == ERR_SUCCESS )
		      ExecCommand( CMD_FileClose, 1 );  //操作成功
		}
		else
		{
		   //操作失败
		}
		break;
	  case 6://写入文件
		sendBuff[0] = 92;
		strcpy(sendBuff+1,"1.DAT");		     
		if ( ExecCommand( CMD_FileErase, 7 ) == ERR_SUCCESS )
		{
		   //操作成功
		}
		else
		{
		   //操作失败
		}
		break;
	 default :break;
	} 	 	 	 
	while ( 1 ) 
	{  
	   /* 主循环 */	
	}
	
}

⌨️ 快捷键说明

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