📄 8051_ch375prt.c
字号:
****************************************
** USB 1.1 Host Examples for CH375 **
****************************************
*/
/* 单片机通过CH375控制USB打印机 */
/* 程序示例,C语言,CH375中断为查询方式,只负责数据传输,不涉及打印格式及打印描述语言 */
/* 另可提供多台计算机共享一台USB打印机的方案 */
/* 以下定义适用于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地址 */
sbit CH375_INT_WIRE = 0xB0^2; /* P3.2, INT0, 连接CH375的INT#引脚,用于查询中断状态 */
typedef unsigned char BOOL1; /* typedef bit BOOL1; */
/* 以下为通用的单片机C程序 */
#include <string.h>
#include <stdio.h>
/* 定义CH375命令代码及返回状态 */
#include "CH375INC.H"
typedef unsigned char UCHAR;
typedef unsigned short USHORT;
typedef struct _USB_DEVICE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
typedef struct _USB_CONFIG_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
typedef struct _USB_INTERF_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
typedef struct _USB_ENDPOINT_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bEndpointAddress;
UCHAR bmAttributes;
UCHAR wMaxPacketSize;
UCHAR wMaxPacketSize1;
UCHAR bInterval;
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
typedef struct _USB_CONFIG_DESCRIPTOR_LONG {
USB_CFG_DESCR cfg_descr;
USB_ITF_DESCR itf_descr;
USB_ENDP_DESCR endp_descr[4];
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
unsigned char buffer[64]; /* 公用缓冲区 */
/* 延时2微秒,不精确 */
void delay2us( )
{
unsigned char i;
for ( i = 2; i != 0; i -- );
}
/* 延时1微秒,不精确 */
void delay1us( )
{
unsigned char i;
for ( i = 1; i != 0; i -- );
}
/* 以毫秒为单位延时,不精确,适用于24MHz时钟 */
void mDelaymS( unsigned char delay )
{
unsigned char i, j, c;
for ( i = delay; i != 0; i -- ) {
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz时钟下延时500uS */
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz时钟下延时500uS */
}
}
/* 基本操作 */
void CH375_WR_CMD_PORT( unsigned char cmd ) { /* 向CH375的命令端口写入命令,周期不小于4uS,如果单片机较快则延时 */
delay2us();
CH375_CMD_PORT=cmd;
delay2us();
}
void CH375_WR_DAT_PORT( unsigned char dat ) { /* 向CH375的数据端口写入数据,周期不小于1.5uS,如果单片机较快则延时 */
CH375_DAT_PORT=dat;
delay1us(); /* 因为MCS51单片机较慢所以实际上无需延时 */
}
unsigned char CH375_RD_DAT_PORT() { /* 从CH375的数据端口读出数据,周期不小于1.5uS,如果单片机较快则延时 */
delay1us(); /* 因为MCS51单片机较慢所以实际上无需延时 */
return( CH375_DAT_PORT );
}
unsigned char wait_interrupt() { /* 主机端等待操作完成, 返回操作状态 */
unsigned short i;
// while( CH375_INT_WIRE ); /* 查询等待CH375操作完成中断(INT#低电平) */
for ( i = 0; CH375_INT_WIRE != 0; i ++ ) { /* 如果CH375的中断引脚输出高电平则等待,通过计数防止超时 */
delay1us();
if ( i == 0xF000 ) CH375_WR_CMD_PORT( CMD_ABORT_NAK ); /* 如果超时达61mS以上则强行终止NAK重试,中断返回USB_INT_RET_NAK */
}
CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 产生操作完成中断, 获取中断状态 */
return( CH375_RD_DAT_PORT() );
}
#define TRUE 1
#define FALSE 0
unsigned char set_usb_mode( unsigned char mode ) { /* 设置CH375的工作模式 */
unsigned char i;
CH375_WR_CMD_PORT( CMD_SET_USB_MODE );
CH375_WR_DAT_PORT( mode );
for( i=0; i!=100; i++ ) { /* 等待设置模式操作完成,不超过30uS */
if ( CH375_RD_DAT_PORT()==CMD_RET_SUCCESS ) return( TRUE ); /* 成功 */
}
return( FALSE ); /* CH375出错,例如芯片型号错或者处于串口方式或者不支持 */
}
/* 数据同步 */
/* USB的数据同步通过切换DATA0和DATA1实现: 在设备端, USB打印机可以自动切换;
在主机端, 必须由SET_ENDP6和SET_ENDP7命令控制CH375切换DATA0与DATA1.
主机端的程序处理方法是为设备端的各个端点分别提供一个全局变量,
初始值均为DATA0, 每执行一次成功事务后取反, 每执行一次失败事务后将其复位为DATA1 */
void toggle_recv( BOOL1 tog ) { /* 主机接收同步控制:0=DATA0,1=DATA1 */
CH375_WR_CMD_PORT( CMD_SET_ENDP6 );
CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 );
delay2us();
}
void toggle_send( BOOL1 tog ) { /* 主机发送同步控制:0=DATA0,1=DATA1 */
CH375_WR_CMD_PORT( CMD_SET_ENDP7 );
CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 );
delay2us();
}
unsigned char clr_stall( unsigned char endp_addr ) { /* USB通讯失败后,复位设备端的指定端点到DATA0 */
CH375_WR_CMD_PORT( CMD_CLR_STALL );
CH375_WR_DAT_PORT( endp_addr );
return( wait_interrupt() );
}
/* 数据读写, 单片机读写CH375芯片中的数据缓冲区 */
unsigned char rd_usb_data( unsigned char *buf ) { /* 从CH37X读出数据块 */
unsigned char i, len;
CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 从CH375的端点缓冲区读取接收到的数据 */
len=CH375_RD_DAT_PORT(); /* 后续数据长度 */
for ( i=0; i!=len; i++ ) *buf++=CH375_RD_DAT_PORT();
return( len );
}
void wr_usb_data( unsigned char len, unsigned char *buf ) { /* 向CH37X写入数据块 */
CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); /* 向CH375的端点缓冲区写入准备发送的数据 */
CH375_WR_DAT_PORT( len ); /* 后续数据长度, len不能大于64 */
while( len-- ) CH375_WR_DAT_PORT( *buf++ );
}
/* 主机操作 */
unsigned char endp_out_addr; /* 打印机数据接收端点的端点地址 */
unsigned char endp_out_size; /* 打印机数据接收端点的端点尺寸 */
BOOL1 tog_send; /* 打印机数据接收端点的同步标志 */
unsigned char endp_in_addr; /* 双向打印机发送端点的端点地址,一般不用 */
BOOL1 tog_recv; /* 双向打印机发送端点的同步标志,一般不用 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -