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

📄 ch375host.c

📁 USB 1.1 U Device for CH375 & USB 2.0 for CH375A 读写usb超精简的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		// 接收成功,返回接收到的数据长度  
		if( status == USB_INT_SUCCESS )   
		{
		    status = CH375_ReadUSBData( buffer );// 读取接收到的数据 
			return( status );             // 返回数据长度( 0--64B ) 
		}
		// 接收错误处理 
		else
		{
			CH375_ClrStall6( );           // 接收设备端的端点错误 
			return( 0xFF );               // 返回操作失败 
		}
	}
}

//=================================================================================================
// 
//-------------------------------------------------------------------------------------------------
// 从设备端获取描述符 
unsigned char CH375_GetDescription( unsigned char type ) 
{
	xWriteCH375Cmd( CMD_GET_DESCR );
	xWriteCH375Data( type );              // 描述符类型, 只支持1(设备)或者2(配置) 

	return( xQueryInterrupt( ) );         // 等待CH375操作完成 

	// 由于CH375 的控制传输缓冲区只有64个字节,所以当描述符的长度超过64 字节时,
	// CH375将返回操作状态USB_INT_BUF_OVER,对于该USB 设备,单片机可以通过ISSUE_TOKEN 命令自行处理控制传输。
}

//-------------------------------------------------------------------------------------------------
// 设置设备端的USB地址 
unsigned char CH375_SetAddress( unsigned char address )   
{
	unsigned char status;

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

	return( status );
}

//-------------------------------------------------------------------------------------------------
// 设置设备端的USB配置 
unsigned char CH375_SetConfiguration( unsigned char configuration )   
{
	Endp6Mode = Endp7Mode = 0x80;         // 复位USB数据同步标志 

	xWriteCH375Cmd( CMD_SET_CONFIG );     // 设置USB设备端的配置值 
	xWriteCH375Data( configuration );     // 此值取自USB设备的配置描述符中 
	
	return( xQueryInterrupt( ) );         // 等待CH375操作完成 
}

//=================================================================================================
//=================================================================================================
// CH375初始化子程序 
//=================================================================================================
//=================================================================================================
// 
void CH375Init( void )
{
	unsigned char i, k;
	unsigned char Datum;

//	CH375_PORT_INIT( );                   // 使用通用I/O模块并口读写时序,进行初始化 
	
	// 测试CH375是否正常工作 
	for( k=100; k!=0; k-- )
	{
		xWriteCH375Cmd( CMD_CHECK_EXIST );// 测试CH375是否正常工作 
		i = 0x5A; xWriteCH375Data( i );   // 写入测试数据 
		
		i = ~i;                           // 返回数据应该是测试数据取反 
		Datum = xReadCH375Data( );
		if( Datum != i )                  // CH375不正常 
		{
		    for ( i=5; i!=0; i-- )
			{
			    xWriteCH375Cmd( CMD_RESET_ALL ); // 多次重复发命令,执行硬件复位 
			}
			mDelaymS( 50 );               // 延时50mS 
		}
		else break;
	}
	if( k==0 )
	{
		mStopIfError( 0xFF );             // 如果错误则停止运行并显示错误状态 
	}
	
	// 设置USB主机模式, 如果设备端是CH37X, 那么5和6均可 
	CH375_SetUSBMode( 6 );
//	while( xQueryInterrupt( )!=USB_INT_CONNECT );// 等待USB设备连接上来 
}

