📄 ch375prt.lst
字号:
C51 COMPILER V7.07 CH375PRT 11/03/2004 19:15:32 PAGE 1
C51 COMPILER V7.07, COMPILATION OF MODULE CH375PRT
OBJECT MODULE PLACED IN CH375PRT.OBJ
COMPILER INVOKED BY: d:\Keil\C51\BIN\C51.EXE CH375PRT.C BROWSE DEBUG OBJECTEXTEND
stmt level source
1 /* 2004.03.05, 2004.8.18
2 ****************************************
3 ** Copyright (C) W.ch 1999-2004 **
4 ** Web: http://www.winchiphead.com **
5 ****************************************
6 ** USB 1.1 Host Examples for CH375 **
7 ** KC7.0@MCS-51 **
8 ****************************************
9 */
10 /* 单片机通过CH375控制USB打印机 */
11 /* 程序示例,C语言,CH375中断为查询方式,只负责数据传输,不涉及打印格式及打印描述语言 */
12
13 /* 以下定义适用于MCS-51单片机,其它单片机参照修改,为了提供C语言的速度需要对本程序进行优化 */
14 #include <reg51.h>
15 unsigned char volatile xdata CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */
16 unsigned char volatile xdata CH375_DAT_PORT _at_ 0xBCF0; /* CH375数据端口的I/O地址 */
17 sbit CH375_INT_WIRE = 0xB0^2; /* P3.2, INT0, 连接CH375的INT#引脚,用于查询中断状态 */
18 typedef unsigned char BOOL1; /* typedef bit BOOL1; */
19
20 /* 以下为通用的单片机C程序 */
21 #include <string.h>
22 #include <stdio.h>
23
24 /* 定义CH375命令代码及返回状态 */
25 #include "CH375INC.H"
26
27 typedef unsigned char UCHAR;
28 typedef unsigned short USHORT;
29
30 typedef struct _USB_DEVICE_DESCRIPTOR {
31 UCHAR bLength;
32 UCHAR bDescriptorType;
33 USHORT bcdUSB;
34 UCHAR bDeviceClass;
35 UCHAR bDeviceSubClass;
36 UCHAR bDeviceProtocol;
37 UCHAR bMaxPacketSize0;
38 USHORT idVendor;
39 USHORT idProduct;
40 USHORT bcdDevice;
41 UCHAR iManufacturer;
42 UCHAR iProduct;
43 UCHAR iSerialNumber;
44 UCHAR bNumConfigurations;
45 } USB_DEV_DESCR, *PUSB_DEV_DESCR;
46
47 typedef struct _USB_CONFIG_DESCRIPTOR {
48 UCHAR bLength;
49 UCHAR bDescriptorType;
50 USHORT wTotalLength;
51 UCHAR bNumInterfaces;
52 UCHAR bConfigurationValue;
53 UCHAR iConfiguration;
54 UCHAR bmAttributes;
55 UCHAR MaxPower;
C51 COMPILER V7.07 CH375PRT 11/03/2004 19:15:32 PAGE 2
56 } USB_CFG_DESCR, *PUSB_CFG_DESCR;
57
58 typedef struct _USB_INTERF_DESCRIPTOR {
59 UCHAR bLength;
60 UCHAR bDescriptorType;
61 UCHAR bInterfaceNumber;
62 UCHAR bAlternateSetting;
63 UCHAR bNumEndpoints;
64 UCHAR bInterfaceClass;
65 UCHAR bInterfaceSubClass;
66 UCHAR bInterfaceProtocol;
67 UCHAR iInterface;
68 } USB_ITF_DESCR, *PUSB_ITF_DESCR;
69
70 typedef struct _USB_ENDPOINT_DESCRIPTOR {
71 UCHAR bLength;
72 UCHAR bDescriptorType;
73 UCHAR bEndpointAddress;
74 UCHAR bmAttributes;
75 USHORT wMaxPacketSize;
76 UCHAR bInterval;
77 } USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
78
79 typedef struct _USB_CONFIG_DESCRIPTOR_LONG {
80 USB_CFG_DESCR cfg_descr;
81 USB_ITF_DESCR itf_descr;
82 USB_ENDP_DESCR endp_descr[4];
83 } USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
84
85 unsigned char buffer[64]; /* 公用缓冲区 */
86
87 /* 延时2微秒,不精确 */
88 void delay2us( )
89 {
90 1 unsigned char i;
91 1 for ( i = 2; i != 0; i -- );
92 1 }
93
94 /* 延时1微秒,不精确 */
95 void delay1us( )
96 {
97 1 unsigned char i;
98 1 for ( i = 1; i != 0; i -- );
99 1 }
100
101 /* 延时100毫秒,不精确 */
102 void delay100ms( )
103 {
104 1 unsigned char i, j, c;
105 1 for ( i = 200; i != 0; i -- ) for ( j = 200; j != 0; j -- ) c+=3;
106 1 }
107
108 /* 基本操作 */
109
110 void CH375_WR_CMD_PORT( unsigned char cmd ) { /* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则
-延时 */
111 1 delay2us();
112 1 CH375_CMD_PORT=cmd;
113 1 delay2us();
114 1 }
115
116 void CH375_WR_DAT_PORT( unsigned char dat ) { /* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快
C51 COMPILER V7.07 CH375PRT 11/03/2004 19:15:32 PAGE 3
-则延时 */
117 1 CH375_DAT_PORT=dat;
118 1 delay1us(); /* 因为MCS51单片机较慢所以实际上无需延时 */
119 1 }
120
121 unsigned char CH375_RD_DAT_PORT() { /* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
122 1 delay1us(); /* 因为MCS51单片机较慢所以实际上无需延时 */
123 1 return( CH375_DAT_PORT );
124 1 }
125
126 unsigned char wait_interrupt() { /* 主机端等待操作完成, 返回操作状态 */
127 1 while( CH375_INT_WIRE ); /* 查询等待CH375操作完成中断(INT#低电平) */
128 1 CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */
129 1 return( CH375_RD_DAT_PORT() );
130 1 }
131
132 #define TRUE 1
133 #define FALSE 0
134 unsigned char set_usb_mode( unsigned char mode ) { /* 设置CH375的工作模式 */
135 1 unsigned char i;
136 1 CH375_WR_CMD_PORT( CMD_SET_USB_MODE );
137 1 CH375_WR_DAT_PORT( mode );
138 1 for( i=0; i!=100; i++ ) { /* 等待设置模式操作完成,不超过30uS */
139 2 if ( CH375_RD_DAT_PORT()==CMD_RET_SUCCESS ) return( TRUE ); /* 成功 */
140 2 }
141 1 return( FALSE ); /* CH375出错,例如芯片型号错或者处于串口方式或者不支持 */
142 1 }
143
144 /* 数据同步 */
145 /* USB的数据同步通过切换DATA0和DATA1实现: 在设备端, USB打印机可以自动切换;
146 在主机端, 必须由SET_ENDP6和SET_ENDP7命令控制CH375切换DATA0与DATA1.
147 主机端的程序处理方法是为设备端的各个端点分别提供一个全局变量,
148 初始值均为DATA0, 每执行一次成功事务后取反, 每执行一次失败事务后将其复位为DATA1 */
149
150 void toggle_recv( BOOL1 tog ) { /* 主机接收同步控制:0=DATA0,1=DATA1 */
151 1 CH375_WR_CMD_PORT( CMD_SET_ENDP6 );
152 1 CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 );
153 1 delay2us();
154 1 }
155
156 void toggle_send( BOOL1 tog ) { /* 主机发送同步控制:0=DATA0,1=DATA1 */
157 1 CH375_WR_CMD_PORT( CMD_SET_ENDP7 );
158 1 CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 );
159 1 delay2us();
160 1 }
161
162 unsigned char clr_stall( unsigned char endp_addr ) { /* USB通讯失败后,复位设备端的指定端点到DATA0 */
163 1 CH375_WR_CMD_PORT( CMD_CLR_STALL );
164 1 CH375_WR_DAT_PORT( endp_addr );
165 1 return( wait_interrupt() );
166 1 }
167
168 /* 数据读写, 单片机读写CH375芯片中的数据缓冲区 */
169
170 unsigned char rd_usb_data( unsigned char *buf ) { /* 从CH37X读出数据块 */
171 1 unsigned char i, len;
172 1 CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 从CH375的端点缓冲区读取接收到的数据 */
173 1 len=CH375_RD_DAT_PORT(); /* 后续数据长度 */
174 1 for ( i=0; i!=len; i++ ) *buf++=CH375_RD_DAT_PORT();
175 1 return( len );
176 1 }
177
C51 COMPILER V7.07 CH375PRT 11/03/2004 19:15:32 PAGE 4
178 void wr_usb_data( unsigned char len, unsigned char *buf ) { /* 向CH37X写入数据块 */
179 1 CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); /* 向CH375的端点缓冲区写入准备发送的数据 */
180 1 CH375_WR_DAT_PORT( len ); /* 后续数据长度, len不能大于64 */
181 1 while( len-- ) CH375_WR_DAT_PORT( *buf++ );
182 1 }
183
184 /* 主机操作 */
185 unsigned char endp_out_addr; /* 打印机数据接收端点的端点地址 */
186 unsigned char endp_out_size; /* 打印机数据接收端点的端点尺寸 */
187 BOOL1 tog_send; /* 打印机数据接收端点的同步标志 */
188 unsigned char endp_in_addr; /* 打印机状态发送端点的端点地址,为0则只支持单向接口 */
189 BOOL1 tog_recv; /* 打印机状态发送端点的同步标志 */
190
191 unsigned char issue_token( unsigned char endp_and_pid ) { /* 执行USB事务 */
192 1 /* 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 */
193 1 CH375_WR_CMD_PORT( CMD_ISSUE_TOKEN );
194 1 CH375_WR_DAT_PORT( endp_and_pid ); /* 高4位目的端点号, 低4位令牌PID */
195 1 return( wait_interrupt() ); /* 等待CH375操作完成 */
196 1 }
197
198 void soft_reset_print( ) { /* 控制传输:软复位打印机 */
199 1 tog_send=tog_recv=0; /* 复位USB数据同步标志 */
200 1 toggle_send( 0 ); /* SETUP阶段为DATA0 */
201 1 buffer[0]=0x21; buffer[1]=2; buffer[2]=buffer[3]=buffer[4]=buffer[5]=buffer[6]=buffer[7]=0; /* SETUP数据
-,SOFT_RESET */
202 1 wr_usb_data( 8, buffer ); /* SETUP数据总是8字节 */
203 1 if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_OUT )==USB_INT_SUCCESS ) { /* SETUP阶段操作成功 */
204 2 toggle_recv( 1 ); /* STATUS阶段,准备接收DATA1 */
205 2 if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) return; /* STATUS阶段操作成功,操作成
-功返回 */
206 2 }
207 1 }
208
209 #define USB_INT_RET_NAK 0x2A /* 00101010B,返回NAK */
210 void send_data( unsigned short len, unsigned char *buf ) { /* 主机发送数据块,一次最多64KB */
211 1 unsigned char l, s;
212 1 while( len ) { /* 连续输出数据块给USB打印机 */
213 2 toggle_send( tog_send ); /* 数据同步 */
214 2 l = len>endp_out_size?endp_out_size:len; /* 单次发送不能超过端点尺寸 */
215 2 wr_usb_data( l, buf ); /* 将数据先复制到CH375芯片中 */
216 2 s = issue_token( ( endp_out_addr << 4 ) | DEF_USB_PID_OUT ); /* 请求CH375输出数据 */
217 2 if ( s==USB_INT_SUCCESS ) { /* CH375成功发出数据 */
218 3 tog_send = ~ tog_send; /* 切换DATA0和DATA1进行数据同步 */
219 3 len-=l; /* 计数 */
220 3 buf+=l; /* 操作成功 */
221 3 }
222 2 else if ( s==USB_INT_RET_NAK ) { /* USB打印机正忙,如果未执行SET_RETRY命令则CH375自动重试,所以不会返回US
-B_INT_RET_NAK状态 */
223 3 /* USB打印机正忙,正常情况下应该稍后重试 */
224 3 /* s=get_port_status( ); 如果有必要,可以检查是什么原因导致打印机忙 */
225 3 }
226 2 else { /* 操作失败,正常情况下不会失败 */
227 3 clr_stall( endp_out_addr ); /* 清除打印机的数据接收端点,或者 soft_reset_print() */
228 3 /* soft_reset_print(); 打印机出现意外错误,软复位 */
229 3 tog_send = 0; /* 操作失败 */
230 3 }
231 2 /* 如果数据量较大,可以定期调用get_port_status()检查打印机状态 */
232 2 }
233 1 }
234
235 unsigned char get_port_status( ) { /* 查询打印机端口状态,返回状态码,如果为0FFH则说明操作失败 */
236 1 /* 返回状态码中: 位5(Paper Empty)为1说明无纸, 位4(Select)为1说明打印机联机, 位3(Not Error)为0说明打印机出
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -