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

📄 ch375.c

📁 CH375按照从设备外置固件模式
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "k9f1208.h"
#include "Ch375.h"
#include "44blib.h"

//driver 
U8 endp_out_addr;	// 打印机数据接收端点的端点地址
U8 endp_out_size;	//打印机数据接收端点的端点尺寸
U8 tog_send;		//打印机数据接收端点的同步标志 
U8 endp_in_addr;	//打印机状态发送端点的端点地址,为0则只支持单向接口
U8 tog_recv;		// 打印机状态发送端点的同步标志
U8 buffer[64];

void EZUSB_Delay(U8 dly)
{	
  int count;
  U8 i;
   for(i=0;i<=dly;i++)
  {
   for(count=1;count<8580;count++);
  }
}

void	delay2us( )
{
	unsigned char i;
	for ( i = 200; i != 0; i -- );
}

void	delay100ms( )
{
	unsigned int	i, j, c;
	for ( i = 2000; i != 0; i -- ) for ( j = 2000; j != 0; j -- ) c+=3;
}


void CH375_WR_CMD_PORT( unsigned char cmd )
{
	delay2us();
	CH375_CMD_PORT=cmd;
	delay2us();
}

void CH375_WR_DAT_PORT( unsigned char dat )
 {
    delay2us();
	CH375_DAT_PORT=dat;
	delay2us(); 
}

unsigned char CH375_RD_DAT_PORT() 
{
	delay2us();
	delay2us();
	return( CH375_DAT_PORT );
}

unsigned char wait_interrupt() 
{  /* 主机端等待操作完成, 返回操作状态 */
	unsigned char i;
	while((rPDATG&0x1)==0x1);
	CH375_WR_CMD_PORT( CMD_GET_STATUS );  /* 产生操作完成中断, 获取中断状态 */
	i=CH375_RD_DAT_PORT();
	return(i);
}

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!=200; i++ ) 
	{
		if ( CH375_RD_DAT_PORT()==CMD_RET_SUCCESS ) 
		return( TRUE ); 
	}
	return( FALSE );  
}

void toggle_recv( U8 tog ) 
{  /* 主机接收同步控制:0=DATA0,1=DATA1 */
	CH375_WR_CMD_PORT( CMD_SET_ENDP6 );
	CH375_WR_DAT_PORT( tog ? 0xC0 : 0x80 );
	delay2us();
}

void toggle_send( U8 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() );
}

unsigned char rd_usb_data( unsigned char *buf ) 
{  /* 从CH37X读出数据块 */
	unsigned char i, len,j;
	CH375_WR_CMD_PORT( CMD_RD_USB_DATA );  	  	/* 从CH375的端点缓冲区读取接收到的数据 */
	len=CH375_RD_DAT_PORT();  		   			/* 后续数据长度 */
	Uart_Printf("receive.....\n");
	for ( i=0; i!=len; i++ ) 
	{
	j=CH375_RD_DAT_PORT();
	Uart_SendByte(j);
	*buf++=j;
	}
	return( len );
}

void wr_usb_data( unsigned char len, unsigned char *buf ) 
{  /* 向CH37X写入数据块 */
	CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 );    /* 向CH375的端点缓冲区写入准备发送的数据 */
	delay2us();
	CH375_WR_DAT_PORT( len );  				  /* 后续数据长度, len不能大于64 */
	//Uart_Printf("[");
	while( len-- ) 
	{
	      // Uart_Printf("%2x ",*buf);
		   CH375_WR_DAT_PORT( *buf++ );
		   delay2us();
    }
    //Uart_Printf("]\n");
}

unsigned char issue_token( unsigned char endp_and_pid ) 
{  /* 执行USB事务 */
	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]=0;
	buffer[3]=0;
	buffer[4]=0;
	buffer[5]=0;
	buffer[6]=0;
	buffer[7]=0;  								/* SETUP数据,SOFT_RESET */
	wr_usb_data( 8, buffer );  					/* SETUP数据总是8字节 */
	if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_OUT )==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 */
/* 如果数据量较大,可以定期调用get_port_status()检查打印机状态 */
void send_data( unsigned int len, unsigned char *buf ) 
{  /* 主机发送数据块,一次最多64KB */
	unsigned char l, s;
	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;  /* 操作失败 */
		}

	}
}

unsigned char get_port_status( ) 
{  /* 查询打印机端口状态,返回状态码,如果为0FFH则说明操作失败 */
/* 返回状态码中: 位5(Paper Empty)为1说明无纸, 位4(Select)为1说明打印机联机, 位3(Not Error)为0说明打印机出错 */
	if ( endp_in_addr ) 
	{  /* 支持双向接口 */
		toggle_recv( tog_recv );  /* 设置主机接收的同步标志 */
		if ( issue_token( ( endp_in_addr << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) 
		{  /* 接收成功 */
			tog_recv = ~ tog_recv;  /* 数据同步 */
			rd_usb_data( buffer );  /* 读取接收到的数据,通常只有1个字节 */
			return( buffer[0] );  /* 返回状态码 */
		}
		else {  /* 接收失败 */
			clr_stall( endp_in_addr | 0x80 );  /* 接收设备端的端点错误 */
			tog_recv = 0;
			return( 0xFF );  /* 返回操作失败 */
		}
	}
	else {  /* 只支持单向接口,下面通过控制传输获取打印机的状态 */
		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 );  /* 返回操作失败 */
}

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地址 */
	}
	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
#define	p_dev_descr		((PUSB_DEV_DESCR)buffer)
#define	p_cfg_descr		((PUSB_CFG_DESCR_LONG)buffer)
unsigned char init_print() 
{  		 	  			   /* 初始化USB打印机,完成打印机枚举 */
	unsigned char status, len, c;
	status=get_descr(1);  /* 获取设备描述符 */
	if ( status==USB_INT_SUCCESS ) 
	{
		len=rd_usb_data( buffer );  
		/* 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 */
		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 ) 
		{
			status=get_descr(2);  /* 获取配置描述符 */
			if ( status==USB_INT_SUCCESS ) 
			{  /* 操作成功则读出描述符并分析 */
				len=rd_usb_data( buffer );  /* 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 */
				if ( p_cfg_descr->itf_descr.bInterfaceClass!=7 || p_cfg_descr->itf_descr.bInterfaceSubClass!=1 ) 
				  return( UNKNOWN_USB_PRINT );  /* 不是USB打印机或者不符合USB规范 */
				endp_out_addr=endp_in_addr=0;
				c=p_cfg_descr->endp_descr[0].bEndpointAddress;  /* 第一个端点的地址 */
				if ( c&0x80 ) endp_in_addr=c&0x0f;  /* IN端点的地址 */
				else 
				{  /* OUT端点 */
					endp_out_addr=c&0x0f;
					endp_out_size=p_cfg_descr->endp_descr[0].wMaxPacketSize;  /* 数据接收端点的最大包长度 */
				}
				if ( p_cfg_descr->itf_descr.bNumEndpoints>=2 )
				 {  /* 接口有两个以上的端点 */
					if ( p_cfg_descr->endp_descr[1].bDescriptorType==5 ) 
					{  /* 端点描述符 */
						c=p_cfg_descr->endp_descr[1].bEndpointAddress;  /* 第二个端点的地址 */
						if ( c&0x80 ) endp_in_addr=c&0x0f;  /* IN端点 */
						else {  /* OUT端点 */
							endp_out_addr=c&0x0f;
							endp_out_size=p_cfg_descr->endp_descr[1].wMaxPacketSize;
						}
					}
				}
				if ( p_cfg_descr->itf_descr.bInterfaceProtocol==1 ) 
				   endp_in_addr=0;  /* 单向接口不需要IN端点 */
				if ( endp_out_addr==0 ) 
				   return( UNKNOWN_USB_PRINT );  /* 不是USB打印机或者不符合USB规范 */
				status=set_config( p_cfg_descr->cfg_descr.bConfigurationValue );  
				/* 加载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为超时后的重试次数 */
/* 如果单片机在打印机忙时并无事可做,建议设置位7为1,使CH375在收到NAK时自动重试直到操作成功或者失败 */
/* 如果希望单片机在打印机忙时能够做其它事,那么应该设置位7为0,使CH375在收到NAK时不重试,
   所以在下面的USB通讯过程中,如果USB打印机正忙,issue_token等子程序将得到状态码USB_INT_RET_NAK */
				}
			}
		}
	}
//	putstring("endp_out_addr is $");
//	outchar2(endp_out_addr);
//	putstring("endp_out_size is $");
//	outchar2(endp_out_size);
//	putstring("endp_in_addr is $");
//	outchar2(endp_in_addr);
						
	return(status);
}

/*
void Slave_Detach(void)
{
 	 unsigned char i,j;
     CH375_COMM=CMD_CHECK_EXIST;
     i = 0xa5;
	 delay2us();
     CH375_DATA= i;
	 delay2us();
	 delay2us();
     i = ~i;
	 j = CH375_DATA;
	 if(i!=j)
	 {
	    SLAVE_ENUMERATED = FALSE;					// return to un-enumeration
		putstring("usb device not exist!$");
		PORTB|=0x08;
		PORTE&=0xfb;//busy=0;
	 }
	 CH375_WR_CMD_PORT( CMD_GET_STATUS );  // 产生操作完成中断, 获取中断状态 
	 i=CH375_RD_DAT_PORT();
	 //outchar2(i);
	 if(i==0x16)
	  {
	     SLAVE_ENUMERATED = FALSE;
		 putstring("usb device pull out!$");
	  }
	
}	 	

void slave_detect(void)
   {
    unsigned char i;
	if(!SLAVE_ENUMERATED)					
	{
		{
		 	putstring("begin usb$"); 		
			set_usb_mode( 6 );  				  		  // 设置USB主机模式
	        while ( wait_interrupt()!=USB_INT_CONNECT );  // 等待USB打印机连接上来
			putstring("find device!$");
	   		set_usb_mode( 7 );
	        for ( i=0; i<250; i++ )
			{ 
			 delay2us(); 
			 delay2us(); 
			 delay2us(); 
			 delay2us(); 
			}  		 	  	  	   	   				  	  // 复位时间不少于1mS,建议为10mS
	       set_usb_mode( 6 );    						  // 结束复位
	       while ( wait_interrupt()!=USB_INT_CONNECT );   // 等待复位之后的设备端再次连接上来
		   putstring("after reset find device!$");
	  	   delay100ms(); 
		   delay100ms();                                  //有些USB设备要等待数百毫秒才能正常工作
	       if ( init_print()!=USB_INT_SUCCESS )
			{
			  putstring("err!$"); 
			  SLAVE_ENUMERATED=FALSE;
			}
			else
			{
			  putstring("done!$");
			  SLAVE_ENUMERATED=TRUE;
			  address.int_value=0x003a;//v-height
			  five_program=0;
			  PORTB&=0xf7;								  //led turn on
			}  
	   	}	
	}
	else									
	   Slave_Detach();	// test for slave device detach ???
}
*/
int DataRW_in(BYTE usbaddr, BYTE epaddr, WORD wPayload, WORD wLen, BYTE const *pData)
{
  unsigned char buff[64],i;
  unsigned int inta,len;
  unsigned int intb;
  BYTE const *prt;
  inta=wLen/64;
  intb=wLen%64;
  prt=pData;
  for(len=0;len<inta;len++)
	{
	 	for(i=0;i<64;i++)
		 {
		 buff[i]=*prt;
		 prt++;
		 }
	   	DataRW(1,1,64,64,buff);
	}       
	if(intb)
	{
	    for(i=0;i<intb;i++)
		 {
		 buff[i]=*prt;
		 prt++;
		 }
		DataRW(1,1,64,intb,buff);
   }
   return TRUE;
}


⌨️ 快捷键说明

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