⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch375prt.c

📁 采用51核单片机+375A usb主控芯片驱动hp打印机
💻 C
📖 第 1 页 / 共 5 页
字号:
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;				/* 双向打印机发送端点的同步标志,一般不用 */

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操作完成 */
}

void soft_reset_print( ) {  /* 控制传输:软复位打印机 */
	tog_send=tog_recv=0;  /* 复位USB数据同步标志 */
	toggle_send( 0 );  /* SETUP阶段为DATA0 */
	buffer[0]=0x21; buffer[1]=2; buffer[2]=buffer[3]=buffer[4]=buffer[5]=buffer[6]=buffer[7]=0;  /* SETUP数据,SOFT_RESET */
	wr_usb_data( 8, buffer );  /* SETUP数据总是8字节 */
	if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_SETUP )==USB_INT_SUCCESS ) {  /* SETUP阶段操作成功 */
		toggle_recv( 1 );  /* STATUS阶段,准备接收DATA1 */
		if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) return;  /* STATUS阶段操作成功,操作成功返回 */
	}
}

#define	USB_INT_RET_NAK		0x2A		/* 00101010B,返回NAK */
void send_data( unsigned int len, unsigned char *buf ) {  /* 主机发送数据块,一次最多64KB */
	unsigned char l, s;
    endp_out_size=64;
	while( len ) {  /* 连续输出数据块给USB打印机 */
		toggle_send( tog_send );  /* 数据同步 */
		l = len>endp_out_size?endp_out_size:len;  /* 单次发送不能超过端点尺寸 */
		wr_usb_data( l, buf );  /* 将数据先复制到CH375芯片中 */
		s = issue_token( ( endp_out_addr << 4 ) | DEF_USB_PID_OUT );  /* 请求CH375输出数据 */
		if ( s==USB_INT_SUCCESS ) {  /* CH375成功发出数据 */
			tog_send = ~ tog_send;  /* 切换DATA0和DATA1进行数据同步 */
			len-=l;  /* 计数 */
			buf+=l;  /* 操作成功 */
		}
		else if ( s==USB_INT_RET_NAK ) {  /* USB打印机正忙,如果未执行SET_RETRY命令则CH375自动重试,所以不会返回USB_INT_RET_NAK状态 */
			/* USB打印机正忙,正常情况下应该稍后重试 */
//			 s=get_port_status( );  /*如果有必要,可以检查是什么原因导致打印机忙 */
		}
		else {  /* 操作失败,正常情况下不会失败 */
			clr_stall( endp_out_addr );  /* 清除打印机的数据接收端点,或者 soft_reset_print() */
			soft_reset_print(); /* 打印机出现意外错误,软复位 */
			tog_send = 0;  /* 操作失败 */
		}
/* 如果数据量较大,可以定期调用get_port_status()检查打印机状态 */
	}
}


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_SETUP )==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 );  /* 返回操作失败 */
}


unsigned char get_descr( unsigned char type ) {  /* 从设备端获取描述符 */
	CH375_WR_CMD_PORT( CMD_GET_DESCR );
	CH375_WR_DAT_PORT( type );  /* 描述符类型, 只支持1(设备)或者2(配置) */
	return( wait_interrupt() );  /* 等待CH375操作完成 */
}

unsigned char set_addr( unsigned char addr ) {  /* 设置设备端的USB地址 */
	unsigned char status;
	CH375_WR_CMD_PORT( CMD_SET_ADDRESS );  /* 设置USB设备端的USB地址 */
	CH375_WR_DAT_PORT( addr );  /* 地址, 从1到127之间的任意值, 常用2到20 */
	status=wait_interrupt();  /* 等待CH375操作完成 */
	if ( status==USB_INT_SUCCESS ) {  /* 操作成功 */
		CH375_WR_CMD_PORT( CMD_SET_USB_ADDR );  /* 设置USB主机端的USB地址 */
		CH375_WR_DAT_PORT( addr );  /* 当目标USB设备的地址成功修改后,应该同步修改主机端的USB地址 */
	}
	mDelaymS( 5 );
	return( status );
}

unsigned char set_config( unsigned char cfg ) {  /* 设置设备端的USB配置 */
	tog_send=tog_recv=0;  /* 复位USB数据同步标志 */
	CH375_WR_CMD_PORT( CMD_SET_CONFIG );  /* 设置USB设备端的配置值 */
	CH375_WR_DAT_PORT( cfg );  /* 此值取自USB设备的配置描述符中 */
	return( wait_interrupt() );  /* 等待CH375操作完成 */
}


#define	UNKNOWN_USB_DEVICE	0xF1
#define	UNKNOWN_USB_PRINT	0xF2

unsigned char init_print() {  /* 初始化USB打印机,完成打印机枚举 */
#define	p_dev_descr		((PUSB_DEV_DESCR)buffer)
#define	p_cfg_descr		((PUSB_CFG_DESCR_LONG)buffer)
	unsigned char status, len, i;
	status=get_descr(1);  /* 获取设备描述符 */
	if ( status==USB_INT_SUCCESS ) {
		len=rd_usb_data( buffer );  /* 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 */
        for(i=0;i!=len;i++){
		}
		if ( len<18 || p_dev_descr->bDescriptorType!=1 ) return( UNKNOWN_USB_DEVICE );  /* 意外错误:描述符长度错误或者类型错误 */
		if ( p_dev_descr->bDeviceClass!=0 ) return( UNKNOWN_USB_DEVICE );  /* 连接的USB设备不是USB打印机,或者不符合USB规范 */
		status=set_addr(3);  /* 设置打印机的USB地址 */
		if ( status==USB_INT_SUCCESS ) {
			if ( status==USB_INT_SUCCESS ) {  /* 操作成功则读出描述符并分析 */
                endp_out_addr=0x81;  
				status=set_config( 0x01 );  /* 加载USB配置值 */
				if ( status==USB_INT_SUCCESS ) {
					CH375_WR_CMD_PORT( CMD_SET_RETRY );  /* 设置USB事务操作的重试次数 */
					CH375_WR_DAT_PORT( 0x25 );
					CH375_WR_DAT_PORT( 0x89 );  /* 位7为1则收到NAK时无限重试, 位3~位0为超时后的重试次数 */
//                    printf("set config ok!\n");
/* 如果单片机在打印机忙时并无事可做,建议设置位7为1,使CH375在收到NAK时自动重试直到操作成功或者失败 */
/* 如果希望单片机在打印机忙时能够做其它事,那么应该设置位7为0,使CH375在收到NAK时不重试,
   所以在下面的USB通讯过程中,如果USB打印机正忙,issue_token等子程序将得到状态码USB_INT_RET_NAK */
				}
			}
		}
	}
	return(status);
}

unsigned int HexToBCD(unsigned char Value)
{
  unsigned int i;
  i=(unsigned int)(Value>>4)*16+(unsigned int)(Value&0x0f);
  return(i);
}

void mInitSTDIO( )
{

  t2con=0x30;   	//timer2 used for baud rate generator
  scon0=0x50;     //
  rcap2h=0x0ff;  	//bundrate 9600
  rcap2l=0xdc;//
  TMOD=0x21;        // 
  scon1=0x50;       //
  TH1=0xfd;    //bundrate 9600 
  TL1=0xfd;
  EA=1;
  ES=1;
//  es1=1;
  TR1=1;
  tr2=1;


//   SCON = 0x50;
   PCON = 0x00;
//   TMOD = 0x21;
//   TH1 = 0xfd;  /* 11.0592MHz晶振, 9600bps */
//   TR1 = 1;
//   TI = 1;
//   RI=0;
//   EX0=1;
//   EA=0;
//   ES=1;///
   EA=1;///
}

void SendStr()
{
  unsigned char idata i;
  TI=0;
  RI=0;
  for(i=0;i<53;i++)
  {
   SBUF=buffer[i];
   while(TI);
   TI=0;
   mDelaymS( 50 );
  }

}

void RecvStr()
{
  TI=0;
  RI=0;
  if(SBUF==0xfd)
  {
   RecvStart=1;
   RecvCount=70;
   RecvFlage=1;
   SBUF=0xfa;
  }
  else
   if(RecvStart)
   {
    buffer[RecvCount]=SBUF;
    RecvCount++;
    if(RecvCount==123)
	{
     RecvStart=0;
	 RecvFlage=1;
    }
   }
}

void ComInt() interrupt 4
{
 TI=0;
 if(RI) RecvStr();
}

void ChangeData()
{
//编号
  buffer[0]=HexToBCD(buffer[70]);
  buffer[1]=HexToBCD(buffer[71]);
//年龄
  buffer[2]=HexToBCD(buffer[72]);
//身高
  buffer[3]=HexToBCD(buffer[73]);
  buffer[4]=HexToBCD(buffer[74]);
//腰围
  buffer[5]=HexToBCD(buffer[75]);
  buffer[6]=HexToBCD(buffer[76]);
//体重
  buffer[7]=HexToBCD(buffer[77]);
  buffer[8]=HexToBCD(buffer[78]);
//类型
  if(buffer[79])
   buffer[9]='G';// generic=1;motile=0
  else
   buffer[9]='M';// generic=1;motile=0
//性别
  if(buffer[80])
   buffer[10]='M';//male=1;female=0
  else
   buffer[10]='F';//male=1;female=0
//脂肪量  
  buffer[11]=HexToBCD(buffer[81]);
  buffer[12]=HexToBCD(buffer[82]);
//脂肪率
  buffer[13]=HexToBCD(buffer[83]);
  buffer[14]=HexToBCD(buffer[84]);
//净重
  buffer[15]=HexToBCD(buffer[85]);
  buffer[16]=HexToBCD(buffer[86]);
//水分
  buffer[17]=HexToBCD(buffer[87]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -