📄 main.s
字号:
.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 + -