📄 avrmain.lst
字号:
__start:
__text_start:
004F E5CF LDI R28,0x5F
0050 E0D4 LDI R29,4
0051 BFCD OUT 0x3D,R28
0052 BFDE OUT 0x3E,R29
0053 51C0 SUBI R28,0x10
0054 40D0 SBCI R29,0
0055 EA0A LDI R16,0xAA
0056 8308 STD Y+0,R16
0057 2400 CLR R0
0058 EAEA LDI R30,0xAA
0059 E0F0 LDI R31,0
005A E011 LDI R17,1
005B 3AEA CPI R30,0xAA
005C 07F1 CPC R31,R17
005D F011 BEQ 0x0060
005E 9201 ST R0,Z+
005F CFFB RJMP 0x005B
0060 8300 STD Z+0,R16
0061 E5E4 LDI R30,0x54
0062 E0F0 LDI R31,0
0063 E6A0 LDI R26,0x60
0064 E0B0 LDI R27,0
0065 E010 LDI R17,0
0066 39EE CPI R30,0x9E
0067 07F1 CPC R31,R17
0068 F021 BEQ 0x006D
0069 95C8 LPM
006A 9631 ADIW R30,1
006B 920D ST R0,X+
006C CFF9 RJMP 0x0066
006D 940E0106 CALL _main
_exit:
006F CFFF RJMP _exit
FILE: E:\电子项目\北极熊模块\例程\AVR\main.c
(0001) /*
(0002) name:main.c
(0003) writer:xiaowu
(0004) date:2009/1/6
(0005) ****************************************
(0006) ** Copyright (C) fifth 2008-2009 **
(0007) ** Web: http://www.chinamcu.com **
(0008) ****************************************
(0009) ** USB Host File Module @PB375 **
(0010) ** AVR ATMega32 **
(0011) ** 深圳第五元素科技有限公司 **
(0012) ** 联系方式:0755-29739852
(0013) ** 技术email:xiaowuyeah@163.com **
(0014) discription:
(0015)
(0016) U盘文件读写模块, 连接方式: 软件模拟SPI时序+查询
(0017) AVR单片机C语言示例程序
(0018)
(0019) 以字节为单位进行U盘文件读写,单片机的RAM只需要几十个字节,不需要外部RAM
(0020) *********************************************
(0021) */
(0022)
(0023)
(0024) #include <iom16v.h>
(0025) #include <macros.h>
(0026)
(0027)
(0028) #define PB375_VER 0x30 /* 当前模块版本 */
(0029)
(0030) /* ********************************************************************************************************************* */
(0031) /* 返回的操作状态码 */
(0032) /* 以下是事件通知状态码,检测到当前U盘已经连接或者已经断开,可以作为最终状态码 */
(0033) #define ERR_USB_CONNECT 0x15 /* 检测到USB设备连接事件,磁盘已经连接 */
(0034) #define ERR_DISK_DISCON 0x82 /* 检测到USB设备连接事件,磁盘已经断开,或者磁盘尚未连接 */
(0035) /* 代码0XH用于USB设备方式的操作状态代码,由PB375返回,是USB设备模式的中断状态 */
(0036) #define ERR_USB_DAT_DOWN 0x02 /* USB设备模式: 数据下传成功,上位机下传的数据已经在模块中 */
(0037) #define ERR_USB_DAT_UP 0x0A /* USB设备模式: 数据上传成功,模块中的上传数据已经被上位机取走 */
(0038)
(0039)
(0040) /* 最终状态码 */
(0041) #define ERR_SUCCESS 0x00 /* 操作成功 */
(0042) #define ERR_PB375_ERROR 0x81 /* PB375硬件错误,可能需要复位PB375 */
(0043) #define ERR_STATUS_ERR 0x83 /* 磁盘状态错误,可能正在连接或者断开磁盘 */
(0044) #define ERR_MBR_ERROR 0x91 /* 磁盘的主引导记录无效,可能磁盘尚未分区或者尚未格式化 */
(0045) #define ERR_TYPE_ERROR 0x92 /* 磁盘分区类型不支持,只支持FAT12/FAT16/BigDOS/FAT32,需要由磁盘管理工具重新分区 */
(0046) #define ERR_BPB_ERROR 0xA1 /* 磁盘尚未格式化,或者参数错误,需要由WINDOWS采用默认参数重新格式化 */
(0047) #define ERR_TOO_LARGE 0xA2 /* 磁盘非正常格式化并且容量大于4GB,或者容量大于250GB,需要由WINDOWS采用默认参数重新格式化 */
(0048) #define ERR_FAT_ERROR 0xA3 /* 磁盘的文件系统不支持,只支持FAT12/FAT16/FAT32,需要由WINDOWS采用默认参数重新格式化 */
(0049) #define ERR_DISK_FULL 0xB1 /* 磁盘文件太满,剩余空间太少或者已经没有,需要磁盘整理 */
(0050) #define ERR_FDT_OVER 0xB2 /* 目录内文件太多,没有空闲的目录项,FAT12/FAT16根目录下的文件数应该少于500个,需要磁盘整理 */
(0051) #define ERR_MISS_DIR 0xB3 /* 指定路径的某个子目录没有找到,可能是目录名称错误 */
(0052) #define ERR_FILE_CLOSE 0xB4 /* 文件已经关闭,如果需要使用,应该重新打开文件 */
(0053) #define ERR_OPEN_DIR 0x41 /* 指定路径的目录被打开 */
(0054) #define ERR_MISS_FILE 0x42 /* 指定路径的文件没有找到,可能是文件名称错误 */
(0055) #define ERR_FOUND_NAME 0x43 /* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中,如果需要使用,应该打开该文件 */
(0056) #define ERR_USB_DISK_ERR 0x1F /* USB存储器操作失败,在初始化时可能是USB存储器不支持,在读写操作中可能是磁盘损坏或者已经断开 */
(0057) /* 其余错误代码未定义,可以发出命令CMD_QueryStatus查询模块状态并分析 */
(0058)
(0059) /* ********************************************************************************************************************* */
(0060) /* 磁盘及文件状态,适用于CMD_PARAM.Status.mDiskStatus */
(0061) #define DISK_UNKNOWN 0x00 /* 尚未初始化,未知状态 */
(0062) #define DISK_DISCONNECT 0x01 /* 磁盘没有连接或者已经断开 */
(0063) #define DISK_CONNECT 0x02 /* 磁盘已经连接,但是尚未初始化或者无法识别该磁盘 */
(0064) #define DISK_MOUNTED 0x03 /* 磁盘已经初始化成功,但是尚未分析文件系统或者文件系统不支持 */
(0065) #define DISK_READY 0x10 /* 已经分析磁盘的文件系统并且能够支持 */
(0066) #define DISK_OPEN_ROOT 0x12 /* 已经打开根目录,扇区模式,只能以扇区为单位读写目录的内容,使用后必须关闭,注意FAT12/FAT16根目录是固定长度 */
(0067) #define DISK_OPEN_DIR 0x13 /* 已经打开子目录,扇区模式,只能以扇区为单位读写目录的内容 */
(0068) #define DISK_OPEN_FILE 0x14 /* 已经打开文件,扇区模式,可以以扇区为单位进行数据读写 */
(0069) #define DISK_OPEN_FILE_B 0x15 /* 已经打开文件,字节模式,可以以字节为单位进行数据读写 */
(0070)
(0071)
(0072) /* 外部命令码 */
(0073) #define CMD_DiskQuery 0x61 /* 查询磁盘信息 */
(0074) #define CMD_FileOpen 0x64 /* 打开文件 */
(0075) #define CMD_FileCreate 0x65 /* 新建文件并打开,如果文件已经存在则先删除后再新建 */
(0076) #define CMD_FileErase 0x66 /* 删除文件并关闭 */
(0077) #define CMD_FileClose 0x67 /* 关闭当前文件 */
(0078) #define CMD_ByteLocate 0x7A /* 以字节为单位移动当前文件指针 */
(0079) #define CMD_ByteRead 0x7B /* 以字节为单位从当前文件读取数据块 */
(0080) #define CMD_ByteWrite 0x7C /* 以字节为单位向当前文件写入数据块 */
(0081) #define CMD_DiskReady 0x71 /* 查询磁盘是否准备好 */
(0082)
(0083)
(0084) /*
(0085) CS------PB0
(0086) SCK-----PB1
(0087) SDI-----PB2
(0088) SDO-----PB3
(0089) */
(0090)
(0091) #define PB375_CS_SET PORTB |= (1<<PB0)
(0092) #define PB375_CS_CLR PORTB &= ~(1<<PB0)
(0093) #define PB375_SCK_SET PORTB |= (1<<PB1)
(0094) #define PB375_SCK_CLR PORTB &= ~(1<<PB1)
(0095) #define PB375_SDI_SET PORTB |= (1<<PB2)
(0096) #define PB375_SDI_CLR PORTB &= ~(1<<PB2)
(0097) #define PB375_SDO (PINB &(1<<PB3))
(0098)
(0099) #define MAXBUFLEN 128
(0100)
(0101) //发送缓冲区
(0102) unsigned char sendBuff[MAXBUFLEN];
(0103) //接收缓冲区
(0104) unsigned char recBuff[MAXBUFLEN];
(0105)
(0106)
(0107)
(0108) //初始化IO口 设置CS SCK SDI 为输出 SDO为输入
(0109) void initPort()
(0110) {
(0111) PORTB |= 0x07;
_initPort:
0070 B388 IN R24,0x18
0071 6087 ORI R24,7
0072 BB88 OUT 0x18,R24
(0112) DDRB |= 0x07;
0073 B387 IN R24,0x17
0074 6087 ORI R24,7
0075 BB87 OUT 0x17,R24
(0113) DDRB &= 0xF7;
0076 B387 IN R24,0x17
0077 7F87 ANDI R24,0xF7
0078 BB87 OUT 0x17,R24
0079 9508 RET
_mDelaymS:
i --> R20
c --> R10
j --> R22
delay --> R16
007A 940E01CF CALL push_gset3
(0114) }
(0115)
(0116)
(0117) /* 以毫秒为单位延时,适用于24MHz时钟 */
(0118) void mDelaymS( unsigned char delay )
(0119) {
(0120) unsigned char i, j, c;
(0121) for ( i = delay; i != 0; i -- ) {
007C 2F40 MOV R20,R16
007D C011 RJMP 0x008F
(0122) for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz时钟下延时500uS */
007E EC68 LDI R22,0xC8
007F C004 RJMP 0x0084
0080 2D8A MOV R24,R10
0081 5F8D SUBI R24,0xFD
0082 2EA8 MOV R10,R24
0083 956A DEC R22
0084 2366 TST R22
0085 F7D1 BNE 0x0080
(0123) for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz时钟下延时500uS */
0086 EC68 LDI R22,0xC8
0087 C004 RJMP 0x008C
0088 2D8A MOV R24,R10
0089 5F8D SUBI R24,0xFD
008A 2EA8 MOV R10,R24
008B 956A DEC R22
008C 2366 TST R22
008D F7D1 BNE 0x0088
008E 954A DEC R20
008F 2344 TST R20
0090 F769 BNE 0x007E
0091 940E01C8 CALL pop_gset3
0093 9508 RET
_mSpiExchange:
d --> R20
i --> R22
c --> R16
0094 940E01D1 CALL push_gset2
(0124) }
(0125) }
(0126)
(0127) /* 发送一个字节数据给PB375模块,同时接收一个字节,以SPI模式0方式(SPI_SCK默认为0) */
(0128) unsigned char mSpiExchange( unsigned char c )
(0129) {
(0130) unsigned char i, d;
(0131) d = 0;
0096 2744 CLR R20
(0132) PB375_SCK_CLR;
0097 98C1 CBI 0x18,1
(0133) for ( i = 8; i != 0; i -- ) { /* 8个位 */
0098 E068 LDI R22,0x8
0099 C00D RJMP 0x00A7
(0134) if ( c & 0x80 )
009A FF07 SBRS R16,7
009B C002 RJMP 0x009E
(0135) PB375_SDI_SET; /* 向模块的SDI输入引脚输出数据 */
009C 9AC2 SBI 0x18,2
009D C001 RJMP 0x009F
(0136) else
(0137) PB375_SDI_CLR;
009E 98C2 CBI 0x18,2
(0138) d <<= 1;
009F 0F44 LSL R20
(0139) if ( PB375_SDO )
00A0 9BB3 SBIS 0x16,3
00A1 C001 RJMP 0x00A3
(0140) d++; /* 如果模块的SDO输出引脚为高电平则输入位1 PB375_SDO */
00A2 9543 INC R20
(0141) PB375_SCK_SET; /* SPI时钟上升沿,模块接收数据并输出数据 */
00A3 9AC1 SBI 0x18,1
(0142) c <<= 1;
00A4 0F00 LSL R16
(0143) PB375_SCK_CLR;
00A5 98C1 CBI 0x18,1
00A6 956A DEC R22
00A7 2366 TST R22
00A8 F789 BNE 0x009A
(0144) }
(0145) return( d );
00A9 2F04 MOV R16,R20
00AA 940E01C5 CALL pop_gset2
00AC 9508 RET
_ExecCommand:
status --> R20
i --> R22
j --> R10
len --> R10
cmd --> R20
00AD 940E01CF CALL push_gset3
00AF 2EA2 MOV R10,R18
00B0 2F40 MOV R20,R16
(0146) }
(0147)
(0148)
(0149)
(0150) /* 执行命令 */
(0151) unsigned char ExecCommand( unsigned char cmd, unsigned char len )
(0152) {
(0153) unsigned char i, j, status;
(0154) PB375_CS_CLR; /* 产生SPI片选 */
00B1 98C0 CBI 0x18,0
(0155) mSpiExchange( cmd ); /* 写入命令码 */
00B2 2F04 MOV R16,R20
00B3 DFE0 RCALL _mSpiExchange
(0156) mSpiExchange( len ); /* 写入后续参数的长度 */
00B4 2D0A MOV R16,R10
00B5 DFDE RCALL _mSpiExchange
(0157) if ( len ) { /* 有参数 */
00B6 20AA TST R10
00B7 F069 BEQ 0x00C5
(0158) for ( i = 0; i != len; i ++ ) mSpiExchange( sendBuff[ i ] ); /* 依次写入参数 */
00B8 2766 CLR R22
00B9 C009 RJMP 0x00C3
00BA E28A LDI R24,0x2A
00BB E091 LDI R25,1
00BC 2FE6 MOV R30,R22
00BD 27FF CLR R31
00BE 0FE8 ADD R30,R24
00BF 1FF9 ADC R31,R25
00C0 8100 LDD R16,Z+0
00C1 DFD2 RCALL _mSpiExchange
00C2 9563 INC R22
00C3 156A CP R22,R10
00C4 F7A9 BNE 0x00BA
(0159) }
(0160) PB375_CS_SET; /* 结束SPI片选 */
00C5 9AC0 SBI 0x18,0
00C6 C02C RJMP 0x00F3
(0161) while ( 1 ) { /* 处理数据传输,直到操作完成才退出 */
(0162)
(0163) PB375_CS_CLR; /* 产生SPI片选 */
00C7 98C0 CBI 0x18,0
(0164) status = mSpiExchange( 0xFF ); /* 写入0xFF作为无效命令码(不应该写其它值),返回模块操作状态 */
00C8 EF0F LDI R16,0xFF
00C9 DFCA RCALL _mSpiExchange
00CA 2F40 MOV R20,R16
(0165) if ( status == 0xFF ) { /* 模块操作尚未完成,也就是INT#没有中断产生 */
00CB 3F0F CPI R16,0xFF
00CC F421 BNE 0x00D1
(0166) PB375_CS_SET; /* 结束SPI片选 */
00CD 9AC0 SBI 0x18,0
(0167) mDelaymS( 1 );
00CE E001 LDI R16,1
00CF DFAA RCALL _mDelaymS
(0168) continue; /* 继续等待模块完成操作 */
00D0 C022 RJMP 0x00F3
(0169) }
(0170)
(0171) if ( status == ERR_SUCCESS ) /* 操作成功 */
00D1 2344 TST R20
00D2 F4B9 BNE 0x00EA
(0172) {
(0173) i = mSpiExchange( 0 ); /* 返回结果数据的长度,写入0没有意义,可以是任何值 */
00D3 2700 CLR R16
00D4 DFBF RCALL _mSpiExchange
00D5 2F60 MOV R22,R16
(0174) if ( i ) { /* 有结果数据 */
00D6 2300 TST R16
00D7 F081 BEQ 0x00E8
(0175) j = 0;
00D8 24AA CLR R10
(0176) do { /* 使用do+while结构是因为其效率高于for */
(0177) recBuff[ j ] = mSpiExchange( 0 ); /* 接收结果数据并保存到参数结构中,写入0没有意义 */
00D9 2700 CLR R16
00DA DFB9 RCALL _mSpiExchange
00DB EA8A LDI R24,0xAA
00DC E090 LDI R25,0
00DD 2DEA MOV R30,R10
00DE 27FF CLR R31
00DF 0FE8 ADD R30,R24
00E0 1FF9 ADC R31,R25
00E1 8300 STD Z+0,R16
(0178) j ++;
00E2 94A3 INC R10
(0179) } while ( -- i );
00E3 2F86 MOV R24,R22
00E4 5081 SUBI R24,1
00E5 2F68 MOV R22,R24
00E6 2388 TST R24
00E7 F789 BNE 0x00D9
(0180) }
(0181) PB375_CS_SET; /* 结束SPI片选 */
00E8 9AC0 SBI 0x18,0
(0182) break; /* 操作成功返回 */
00E9 C00A RJMP 0x00F4
(0183) }
(0184) else /* 操作失败 */
(0185) {
(0186) PB375_CS_SET; /* 结束SPI片选 */
00EA 9AC0 SBI 0x18,0
(0187) if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT ) mDelaymS( 100 ); /* U盘刚刚连接或者断开,应该延时几十毫秒再操作 */
00EB 3842 CPI R20,0x82
00EC F011 BEQ 0x00EF
00ED 3145 CPI R20,0x15
00EE F429 BNE 0x00F4
00EF E604 LDI R16,0x64
00F0 DF89 RCALL _mDelaymS
(0188) break; /* 操作失败返回 */
00F1 C002 RJMP 0x00F4
(0189) }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -