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

📄 ch374_hid.c

📁 MCS51和CH374做USB主机与HID设备通信
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 设定全速USB设备运行环境 */
void	HostSetFullSpeed( void )  
{
	Write374Byte( REG_USB_SETUP, Read374Byte( REG_USB_SETUP ) & ~ BIT_SETP_USB_SPEED | BIT_SETP_AUTO_SOF  );  // 全速且发SOF
	mDelaymS( 1 );
}

/* 设定低速USB设备运行环境 */
void	HostSetLowSpeed( void )  
{
	Write374Byte( REG_USB_SETUP, Read374Byte( REG_USB_SETUP ) | BIT_SETP_USB_SPEED | BIT_SETP_AUTO_SOF );  // 低速且发SOF
	mDelaymS( 1 );
}

 /* 初始化USB主机 */
void	Init374Host( void ) 
{
	Write374Byte( REG_USB_SETUP, 0x00 );
	SetHostUsbAddr( 0x00 );
	Write374Byte( REG_USB_H_CTRL, 0x00 );
	Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG );  // 清所有中断标志
//	Write374Byte( REG_INTER_EN, BIT_IE_TRANSFER );                         // 允许传输完成中断,因为本程序使用查询方式检测USB设备插拔,所以无需USB设备检测中断
	Write374Byte( REG_INTER_EN, BIT_IE_TRANSFER | BIT_IE_DEV_DETECT );     // 允许传输完成中断和USB设备检测中断
	Write374Byte( REG_SYS_CTRL, BIT_CTRL_OE_POLAR );                       // 对于CH374T或者UEN引脚悬空的CH374S必须置BIT_CTRL_OE_POLAR为1
	HostSetBusFree( );                                                     // USB总线空闲
}

/* 获取设备描述符 */
UINT8	GetDeviceDescr( PUINT8 buf )  
{
	UINT8	s, len;
	s = HostCtrlTransfer374( SetupGetDevDescr, buf, &len );                // 执行控制传输
	if ( s == USB_INT_SUCCESS ) {
		UsbDevEndpSize = ( (PUSB_DEV_DESCR)buf ) -> bMaxPacketSize0;      // 端点0最大包长度,这是简化处理,正常应该先获取前8字节后立即更新UsbDevEndpSize再继续
		if ( len < ( (PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL ) s = USB_INT_BUF_OVER;  // 描述符长度错误
	}
	return( s );
}

/* 获取配置描述符 */
UINT8	GetConfigDescr( PUINT8 buf )  
{
	UINT8	s, len,i,c,j;
	UINT8	BufLogDescr[ sizeof( SetupGetCfgDescr ) ] ;

	s = HostCtrlTransfer374( SetupGetCfgDescr, buf, &len );    // 执行控制传输
	if ( s == USB_INT_SUCCESS ) 
    {
		for(i=0;i!=len;i++)
			printf("%02x ",(unsigned short)buf[i]);
		printf("\n");
		if ( len < ( (PUSB_SETUP_REQ)SetupGetCfgDescr ) -> wLengthL ) s = USB_INT_BUF_OVER;  // 返回长度错误
		else 
        {
			memcpy ( BufLogDescr, SetupGetCfgDescr, sizeof( SetupGetCfgDescr ) );
			( (PUSB_SETUP_REQ)BufLogDescr ) -> wLengthL = ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL;  // 完整配置描述符的总长度
			s = HostCtrlTransfer374( BufLogDescr, buf, &len );   // 执行控制传输
			if ( s == USB_INT_SUCCESS ) 
            {
//简单分析配置描述符,获取端点地址,这里只处理一个端点的情况
		        for ( i = 0; i < ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL; i ++ ) printf( "%02X ", (UINT16)( buf[i] ) );  //配置描述符
		        printf( "\n" );
                for(i=0;i<( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL;i++) 
                {
                    if((buf[i]==0x09)&&(buf[i+1]==0x21)&&(buf[i+6]==0x22))  hid_des_leng=buf[i+7];    //获取报告描述符的长度         
                }
                printf("hid_des_leng=%02x\n",(unsigned short)hid_des_leng);
                endp_out_addr=endp_in_addr=0;endp_num=0;
                for(i=0;i<( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL;i++) 
                {
                    if((buf[i]==0x09)&&(buf[i+1]==0x04)&&(buf[i+5]==0x03)&&(buf[i+7]==0x01)||(buf[i+7]==0x02))  //接口描述符为HID的鼠标、键盘   
                    { 
	                    for(j=0;j<( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL-i;j++) 
                        {
	                        if((buf[i+j]==0x07)&&(buf[i+j+1]==0x05)&&(buf[i+j+3]==0x03))   c=buf[i+j+2];        //判断是否为中断端点
	                        if ( c&0x80 )    endp_in_addr=c&0x0f;         // IN端点的地址                                
							    else                                      // OUT端点 
                                {
								    endp_out_addr=c&0x0f;
							    }
                            if((endp_out_addr!=0)||(endp_in_addr!=0))   break;                                       
	                    }
                    }
                    if((endp_out_addr!=0)||(endp_in_addr!=0))   break;           
                }
                printf("endp_in_addr=%02x\n",(unsigned short)endp_in_addr);
                printf("endp_out_addr=%02x\n",(unsigned short)endp_out_addr);
			}
		}
	}
	return( s );
}

/* 设置USB设备地址 */
UINT8	SetUsbAddress( UINT8 addr )  
{
	UINT8	s;
	UINT8	BufSetAddr[ sizeof( SetupSetUsbAddr ) ] ;
	memcpy ( BufSetAddr, SetupSetUsbAddr, sizeof( SetupSetUsbAddr ) );
	( (PUSB_SETUP_REQ)BufSetAddr ) -> wValueL = addr;        // USB设备地址
	s = HostCtrlTransfer374( BufSetAddr, NULL, NULL );       // 执行控制传输
	if ( s == USB_INT_SUCCESS ) {
		SetHostUsbAddr( addr );                              // 设置USB主机当前操作的USB设备地址
	}
	mDelaymS( 3 );                                           // 等待USB设备完成操作
	return( s );
}

/* 设置USB设备配置 */
UINT8	SetUsbConfig( UINT8 cfg )  
{
	UINT8	BufSetCfg[ sizeof( SetupSetUsbConfig ) ] ;
	memcpy ( BufSetCfg, SetupSetUsbConfig, sizeof( SetupSetUsbConfig ) );
	( (PUSB_SETUP_REQ)BufSetCfg ) -> wValueL = cfg;          // USB设备配置
	return( HostCtrlTransfer374( BufSetCfg, NULL, NULL ) );  // 执行控制传输
}

/* 设置Idle */
UINT8  Set_Idle( )    
{
	UINT8  s;
	s=HostCtrlTransfer374(SetupSetidle,NULL,NULL);
	return s;
}

/* 获取报表描述符 */
unsigned char Get_Hid_Des(unsigned char *p)//获取报表描述符
{
	unsigned char s;
//	leng=SetupGetHidDes[0x06]-0x40;//报表描述符的长度在发送数据长度的基础上减去0X40
	unsigned char buffer[8];
	memcpy ( buffer, SetupGetHidDes, 8 );
	buffer[0x06] = hid_des_leng+0x40;
	s=HostCtrlTransfer374(buffer,p,&buffer[0x06]);
	return s;
}


/* 设置报表 */
UINT8  Set_Report(unsigned char *p)
{
	UINT8  s,l=1;
	s=HostCtrlTransfer374(SetupSetReport,p,&l);            //实际的数据可以写别的数据,这个你可以用计算机抓下数据在发下去
	return s;
}

/* 为printf和getkey输入输出初始化串口 */
void	mInitSTDIO( )
{
	SCON = 0x50;
	PCON = 0x80;
	TMOD = 0x20;
	TH1 = 0xf3;                                           //24MHZ, 9600                          
	TR1 = 1;
	TI = 1;
}


int	main( void ) 
{
	UINT8	i, s,close_bit_flag=0;
	UINT8   idata	buf[80];            //由于报告描述符大小不定,缓冲区的大小最好定义大些
//	P1&=0xF8;                           // 如果在U盘文件读写模块上试用本程序必须加上本行
	AUXR |= 0x02;
	mDelaymS( 50 );                     // 等待CH374复位完成
	CH374_PORT_INIT( );                 // CH374接口初始化 
	mInitSTDIO( );                      // 为了让计算机通过串口监控演示过程 
	for(i=0;i!=64;i++)
    {
		s=Read374Byte(i);
		printf("%02x ",(unsigned short)s);
	}
	printf("\n");
	printf( "Start CH374 Host\n" );
	Init374Host( );                     // 初始化USB主机
	while ( 1 ) 
    {
		HostSetBusFree( );              // 设定USB主机空闲
		while ( 1 )
        {
			if ( Query374Interrupt( ) ) HostDetectInterrupt( );  // 如果有USB主机中断则处理
			if ( Query374DeviceIn( ) ) break;                    // 有USB设备
		}
		mDelaymS( 250 );                                         // 由于USB设备刚插入尚未稳定,故等待USB设备数百毫秒,消除插拔抖动
		if ( Query374Interrupt( ) ) HostDetectInterrupt( );      // 如果有USB主机中断则处理

		printf( "Reset Device\n" );
		HostSetBusReset( );                                      // USB总线复位
		for ( i = 0; i < 100; i ++ )                             // 等待USB设备复位后重新连接
        {
			if ( Query374DeviceIn( ) ) break;                    // 有USB设备
			mDelaymS( 1 );
		}
		if ( Query374Interrupt( ) ) HostDetectInterrupt( );      // 如果有USB主机中断则处理
		if ( Query374DeviceIn( ) )                               // 有USB设备
        {  
			if ( Query374DevFullSpeed( ) )
            {
				printf( "Start Full-Speed Device\n" );
				HostSetFullSpeed( );                             // 检测到全速USB设备
			}
			else 
            {
				printf( "Start Low-Speed Device\n" );
				HostSetLowSpeed( );                             // 检测到低速USB设备
				LOW_SPEED_BIT=1;
			}
		}
		else 
        {
			continue;                                           // 设备已经断开,继续等待
		}
		mDelaymS( 50 );
		close_bit_flag=0;
		printf( "GetDeviceDescr: " );
		s = GetDeviceDescr( buf );                             // 获取设备描述符
		printf("device_status=%02x \n",(unsigned short)s);
		if ( s != USB_INT_SUCCESS )
        {
			goto WaitDeviceOut;                                // 终止操作,等待USB设备拔出
		}
		for ( i = 0; i < ( (PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL; i ++ ) printf( "%02X ", (UINT16)( buf[i] ) );
		printf( "\n" );
		s = SetUsbAddress( 0x02 );                             // 设置USB设备地址
		printf("address_status=%02x\n",(unsigned short)s);
		if ( s != USB_INT_SUCCESS ) 
        {
			goto WaitDeviceOut;                                // 终止操作,等待USB设备拔出
		}
		s = GetConfigDescr( buf );                             // 获取配置描述符
		printf("config_status=%02x\n",(unsigned short)s);
		if ( s != USB_INT_SUCCESS ) 
        {
			goto WaitDeviceOut;                                // 终止操作,等待USB设备拔出
		}

// 分析配置描述符,获取端点数据/各端点地址/各端点大小等,更新变量endp_addr和endp_size等 
		s = SetUsbConfig( ( (PUSB_CFG_DESCR)buf ) -> bConfigurationValue );   // 设置USB设备配置
		if ( s != USB_INT_SUCCESS ) 
        {
//	     	printf( "ERROR = %02X\n", (UINT16)s );
			goto WaitDeviceOut;                               // 终止操作,等待USB设备拔出
		}
		else 	printf( "SetUsbConfig_success\n" );

//-------------------------以下进行HID类的简单操作-----------------------------------------------------------
        printf("Set_Idle\n");
		s=Set_Idle( );                                        //设置IDLE,这个步骤是按照HID类的协议来做的
		if(s!=USB_INT_SUCCESS)
        {
			printf("Set_Idle_Err=%02x\n",(unsigned short)s);
            if(s&0x0f==USB_INT_RET_STALL)  goto next_operate1; //返回STALL可能本身不支持
		}
		else printf("Set_idle success\n");
next_operate1:
        printf("Get_Hid_Des\n");
		s=Get_Hid_Des(buf);                                  // 获取报表描述符描述符
		if(s==USB_INT_SUCCESS)
        {
			printf("HID_Desc: ");
			for(i=0;i!=hid_des_leng;i++)  printf("%02x ",(unsigned short)buf[i]);
			printf("\n");
		}
		else
        {
			goto WaitDeviceOut;                             //出错退出
		}

        printf("Set_Report \n");                            //对于键盘发Set_Report来点亮灯,对于鼠标则不需要这一步
		buf[0]=0x01;
		s=Set_Report(buf);                                 //设置报表
		if(s==USB_INT_SUCCESS)   
        {
             printf("Set_Report success\n");
        }
		else
        { 
              printf("Set_Report Err=%02x\n",(unsigned short)s);      //设置报告出错
              if(s&0x0f==USB_INT_RET_STALL)  goto next_operate2;      //返回STALL可能本身不支持		  
		}
next_operate2:

// 下面开始读取数据 ( 实际在读取数据的时候,要先发送中断端点的令牌来读取数据,接着才能获取到数据 )
		tog1=FALSE;                                  //开始取DATA0
		while(1)
        {
			s=Interrupt_Data_Trans(buf);
//          printf("s:%x \n",(unsigned short)s);
			if(s==USB_INT_SUCCESS)
            {
				for(i=0;i!=8;i++)	printf("%02x ",(unsigned short)buf[i]);
				printf("\n");
			}
			else if(s==USB_INT_DISCONNECT)            //  这个是为了知道设备拔出产生的中断状态
            {
				close_bit_flag=1;
				break;				
			}
		}
WaitDeviceOut:                                       // 等待USB设备拔出
		printf( "Wait Device Out\n" );
	    if(close_bit_flag==0){
		    while ( 1 )
            {
			     if ( Query374Interrupt( ) ) HostDetectInterrupt( );  // 如果有USB主机中断则处理
			     if ( Query374DeviceIn( ) == FALSE ) break;           // 没有USB设备
		    }
	    }
		mDelaymS( 100 );                                             // 等待设备完全断开,消除插拔抖动
    }
}

⌨️ 快捷键说明

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