//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
// 初始化USB设备,完成设备枚举 
unsigned char CH375InitUSBDevice( void )
{
	unsigned char  address;
	unsigned char  status;
	unsigned char  length;	

	//-------------------------------------------
	// USB规范中未要求在USB设备插入后必须复位该设备,但是计算机的WINDOWS总是这样做,
#ifdef USB_RESET_FIRST
	CH375_SetUSBMode( 7 );                // 复位USB设备,CH375向USB信号线的D+和D-输出低电平 
	mDelaymS( 10 );                       // 复位时间不少于1mS,建议为10mS 
	CH375_SetUSBMode( 6 );
	mDelaymS( 100 );
	while( xQueryInterrupt( )!=USB_INT_CONNECT );// 等待复位之后的USB设备端再次连接上来 
	mDelaymS( 200 );
#endif
	
	//-------------------------------------------
	// 获取设备描述符 
	status = CH375_GetDescription( 1 );   
	if( status == USB_INT_SUCCESS )
	{
	    length = CH375_ReadUSBData( RECV_BUFFER );  // 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 
		// 设备描述符错误 
		if( (length<18) || (p_dev_descr->bDescriptorType!=1) ) 
			return( UNKNOWN_USB_DEVICE ); // 意外错误:描述符长度错误或者类型错误 		
		if( p_dev_descr->bDeviceClass!=0 ) 
			return( UNKNOWN_USB_DEVICE ); // 连接的USB设备不符合USB规范 
		
		status = CH375_SetAddress( 2 );   // 设置USB设备的USB地址 ????????????
		if( status == USB_INT_SUCCESS )
		{
			status = CH375_GetDescription( 2 ); // 获取配置描述符 
			if( status == USB_INT_SUCCESS ) // 操作成功则读出描述符并分析 
			{
				length = CH375_ReadUSBData( RECV_BUFFER );  // 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 
				// 配置描述符错误 
				if( (p_cfg_descr->itf_descr.bInterfaceClass!=7) || (p_cfg_descr->itf_descr.bInterfaceSubClass!=1) )
					return( UNKNOWN_USB_DEVICE );// 不符合USB规范 
				
				EndpOutAddr = EndpInAddr = 0;
				address = p_cfg_descr->endp_descr[0].bEndpointAddress;  // 第一个端点的地址 
				if( address & 0x80 ) EndpInAddr = address & 0x0F;    // IN端点的地址 
				else                                                 // OUT端点 
				{  
					EndpOutAddr = address & 0x0F;
					EndpOutSize = p_cfg_descr->endp_descr[0].wMaxPacketSize;  // 数据接收端点的最大包长度 
					if( (EndpOutSize == 0) || (EndpOutSize > 64) ) EndpOutSize = 64;
				}
				// 接口有两个以上的端点 
				if( p_cfg_descr->itf_descr.bNumEndpoints >= 2 )      
				{
					if( p_cfg_descr->endp_descr[1].bDescriptorType == 5 )   // 端点描述符 
					{
						address = p_cfg_descr->endp_descr[1].bEndpointAddress;  // 第二个端点的地址 
						if( address & 0x80 ) EndpInAddr = address & 0x0F;  // IN端点 
						else                                               // OUT端点 
						{  
							EndpOutAddr = address & 0x0F;
							EndpOutSize = p_cfg_descr->endp_descr[1].wMaxPacketSize;
							if( (EndpOutSize == 0) || (EndpOutSize > 64) ) EndpOutSize = 64;
						}
					}
				}
				if( p_cfg_descr->itf_descr.bInterfaceProtocol==1 ) EndpInAddr = 0;  // 单向接口不需要IN端点 
				if( EndpOutAddr == 0 ) return( UNKNOWN_USB_DEVICE ); // 不符合USB规范 
				
				status = CH375_SetConfiguration( p_cfg_descr->cfg_descr.bConfigurationvalue );  // 加载USB配置值 
				if( status == USB_INT_SUCCESS )
				{
					// 如果单片机在USB设备忙时并无事可做,建议设置位7为1,使CH375在收到NAK时自动重试直到操作成功或者失败 
					// 如果希望单片机在USB设备忙时能够做其它事,那么应该设置位7为0,使CH375在收到NAK时不重试,
					// 所以在下面的USB通讯过程中,如果USB设备正忙,issue_token等子程序将得到状态码USB_INT_RET_NAK 
					xWriteCH375Cmd( CMD_SET_RETRY );  // 设置USB事务操作的重试次数 
					xWriteCH375Data( 0x25 );          // 输入 0x25 
					xWriteCH375Data( 0xC5 );          // 位7为0则收到NAK时不重试 
													  // 位7为1位6为0则收到NAK时无限重试 (CH375A)
													  // 位7为1位6为1则收到NAK时重试200mS, 位5~位0为超时后的重试次数 (CH375A)
				}
			}
		}
	}
	return( status );
}





//=================================================================================================
//							  	      CH375 Host Procedure 
//=================================================================================================
// 
void CH375HostProcess( void )
{
	unsigned char i;
	unsigned char length;

	i = xQueryInterrupt( );               // 查询中断状态 
	if( i == USB_INT_CONNECT )            // 检测到有设备连接 
	{
	//	UART0SendString( "USB设备连接\n" ); 

		// 如果设备端是CH37X,那么以下步骤是可选的,
		// 如果是其它USB芯片,那么需要执行以下步骤,并且要分析配置描述符的数据获得配置值以及端点号,并修改本程序中的端点号,
		// USB规范中未要求在USB设备插入后必须复位该设备,但是计算机的WINDOWS总是这样做,所以有些USB设备也要求在插入后必须先复位才能工作 
		CH375_SetUSBMode( 7 );            // 复位USB设备,CH375向USB信号线的D+和D-输出低电平 

		// 如果单片机对CH375的INT#引脚采用中断方式而不是查询方式,那么应该在复制USB设备期间禁止CH375中断,在USB设备复位完成后清除CH375中断标志再允许中断 
		mDelaymS( 50 );                   // Waiting ... 
		CH375_SetUSBMode( 6 );            // 结束复位 

		// 等待复位之后的设备端再次连接上来 
		while( 1 )
		{
			i = xQueryInterrupt( );       // 查询中断状态 
			if( i == USB_INT_CONNECT ) break;
		}

		// 有些USB设备要求延时数百毫秒后才能工作 
		mDelay( 100 );

		// 初始化USB设备 
		for( i=5; i!=0; i-- )
		{
			if( CH375InitUSBDevice( ) != USB_INT_SUCCESS ) mStopIfError( 0xFF );
			else                                            break;
		}
		if( i == 0 ) mStopIfError( 0xFF );

		// Processing 
		while( 1 )
		{
			ReceiveBuffer = RECV_BUFFER;  // 接收缓冲区 
			length = CH375_HostReceive( ReceiveBuffer );   // 从设备端接收数据 
			if( length == 0xEF )          // 串口接收到数据 
			{
				LED_OUT_ACT( );           // Enable LED! 
				receive( );
				LED_OUT_INACT( );         // Disable LED! 

				ReceiveBuffer = RECV_BUFFER;     // 接收缓冲区 
				length = RECV_LEN;        // 刚接收到的数据长度 

				if( length !=0 ) CH375_HostSend( length, ReceiveBuffer ); // 将从串口接收到的数据发送到USB设备 
				else if( length == 0xFE ) break; // USB设备断开事件 
				else if( length != 0xFF )
				{
					ReceiveBuffer = RECV_BUFFER; // 接收缓冲区 
					while( length-- )
					{
						SendChar( *ReceiveBuffer ); // 将从USB设备接收到的数据发送到串口 
						ReceiveBuffer++;
					}
				}
			}
		}
	}
}

⌨️ 快捷键说明

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