📄 ch375ev0.s
字号:
.module CH375EV0.C
.area text(rom, con, rel)
.dbfile E:\ICC128\2008控制台\2008console0TEST\U盘扇区读写\CH375EV0.C
.dbfunc e delay2us _delay2us fV
; i -> R16
.even
_delay2us::
.dbline -1
.dbline 59
; /* 2004.03.05
; 修改记录:
; 2007.08支持大扇区, 适用于CH375B芯片, 修改了: mInitDisk, mReadSector, mWriteSector, 增加了解: mClearError
; ****************************************
; ** Copyright (C) W.ch 1999-2004 **
; ** Web: http://www.winchiphead.com **
; ****************************************
; ** USB 1.1 Host Examples for CH375 **
; ** KC7.0@MCS-51 **
; ****************************************
; */
; /* CH375作为USB主机接口的程序示例 */
;
; /* MCS-51单片机C语言的示例程序, U盘数据读写 */
;
; #include <iom128v.h>
; #include <string.h>
; #include <stdio.h>
;
; #define MAX_SECTOR_SIZE 2048 /* 以512字节每扇区为主,部分有2K字节每扇区,最大为4K字节 */
;
; /* 定义CH375命令代码及返回状态 */
; #include "CH375INC.H"
; /* CH375特性 */
; #define CH375_BLOCK_SIZE 64 /* CH375 maximum data block size */
;
; /* 以下定义适用于MCS-51单片机,其它单片机参照修改,为了提供C语言的速度需要对本程序进行优化 */
; //#include <reg51.h>
; //unsigned char volatile xdata CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */
; //unsigned char volatile xdata CH375_DAT_PORT _at_ 0xBCF0; /* CH375数据端口的I/O地址 */
; //unsigned char xdata DATA_BUFFER[ MAX_SECTOR_SIZE ] _at_ 0x0000; /* 外部RAM数据缓冲区的起始地址,长度不少于一次读写的数据长度 */
; //sbit CH375_INT_WIRE = 0xB0^2; /* P3.2, INT0, 连接CH375的INT#引脚,用于查询中断状态 */
;
; unsigned char DATA_BUFFER[ MAX_SECTOR_SIZE ];
;
; #define CH375_INT_WIRE ( PIND & 0x10 ) /* PINB.4, CH375的中断线INT#引脚,连接CH375的INT#引脚,用于查询中断状态 */
;
;
; #define TXB8 0
; #define FE 4
; #define DOR 3
; #define UPE 2
; #define RXC 7
;
; unsigned short BytePerSector; /* 每扇区字节数,扇区大小 */
; unsigned char BlockPerSector; /* 每扇区块数,指CH375读写时的块 BlockPerSector=BytePerSector/CH375_BLOCK_SIZE */
;
; /* 在P1.4连接一个LED用于监控演示程序的进度,低电平LED亮,当U盘插入后亮 */
; //sbit P1_4 = P1^4;
; //#define LED_OUT_ACT( ) { P1_4 = 0; } /* P1.4 低电平驱动LED显示 */
; //#define LED_OUT_INACT( ) { P1_4 = 1; } /* P1.4 低电平驱动LED显示 */
;
; #define P1_4 PORTG ^= 0x10;
; #define LED_OUT_ACT( ) { PORTG &= 0xEF; } /* PORTB.7 低电平驱动LED显示 */
; #define LED_OUT_INACT( ) { PORTG |= 0x10; } /* PORTB.7 低电平驱动LED显示 */
;
; /* 延时2微秒,不精确 */
; void delay2us( )
; {
.dbline 61
ldi R16,10
xjmp L5
L2:
.dbline 61
L3:
.dbline 61
dec R16
L5:
.dbline 61
; unsigned char i;
; for ( i = 10; i != 0; i -- );
tst R16
brne L2
.dbline -2
L1:
.dbline 0 ; func end
ret
.dbsym r i 16 c
.dbend
.dbfunc e delay1us _delay1us fV
; i -> R16,R17
.even
_delay1us::
.dbline -1
.dbline 66
; }
;
; /* 延时1微秒,不精确 */
; void delay1us( )
; {
.dbline 68
ldi R16,5
ldi R17,0
xjmp L10
L7:
.dbline 68
L8:
.dbline 68
subi R16,1
sbci R17,0
L10:
.dbline 68
; unsigned int i;
; for ( i = 5; i != 0; i -- );
cpi R16,0
cpc R16,R17
brne L7
X0:
.dbline -2
L6:
.dbline 0 ; func end
ret
.dbsym r i 16 i
.dbend
.dbfunc e mDelaymS _mDelaymS fV
; i -> R20,R21
; cnt -> R16
.even
_mDelaymS::
xcall push_gset1
.dbline -1
.dbline 73
; }
;
; /* 延时毫秒,不精确 */
; void mDelaymS( unsigned char cnt )
; {
xjmp L13
L12:
.dbline 75
; unsigned int i;
; while ( cnt -- ) {
.dbline 76
ldi R20,2665
ldi R21,10
xjmp L18
L15:
.dbline 76
L16:
.dbline 76
subi R20,1
sbci R21,0
L18:
.dbline 76
cpi R20,0
cpc R20,R21
brne L15
X1:
.dbline 77
L13:
.dbline 75
mov R2,R16
clr R3
subi R16,1
tst R2
brne L12
.dbline -2
L11:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r i 20 i
.dbsym r cnt 16 c
.dbend
.dbfunc e CH375_WR_CMD_PORT _CH375_WR_CMD_PORT fV
; cmd -> R20
.even
_CH375_WR_CMD_PORT::
xcall push_gset1
mov R20,R16
.dbline -1
.dbline 82
; for ( i = 2665; i != 0; i -- );
; }
; }
;
; /* 基本操作 */
;
; void CH375_WR_CMD_PORT( unsigned char cmd ) { /* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 */
.dbline 83
; delay2us();
xcall _delay2us
.dbline 85
; //CH375_CMD_PORT=cmd;
; UCSR1B |= 0X01; //将数据第9位置1,表示是地址帧
lds R24,154
ori R24,1
sts 154,R24
L20:
.dbline 86
L21:
.dbline 86
; while(!(UCSR1A&0x20));
lds R2,155
sbrs R2,5
rjmp L20
.dbline 87
; UDR1=cmd; //写命令
sts 156,R20
.dbline 88
; mDelaymS( 30 ); /* 延时100毫秒 */
ldi R16,30
xcall _mDelaymS
.dbline 89
; delay2us();
xcall _delay2us
.dbline -2
L19:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r cmd 20 c
.dbend
.dbfunc e CH375_WR_DAT_PORT _CH375_WR_DAT_PORT fV
; dat -> R20
.even
_CH375_WR_DAT_PORT::
xcall push_gset1
mov R20,R16
.dbline -1
.dbline 92
; }
;
; void CH375_WR_DAT_PORT( unsigned char dat ) { /* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 */
.dbline 94
; //CH375_DAT_PORT=dat;
; UCSR1B &= 0XFE;
lds R24,154
andi R24,254
sts 154,R24
L24:
.dbline 95
L25:
.dbline 95
; while(!(UCSR1A&0x20));
lds R2,155
sbrs R2,5
rjmp L24
.dbline 96
; UDR1= dat;
sts 156,R20
.dbline 97
; mDelaymS( 30 ); /* 延时100毫秒 */
ldi R16,30
xcall _mDelaymS
.dbline 98
; delay1us(); /* 因为MCS51单片机较慢所以实际上无需延时 */
xcall _delay1us
.dbline -2
L23:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r dat 20 c
.dbend
.dbfunc e CH375_RD_DAT_PORT _CH375_RD_DAT_PORT fc
; status -> R20
; resl -> R20
; resh -> R22
.even
_CH375_RD_DAT_PORT::
xcall push_gset2
.dbline -1
.dbline 102
; }
;
; unsigned char CH375_RD_DAT_PORT()
; { /* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
.dbline 105
; unsigned char status, resh;
; unsigned char resl;
; delay1us(); /* 因为MCS51单片机较慢所以实际上无需延时 */
xcall _delay1us
.dbline 108
; //while ( !(UCSR1A & (1<<RXC)) ) // 等待接收数据
; //while ( !(UCSR1A & 0x80) ) // 等待接收数据
; status = UCSR1A;// 从缓冲器中获得状态、第9 位及数据
lds R20,155
.dbline 109
; resh = UCSR1B;
lds R22,154
.dbline 110
; resl = UDR1;
lds R20,156
.dbline 115
;
; //if ( status & (1<<FE)|(1<<DOR)|(1<<UPE) ) //如果出错,返回 -1
; //return -1;
; /* 过滤第9 位数据,然后返回*/
; resh = (resh >> 1) & 0x01;
lsr R22
andi R22,1
.dbline 116
; return ((resh << 8) | resl);
mov R17,R22
mov R16,R20
xjmp L27
X2:
.dbline 117
; mDelaymS( 6 ); /* 延时100毫秒 */
ldi R16,6
xcall _mDelaymS
.dbline -2
L27:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r status 20 c
.dbsym r resl 20 c
.dbsym r resh 22 c
.dbend
.dbfunc e mWaitInterrupt _mWaitInterrupt fc
.even
_mWaitInterrupt::
.dbline -1
.dbline 123
; //return( CH375_DAT_PORT );
; }
;
; /* 等待CH375中断并获取状态 */
; unsigned char mWaitInterrupt()
; { /* 主机端等待操作完成, 返回操作状态 */
xjmp L30
L29:
.dbline 125
.dbline 126
.dbline 126
lds R24,101
andi R24,239
sts 101,R24
.dbline 126
.dbline 126
.dbline 127
ldi R16,80
xcall _mDelaymS
.dbline 128
.dbline 128
lds R24,101
ori R24,16
sts 101,R24
.dbline 128
.dbline 128
.dbline 129
ldi R16,80
xcall _mDelaymS
.dbline 130
L30:
.dbline 124
; while( CH375_INT_WIRE ) /* 查询等待CH375操作完成中断(INT#低电平) */
sbic 0x10,4
rjmp L29
.dbline 131
; {
; LED_OUT_ACT( ); /* LED闪烁 */
; mDelaymS( 80 );
; LED_OUT_INACT( );
; mDelaymS( 80 );
; }
; CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */
ldi R16,34
xcall _CH375_WR_CMD_PORT
.dbline 132
; return( CH375_RD_DAT_PORT( ) );
xcall _CH375_RD_DAT_PORT
.dbline -2
L28:
.dbline 0 ; func end
ret
.dbend
.dbfunc e mCH375Init _mCH375Init fc
; i -> R20
.even
_mCH375Init::
xcall push_gset1
sbiw R28,2
.dbline -1
.dbline 140
; /* c = CH375_RD_DAT_PORT( ); 返回中断状态 */
; /* if ( c == USB_INT_DISCONNECT ) ?; 检测到USB设备断开事件 */
; /* else if ( c == USB_INT_CONNECT ) ?; 检测到USB设备连接事件 */
; }
;
; /* 设置CH375为USB主机方式 */
; unsigned char mCH375Init( )
; {
.dbline 163
; unsigned char i;
; #ifdef TEST_CH375_PORT
; unsigned char c;
; CH375_WR_CMD_PORT( CMD_CHECK_EXIST ); /* 测试工作状态 */
; CH375_WR_DAT_PORT( 0x55 ); /* 测试数据 */
; c = CH375_RD_DAT_PORT( ); /* 返回数据应该是测试数据取反 */
; if ( c != 0xaa ) { /* CH375出错 */
; for ( i = 100; i != 0; i -- ) { /* 强制数据同步 */
; CH375_WR_CMD_PORT( CMD_RESET_ALL ); /* CH375执行硬件复位 */
; c = CH375_RD_DAT_PORT( ); /* 延时 */
; ShowText(10,21,"初始化错误!");
; while ( 1 )
; {
; LED_OUT_ACT( ); //LED闪烁
; mDelaymS( 80 );
; LED_OUT_INACT( );
; mDelaymS( 80 );
; }
; }
; mDelaymS( 50 ); /* 延时至少30mS */
; }
; #endif
; CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); /* 设置USB工作模式 */
ldi R16,21
xcall _CH375_WR_CMD_PORT
.dbline 164
; CH375_WR_DAT_PORT( 6 ); /* 模式代码,自动检测USB设备连接 */
ldi R16,6
xcall _CH375_WR_DAT_PORT
.dbline 165
; for ( i = 0xff; i != 0; i -- ) /* 等待操作成功,通常需要等待10uS-20uS */
ldi R20,255
xjmp L36
L33:
.dbline 166
; if ( CH375_RD_DAT_PORT( ) == CMD_RET_SUCCESS ) break; /* 操作成功 */
xcall _CH375_RD_DAT_PORT
cpi R16,81
brne L37
.dbline 166
xjmp L35
L37:
L34:
.dbline 165
dec R20
L36:
.dbline 165
tst R20
brne L33
L35:
.dbline 167
; if ( i != 0 )
tst R20
breq L39
.dbline 168
; { return( 0 ); } /* 操作成功 */
.dbline 168
clr R16
xjmp L32
L39:
.dbline 170
; else
; {
.dbline 171
; ShowText(10,21,"CH375出错!");
ldi R24,<L41
ldi R25,>L41
std y+1,R25
std y+0,R24
ldi R18,21
ldi R19,0
ldi R16,10
ldi R17,0
xcall _ShowText
xjmp L43
L42:
.dbline 173
.dbline 174
.dbline 174
lds R24,101
andi R24,239
sts 101,R24
.dbline 174
.dbline 174
.dbline 175
ldi R16,80
xcall _mDelaymS
.dbline 176
.dbline 176
lds R24,101
ori R24,16
sts 101,R24
.dbline 176
.dbline 176
.dbline 177
ldi R16,80
xcall _mDelaymS
.dbline 178
L43:
.dbline 172
; while ( 1 )
xjmp L42
X3:
.dbline 179
; {
; LED_OUT_ACT( ); //LED闪烁
; mDelaymS( 80 );
; LED_OUT_INACT( );
; mDelaymS( 80 );
; }
; return( 0xff );
ldi R16,255
.dbline -2
L32:
adiw R28,2
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r i 20 c
.dbend
.dbfunc e mInitDisk _mInitDisk fc
; mIntStatus -> R20
; i -> R20
.even
_mInitDisk::
xcall push_gset1
sbiw R28,2
.dbline -1
.dbline 185
; } /* CH375出错,例如芯片型号错或者处于串口方式或者不支持 */
; }
;
; /* 初始化磁盘 */
; unsigned char mInitDisk( )
; {
.dbline 187
; unsigned char mIntStatus, i;
; CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */
ldi R16,34
xcall _CH375_WR_CMD_PORT
.dbline 188
; mIntStatus = CH375_RD_DAT_PORT( ); //获取中断状态
xcall _CH375_RD_DAT_PORT
mov R20,R16
.dbline 189
; if ( mIntStatus == USB_INT_DISCONNECT ) return( mIntStatus ); /* USB设备断开 */
cpi R16,22
brne L46
.dbline 189
xjmp L45
L46:
.dbline 190
; CH375_WR_CMD_PORT( CMD_DISK_INIT ); /* 初始化USB存储器 */
ldi R16,81
xcall _CH375_WR_CMD_PORT
.dbline 191
; mIntStatus = mWaitInterrupt( ); /* 等待中断并获取状态 */
xcall _mWaitInterrupt
mov R20,R16
.dbline 192
; if ( mIntStatus != USB_INT_SUCCESS ) return( mIntStatus ); /* 出现错误 */
cpi R16,20
breq L48
.dbline 192
xjmp L45
L48:
.dbline 193
; CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* 获取USB存储器的容量 */
ldi R16,83
xcall _CH375_WR_CMD_PORT
.dbline 194
; mIntStatus = mWaitInterrupt( ); /* 等待中断并获取状态 */
xcall _mWaitInterrupt
mov R20,R16
.dbline 195
; if ( mIntStatus != USB_INT_SUCCESS )
cpi R16,20
breq L50
.dbline 196
; { /* 出错重试 */
.dbline 197
; mDelaymS( 200 );
ldi R16,200
xcall _mDelaymS
.dbline 198
; CH375_WR_CMD_PORT( CMD_DISK_SIZE ); /* 获取USB存储器的容量 */
ldi R16,83
xcall _CH375_WR_CMD_PORT
.dbline 199
; mIntStatus = mWaitInterrupt( ); /* 等待中断并获取状态 */
xcall _mWaitInterrupt
mov R20,R16
.dbline 200
; }
L50:
.dbline 201
; if ( mIntStatus != USB_INT_SUCCESS ) return( mIntStatus ); /* 出现错误 */
cpi R20,20
breq L52
.dbline 201
mov R16,R20
xjmp L45
L52:
.dbline 204
;
; /* 可以由CMD_RD_USB_DATA命令将容量数据读出,分析每扇区字节数 */
; CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 从CH375缓冲区读取数据块 */
ldi R16,40
xcall _CH375_WR_CMD_PORT
.dbline 205
; i = CH375_RD_DAT_PORT( ); /* 后续数据的长度 */
xcall _CH375_RD_DAT_PORT
mov R20,R16
.dbline 206
; if ( i != 8 ) return( USB_INT_DISK_ERR ); /* 异常 */
cpi R16,8
breq L54
.dbline 206
ldi R16,31
xjmp L45
L54:
.dbline 207
; for ( i = 0; i != 8; i ++ )
clr R20
xjmp L59
L56:
.dbline 208
.dbline 209
xcall _CH375_RD_DAT_PORT
ldi R24,<_DATA_BUFFER
ldi R25,>_DATA_BUFFER
mov R30,R20
clr R31
add R30,R24
adc R31,R25
std z+0,R16
.dbline 210
L57:
.dbline 207
inc R20
L59:
.dbline 207
cpi R20,8
brne L56
.dbline 211
; { /* 根据长度读取数据 */
; DATA_BUFFER[ i ] = CH375_RD_DAT_PORT( ); /* 读出数据并保存 */
; }
; i = DATA_BUFFER[ 6 ]; /* U盘容量数据中的每扇区字节数,大端格式 */
lds R20,_DATA_BUFFER+6
.dbline 213
;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -