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

📄 main.s

📁 AVR单片机制作U盘的源码
💻 S
📖 第 1 页 / 共 2 页
字号:
	.module main.c
	.area text(rom, con, rel)
	.dbfile E:\电子项目\北极熊模块\例程\AVR\main.c
	.dbfunc e initPort _initPort fV
	.even
_initPort::
	.dbline -1
	.dbline 110
; /*
; 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()
; {
	.dbline 111
;    PORTB |= 0x07;
	in R24,0x18
	ori R24,7
	out 0x18,R24
	.dbline 112
;    DDRB |= 0x07;
	in R24,0x17
	ori R24,7
	out 0x17,R24
	.dbline 113
;    DDRB &= 0xF7;
	in R24,0x17
	andi R24,247
	out 0x17,R24
	.dbline -2
L1:
	.dbline 0 ; func end
	ret
	.dbend
	.dbfunc e mDelaymS _mDelaymS fV
;              i -> R20
;              c -> R10
;              j -> R22
;          delay -> R16
	.even
_mDelaymS::
	xcall push_gset3
	.dbline -1
	.dbline 119
; }
; 
; 
; /* 以毫秒为单位延时,适用于24MHz时钟 */
; void	mDelaymS( unsigned char delay )
; {
	.dbline 121
	mov R20,R16
	xjmp L6
L3:
	.dbline 121
; 	unsigned char	i, j, c;
; 	for ( i = delay; i != 0; i -- ) {
	.dbline 122
	ldi R22,200
	xjmp L10
L7:
	.dbline 122
	mov R24,R10
	subi R24,253    ; addi 3
	mov R10,R24
L8:
	.dbline 122
	dec R22
L10:
	.dbline 122
; 		for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
	tst R22
	brne L7
	.dbline 123
	ldi R22,200
	xjmp L14
L11:
	.dbline 123
	mov R24,R10
	subi R24,253    ; addi 3
	mov R10,R24
L12:
	.dbline 123
	dec R22
L14:
	.dbline 123
	tst R22
	brne L11
	.dbline 124
L4:
	.dbline 121
	dec R20
L6:
	.dbline 121
	tst R20
	brne L3
	.dbline -2
L2:
	xcall pop_gset3
	.dbline 0 ; func end
	ret
	.dbsym r i 20 c
	.dbsym r c 10 c
	.dbsym r j 22 c
	.dbsym r delay 16 c
	.dbend
	.dbfunc e mSpiExchange _mSpiExchange fc
;              d -> R20
;              i -> R22
;              c -> R16
	.even
_mSpiExchange::
	xcall push_gset2
	.dbline -1
	.dbline 129
; 		for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
; 	}
; }
; 
; /* 发送一个字节数据给PB375模块,同时接收一个字节,以SPI模式0方式(SPI_SCK默认为0) */
; unsigned char	mSpiExchange( unsigned char c )
; {
	.dbline 131
; 	unsigned char	i, d;
; 	d = 0;
	clr R20
	.dbline 132
; 	PB375_SCK_CLR;
	cbi 0x18,1
	.dbline 133
	ldi R22,8
	xjmp L19
L16:
	.dbline 133
; 	for ( i = 8; i != 0; i -- ) {  /* 8个位 */
	.dbline 134
; 		if ( c & 0x80 ) 
	sbrs R16,7
	rjmp L20
	.dbline 135
; 		   PB375_SDI_SET;  /* 向模块的SDI输入引脚输出数据 */
	sbi 0x18,2
	xjmp L21
L20:
	.dbline 137
; 		else 
; 		   PB375_SDI_CLR;
	cbi 0x18,2
L21:
	.dbline 138
; 		d <<= 1;
	lsl R20
	.dbline 139
; 		if ( PB375_SDO ) 
	sbis 0x16,3
	rjmp L22
	.dbline 140
; 		 d++;  /* 如果模块的SDO输出引脚为高电平则输入位1 PB375_SDO */
	inc R20
L22:
	.dbline 141
	sbi 0x18,1
	.dbline 142
	lsl R16
	.dbline 143
	cbi 0x18,1
	.dbline 144
L17:
	.dbline 133
	dec R22
L19:
	.dbline 133
	tst R22
	brne L16
	.dbline 145
; 		PB375_SCK_SET;  /* SPI时钟上升沿,模块接收数据并输出数据 */
; 		c <<= 1;
; 		PB375_SCK_CLR;
; 	}
; 	return( d );
	mov R16,R20
	.dbline -2
L15:
	xcall pop_gset2
	.dbline 0 ; func end
	ret
	.dbsym r d 20 c
	.dbsym r i 22 c
	.dbsym r c 16 c
	.dbend
	.dbfunc e ExecCommand _ExecCommand fc
;         status -> R20
;              i -> R22
;              j -> R10
;            len -> R10
;            cmd -> R20
	.even
_ExecCommand::
	xcall push_gset3
	mov R10,R18
	mov R20,R16
	.dbline -1
	.dbline 152
; }
; 
; 
; 
; /* 执行命令 */
; unsigned char	ExecCommand( unsigned char cmd, unsigned char len )
; {
	.dbline 154
; 	unsigned char		i, j, status;
; 	PB375_CS_CLR;  /* 产生SPI片选 */
	cbi 0x18,0
	.dbline 155
; 	mSpiExchange( cmd );  /* 写入命令码 */
	mov R16,R20
	xcall _mSpiExchange
	.dbline 156
; 	mSpiExchange( len );  /* 写入后续参数的长度 */
	mov R16,R10
	xcall _mSpiExchange
	.dbline 157
; 	if ( len ) {  /* 有参数 */
	tst R10
	breq L25
	.dbline 157
	.dbline 158
	clr R22
	xjmp L30
L27:
	.dbline 158
	ldi R24,<_sendBuff
	ldi R25,>_sendBuff
	mov R30,R22
	clr R31
	add R30,R24
	adc R31,R25
	ldd R16,z+0
	xcall _mSpiExchange
L28:
	.dbline 158
	inc R22
L30:
	.dbline 158
; 		for ( i = 0; i != len; i ++ ) mSpiExchange( sendBuff[ i ] );  /* 依次写入参数 */
	cp R22,R10
	brne L27
	.dbline 159
; 	}
L25:
	.dbline 160
; 	PB375_CS_SET;  /* 结束SPI片选 */
	sbi 0x18,0
	xjmp L32
L31:
	.dbline 161
; 	while ( 1 ) {  /* 处理数据传输,直到操作完成才退出 */
	.dbline 163
; 
; 		PB375_CS_CLR;  /* 产生SPI片选 */
	cbi 0x18,0
	.dbline 164
; 		status = mSpiExchange( 0xFF );  /* 写入0xFF作为无效命令码(不应该写其它值),返回模块操作状态 */
	ldi R16,255
	xcall _mSpiExchange
	mov R20,R16
	.dbline 165
; 		if ( status == 0xFF ) {  /* 模块操作尚未完成,也就是INT#没有中断产生 */
	cpi R16,255
	brne L34
	.dbline 165
	.dbline 166
; 			PB375_CS_SET;  /* 结束SPI片选 */
	sbi 0x18,0
	.dbline 167
; 			mDelaymS( 1 );
	ldi R16,1
	xcall _mDelaymS
	.dbline 168
; 			continue;  /* 继续等待模块完成操作 */
	xjmp L32
L34:
	.dbline 171
; 		}
; 
; 		if ( status == ERR_SUCCESS )  /* 操作成功 */ 
	tst R20
	brne L36
	.dbline 172
; 		{  
	.dbline 173
; 			i = mSpiExchange( 0 );  /* 返回结果数据的长度,写入0没有意义,可以是任何值 */
	clr R16
	xcall _mSpiExchange
	mov R22,R16
	.dbline 174
; 			if ( i ) {  /* 有结果数据 */
	tst R16
	breq L38
	.dbline 174
	.dbline 175
; 				j = 0;
	clr R10
L40:
	.dbline 176
; 				do {  /* 使用do+while结构是因为其效率高于for */
	.dbline 177
; 					recBuff[ j ] = mSpiExchange( 0 );  /* 接收结果数据并保存到参数结构中,写入0没有意义 */
	clr R16
	xcall _mSpiExchange
	ldi R24,<_recBuff
	ldi R25,>_recBuff
	mov R30,R10
	clr R31
	add R30,R24
	adc R31,R25
	std z+0,R16
	.dbline 178
; 					j ++;
	inc R10
	.dbline 179
L41:
	.dbline 179
; 				} while ( -- i );
	mov R24,R22
	subi R24,1
	mov R22,R24
	tst R24
	brne L40
	.dbline 180
; 			}
L38:
	.dbline 181
; 			PB375_CS_SET;  /* 结束SPI片选 */
	sbi 0x18,0
	.dbline 182
; 			break;  /* 操作成功返回 */
	xjmp L33
L36:
	.dbline 185
; 		}
; 		else   /* 操作失败 */ 
; 		{  
	.dbline 186
; 			PB375_CS_SET;  /* 结束SPI片选 */
	sbi 0x18,0
	.dbline 187
	cpi R20,130
	breq L45
	cpi R20,21
	brne L33
L45:
	.dbline 187
; 			if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT ) mDelaymS( 100 );  /* U盘刚刚连接或者断开,应该延时几十毫秒再操作 */
	ldi R16,100
	xcall _mDelaymS
	.dbline 188
; 			break;  /* 操作失败返回 */
	xjmp L33
X0:
	.dbline 190
	sbi 0x18,0
	.dbline 191
L32:
	.dbline 161
	xjmp L31
L33:
	.dbline 192
; 		}
; 		PB375_CS_SET;  /* 结束SPI片选 */
; 	}
; 	return( status );
	mov R16,R20

⌨️ 快捷键说明

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