我用的375做主机,用的它的串口方式与单片机连接,想把从单片机并口接收的数据通过ch375送给USB打印机,可是打印出的数据不太对,不知道什么原因。
我再补充一下,我要实现的功能是:把一个智能仪器的数据通过其并口传给单片机,然后单片机通过CH375把数据转换成USB数据送给USB打印机,也就是为该智能仪器扩展USB接口,使其能够连接USB打印机。 我现在的问题是:智能仪器传过来的数据可能不是64的整数倍,那么最后一个数据包不够64的时候怎么处理啊?我在单片机中开了两个64字节的BUFFER,
你可以看下我们这边的例子程序,也是并口接收打印机数据,通过USB口发送数据。实际上只需要加一个定时器超时就可以了: /* 2004.03.05, 2004.8.18 **************************************** ** Copyright (C) W.ch 1999-2004 ** ** Web: http://www.winchiphead.com ** **************************************** ** USB 1.1 Host Examples for CH375 ** ** KC7.0@MCS-51 ** **************************************** */ //计算机通过并口发送数据,然后通过375转换成USB打印机 // 程序示例,C语言,CH375中断为查询方式,只负责数据传输,不涉及打印格式及打印描述语言
// 以下定义适用于MCS-51单片机,其它单片机参照修改,为了提供C语言的速度需要对本程序进行优化 //#pragma src #include #include #include #include "CH375INC.H" unsigned char volatile xdata CH375_CMD_PORT _at_ 0xDEF1; // CH375命令端口的I/O地址 unsigned char volatile xdata CH375_DAT_PORT _at_ 0xDCF0; // CH375数据端口的I/O地址 sbit cs_p=P1^3; sbit SIN=P1^4; sbit ACK=P1^6; sbit ERR=P1^7; sbit PE=P3^1; sbit BUSY0=P3^2; sbit STB=P3^0; sbit SLCT=P3^5; sbit CH375_INT_WIRE =P3^3; // P3.2, INT1, 连接CH375的INT#引脚,用于查询中断状态 unsigned char count=0,send=0; unsigned char xdata buffer[64]; // 公用缓冲区 unsigned char xdata data_to_send[64]; unsigned int j=0; typedef unsigned char BOOL1; // typedef bit BOOL1; 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;
// 延时2微秒,不精确 void delay2us( ) { unsigned char i; for ( i = 2; i != 0; i -- ); }
// 延时1微秒,不精确 void delay1us( ) { unsigned char i; for ( i = 1; i != 0; i -- ); }
void delay2ms( ) { unsigned char i,j; for ( i = 20; i != 1; i -- ) {for(j=100;j!=1;j--); } }
// 延时100毫秒,不精确 void delay100ms( ) { unsigned char i, j, c; for ( i = 200; i != 0; i -- ) for ( j = 200; j != 0; j -- ) c+=3; }
// 基本操作
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 int i=0; while( CH375_INT_WIRE ); 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 );} // 成功 else {return( FALSE );} // CH375出错,例如芯片型号错或者处于串口方式或者不支持 } } // USB的数据同步通过切换DATA0和DATA1实现: 在设备端, USB打印机可以自动切换; // 在主机端, 必须由SET_ENDP6和SET_ENDP7命令控制CH375切换DATA0与DATA1. // 主机端的程 序处理方法是为设备端的各个端点分别提供一个全局变量, // 初始值均为DATA0, 每执行一次成功事务后取反, 每执行一次失败事务后将其复位为DATA1
void toggle_send( BOOL1 tog ) { // 主机发送同步控制:0=DATA0,1=DATA1 CH375_WR_CMD_PORT( CMD_SET_ENDP7 ); CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 ); delay2us(); }
void toggle_recv( BOOL1 tog ) { /* 主机接收同步控制:0=DATA0,1=DATA1 */ CH375_WR_CMD_PORT( CMD_SET_ENDP6 ); CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 ); delay2us(); }
//数据读写, 单片机读写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++ );len--;} }
// 主机操作 unsigned char endp_out_addr; //打印机数据接收端点的端点地址 unsigned char endp_out_size; // 打印机数据接收端点的端点尺寸 BOOL1 tog_send; // 打印机数据接收端点的同步标志 unsigned char endp_in_addr; // 打印机状态发送端点的端点地址,为0则只支持单向接口 BOOL1 tog_recv; // 打印机状态发送端点的同步标志
unsigned char issue_token( unsigned char endp_and_pid ) { // 执行USB事务 // 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 CH375_WR_CMD_PORT( CMD_ISSUE_TOKEN ); CH375_WR_DAT_PORT( endp_and_pid ); // 高4位目的端点号, 低4位令牌PID return( wait_interrupt() ); // 等待CH375操作完成 }
#define USB_INT_RET_NAK 0x2A // 00101010B,返回NAK unsigned char get_port_status( ) { //查询打印机端口状态,返回状态码,如果为0FFH则说明操作失败 //返回状态码中: 位5(Paper Empty)为1说明无纸, 位4(Select)为1说明打印机联机, 位3(Not Error)为0说明打印机出错 toggle_send( 0 ); // SETUP阶段为DATA0 buffer[0]=0xA1; buffer[1]=1; buffer[2]=buffer[3]=buffer[4]=buffer[5]=0; buffer[6]=1; buffer[7]=0; // SETUP数据,GET_PORT_STATUS wr_usb_data( 8, buffer ); // SETUP数据总是8字节 if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_OUT )==USB_INT_SUCCESS ) { // SETUP阶段操作成功 toggle_recv( 1 ); // DATA阶段,准备接收DATA1 if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) { // DATA阶段操作成功 rd_usb_data( buffer ); // 读出接收到的数据,通常只有1个字节 toggle_send( 1 ); // STATUS阶段为DATA1 wr_usb_data( 0, buffer ); // 发送0长度的数据说明控制传输成功 if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_OUT )==USB_INT_SUCCESS ) return( buffer[0] ); // 返回状态码 } } return( 0xFF ); // 返回操作失败 }
void send_data( unsigned short len, unsigned char *buf ) { /* 主机发送数据块,一次最多64KB */ unsigned cha