USB设备,鼠标,键盘使用CH372,CH375,进行模拟的历程

来源:互联网 发布:方舟生存进化淘宝 编辑:程序博客网 时间:2024/06/05 07:47

开始打算做一个关于USB设备共享的机器,多台电脑共享一个鼠标键盘;

模拟鼠标或者键盘,必须使用外部固件模式,内置固件只负责信息数据的传输,所以不得不选择并口控制或者SPI的方式,接下来就是了解基本的USB协议的尝试,懂得USB设备与PC机进行信息握手的过程,懂得什么是SETUP,什么是设备描述符,什么是配置描述符,


以下是部分关于CH372模拟HID鼠标的程序:使用STM32


static void CH376_DATA_DIR_IN( );


BOOLEAN  CH375ACT;
BOOLEAN CH375FLAGERR; //错误清0
BOOLEAN CH375CONFLAG;




BOOLEAN IsBusying;


unsigned char buf[64];
typedef union _REQUEST_PACK{
unsigned char  buffer[8];
struct{
unsigned char bmReuestType;     //标准请求字
unsigned char bRequest;   //请求代码
unsigned int     wValue;//特性选择高
unsigned int     wIndx;//索引
unsigned int     wLength;//数据长度
}r;
} mREQUEST_PACKET, *mpREQUEST_PACKET;
//设备的描述符包含设备描述符、配置描述符、字符描述符;识别描述符的类型就是根据它的第二个字节值来识别;
//一般情况下设备描述符不需要用户去配置,因为可以直接用软件从现有的设备中读取;同种设备的描述符都相同;如优盘描述符都一样
/*以下是设备描述符,(为什么是这些数值,可查阅USB协议书籍)*/
unsigned char DevDes[]={
0x12, //描述符长度,长度1个字节,值18
    0x01, //描述符类型,长度1个字节,值:1-设备描述符,2-配置描述符,3-字符串描述符,4-接口描述符,5-端点描述符
    0x10, //USB规范版本信息,长度2个字节,BCD码:USB1.1-0110、USB2.0-0200
    0x01,
    0x00, //类别码,长度1个字节,数值0X01~0XFE为USB定义的类,如打印机等;00-USB设备的各个接口属于不同的类,由接口描述符提供类的值;02-通信类;03-HID类;09-集线器类;
               //DC-用于诊断用途的设备类;e0-无线通信设备类;XFF是由厂商定义的设备的类别;
    0x00,            //子类别码,长度1个字节,类别码为0,则也必须为0;USB协会指定;0xff-厂商自定义
0x00,            //协议代码,长度1个字节,USB协会指定;0-不使用任何设备类协议,类别码为0时,必须为0;0xff-厂商自定义
    0x08, //端点0的最大信息包大小,长度1字节,低速设备-8,全速设备-8/16/32/64,高速设备-64
    0x87, //厂商ID,VID长度2字节,USB协会分配给不同的厂商,操作系统会根据VID和PID加载驱动
    0x88,
    0x11, //产品ID,PID长度2字节,厂商定义,操作系统加载设备驱动与其有关
    0x00,
    0x00, //设备版本信息,长度2字节,厂商定义,操作系统加载驱动与其有关
    0x01,
    0x01, //描述厂商的字符串描述符的索引值,长度1字节,0-没有厂商字符串;主机获取设备描述符时将其放入WVALUE中,以选择不同的字符串;具体字符串内容在字符串描述符中定义
    0x02,            //描述产品的字符串描述符的索引值,长度1字节,0-没有产品字符串;第一次插入USB设备时,在系统桌面右下角弹出的提示信息就是产品字符串
    0x03,            //描述设备的序列号的字符串描述符的索引值,长度1字节,0-没有序列号描述符
    0x01, //设备支持的配置的数目,长度1字节,一个设备可能有多种配置,每种配置有一个配置描述符,主机通过发送设备配置来选择某一配置
};
//配置描述符;包括配置描述符、接口描述符、端点描述符,HID设备还包括HID描述符;
unsigned char   ConDes[]={
//配置描述符
0x09, //描述符大小
    0x02, //描述符类型02-配置描述符
    0x22, //此配置传回所有数据大小,包括配置描述符、接口描述符、类描述符、端点描述符
    0x00, //
    0x01, //接口数
    0x01, //配置值
    0x00, //描述改配置的字符串的索引,0-没有配置描述字符串
    0x80, //设备属性D7保留位 1,D6:0-总线供电 D5:1-支持远程唤醒 D4-D0:保留位 0000
    0x40, //设备需要的电流,单位为2ma
//接口描述符
    0x09, //描述符大小
    0x04, //描述符类型04-接口描述符
    0x00, //接口编号
    0x00, //接口备用编号
    0x01, //支持的端点数 0-没有非零端点 使用默认控制端点
    0x03, //类别码
    0x01, //子类别码 0-无引导的HID设备 1-有引导的HID设备
    0x02, //协议码子类别码为0时必须也为0 子类别吗为1时 1-键盘 2-鼠标
    0x00, //描述该接口的字符串的索引,0-没有
//HID描述符
0x09,    //描述符长度
0x21,    //描述符类型 0x21-HID
0x10,    //HID协议版本
0x01,
0x21,    //国家码,美式键盘33
0x01,    //下级描述符数量,至少为1,下级描述符即报告描述符或物理描述符
0x22,    //下级描述符类型,0x22-报告描述符 0x23-物理描述符
0x34,    //下级描述符长度,2字节,
0x00,
//端点描述符
    0x07,    //描述符长度
    0x05,    //描述符类型 5-端点描述符
    0x81,    //端点地址,D7-传输方向 1-IN 0-OUT,D3-D0:端点号,D6-D4:保留值
    0x03,    //端点类型;D1-D0:0-控制传输 1-等时传输 2-批量传输 3-中断传输;非等时传输D7-D2保留值 0,等时传输D7-D6保留,D5-D4用途 0-数据端点 1反馈端点 2-暗含反馈的数据端点 D3-D2同步类型0 无同步1-异步 2适配 3 同步
    0x10,    //最大数据包长度
    0x00,    //
    0x0a,    //查询间隔
};
//字符串描述符,报表描述符;
//作键盘设备时,报表描述符描述了数据格式;如键盘,则必须发送8个字节的数据;其中第3个字节是要在
//各种文本里显示的数据(如WORD文挡);其余字节全为0;
unsigned char Hid_des[]={
0x05, 0x01, //全局项目,表示用途页为桌面设备
0x09, 0x02,  //局部项目,表示用途为鼠标
0xa1, 0x01,  //开集合,主项目,应用集合
    0x09, 0x01,  //局部项目,指针设备
    0xa1, 0x00,  //开集合,主项目,物理集合
        0x05, 0x09, //全局项目,用途为按键
        0x19, 0x01, //局部项目,用途最小值为1,鼠标左键
        0x29, 0x03, //局部项目,用途最大值为3,鼠标中键
        0x15, 0x00, //全局项目,返回数据的逻辑值的最小值为0
        0x25, 0x01, //全局项目,返回数据的逻辑值的最大值为1
        
0x95, 0x03, //全局项目,返回值的数据域数量有3个
        0x75, 0x01, //全局项目,返回值每个数据域长度1位
        0x81, 0x02, //主项目,说明有3个长度为1的数据域做输入,属性为DATA VAR ABS,ADAT表示数据可变动,VAR表示这些数据域是独立的变量,即每个数据域表示一个意思,ABS表示他们是绝对值。长度由前述的两个全局项目定义,
        
0x95, 0x01, //全局项目,数据域数量有1个
        0x75, 0x05, //全局项目,数据域长度为5位
        0x81, 0x03, //主项目,说明有一个长度为5位的数据域做输入,属性为CNST VAR ABS,CNST表示常量,目的是补齐8位,因为前面只有3位
        
0x05, 0x01, //全局项目,用途是通用桌面
        0x09, 0x30, //局部项目,用途X轴
        0x09, 0x31, //局部项目,用途Y轴
        0x09, 0x38, //局部项目,用途为滚轮,即中键

        0x15, 0x81, //全局项目,返回值的逻辑值的最大和最小值分别为-127和127;
        0x25, 0x7f,
       
0x75, 0x08, //全局项目,每个数据域的长度为8位
        0x95, 0x03, //全局项目,数据域的个数为3个
        0x81, 0x06, //全局项目,说明前述的3个数据域为输入,属性为DATA VAR REL,DATA、VAR前面已经讲过,REL表示这些值是相对值,即鼠标移动时,发送的只是变化量
    0xc0, //关闭集合
0xc0 //关闭集合
         };
 
unsigned char LangDes[]={0x04,0x03,0x09,0x04}; //语言描述符
unsigned char SerDes[] ={0x16,0x03,0xDD,0x84,0xD7,0x65,0x4C,0x5D,0x65,0x51,0x0F,0x5F,0x48,0x00,0x49,0x00,
0x44,0x00,0x20,0x9F,0x07,0x68};


unsigned char  Chan[]={0x16,0x03,0x32,0x00,0x30,0x00,0x30,0x00,0x31,0x00,0x2d,0x00,0x30,0x00,0x37,0x00,0x2d,0x00,0x30,0x00,0x31,0x00};
unsigned char  Chang[] ={0x14,0x03,'L',0,'E',0,'N',0,'C',0,'H',0,'I',0,'M',0,'C',0,'U',0};


unsigned char mVarSetupRequest; //;USB请求码
unsigned char mVarSetupLength; //;后续数据长度
unsigned char * VarSetupDescr;// ;描述符偏移地址
unsigned char buf1[8];
unsigned char VarUsbAddress ;//
unsigned  char  Report_ID=0X01;




unsigned char  UPDATA_FLAG;
mREQUEST_PACKET  request;                                                    


void sys_DATA_IoInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;


    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);


    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


    GPIO_InitStructure.GPIO_Pin = WR_PIN ;
    GPIO_Init(WR_PORT, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = A0_PIN ;
    GPIO_Init(A0_PORT, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = RD_PIN ;
    GPIO_Init(RD_PORT, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = CS_PIN ;
    GPIO_Init(CS_PORT, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin =   CH376_INT1_PIN;
GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IN_FLOATING;
GPIO_Init(CH376_INT1_PORT , &GPIO_InitStructure);
    
     GPIO_SetBits(CS_PORT,CS_PIN);           // CH376_CS = 1;
     GPIO_SetBits(WR_PORT,WR_PIN);           // CH376_WR = 1;
     GPIO_SetBits(RD_PORT,RD_PIN);           // CH376_RD = 1;
     GPIO_ResetBits(A0_PORT,A0_PIN);         // CH376_A0 = 0;
     CH376_DATA_DIR_IN();


}


/***********************************************************************************
****函数名称:不准确的延时20US的函数
****函数作用:
****函数描述:
************************************************************************************/
static void delay20us(void)
{
// unsigned char i;
// for(i=0;i<20;i++);
}
/***********************************************************************************
****函数名称:不准确的延时1mS的函数
****函数作用:
****函数描述:
************************************************************************************/
static void delay1ms(void)
{
// unsigned char m,n;
// for(m=0;m<200;m++)
// for(n=0;n<50;n++);
}
/***********************************************************************************
****函数名称:不准确的延时50mS的函数
****函数作用:
****函数描述:
************************************************************************************/
static void delay50ms(void)
{
// unsigned char m,n;
// for(m=0;m<200;m++)
// for(n=0;n<250;n++);
}


static void CH376_DATA_DIR_IN( )


{
    GPIO_InitTypeDef GPIO_InitStructure;


    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);


    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


    GPIO_InitStructure.GPIO_Pin =   D0_PIN|D1_PIN|D2_PIN|D3_PIN|D4_PIN|D5_PIN|D6_PIN|D7_PIN;  //OE0:PA7 OE1:PA15  OE2:PA8
    GPIO_Init(D0_PORT, &GPIO_InitStructure);
    
}




static void CH376_DATA_DIR_OUT( )


{
    
    GPIO_InitTypeDef GPIO_InitStructure;
    
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);


    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


    GPIO_InitStructure.GPIO_Pin =   D0_PIN| D1_PIN|D2_PIN|D3_PIN|D4_PIN|D5_PIN|D6_PIN|D7_PIN;  //OE0:PA7 OE1:PA15  OE2:PA8
    GPIO_Init(D0_PORT, &GPIO_InitStructure);


}




static uint8_t  CH376_DATA_DAT_IN(void)
{
    u16 cmd1;  uint8_t cmd;  
    cmd1=GPIO_ReadInputData(D0_PORT);    
    cmd=(GPIO_ReadInputData(D0_PORT)&0xff00)>>8;    
delay50ms();
    return(cmd);
    
    
    
}


static void  CH376_DATA_DAT_OUT(u16 cmd)
{


    u16 Temp;   
    Temp=GPIO_ReadOutputData(D0_PORT);  
delay50ms();    
    GPIO_Write(D0_PORT,(Temp&0x00ff)|(((u16)cmd)<<8));


      
}


/*******************************************************************************
* Function Name  : CH376_WR_CMD_PORT  串口发送命令前需要发送57 ab同步码
* Description    : 写CH376命令子函数
* Input          : - cmd: 8位命令码
* Output         : None
* Return         : None
* Attention : None
*******************************************************************************/


void CH376_WR_CMD_PORT( u16  cmd )
{


    delay20us();
    CH376_DATA_DIR_OUT( );


    CH376_DATA_DAT_OUT(cmd);


    GPIO_SetBits(A0_PORT,A0_PIN);         // CH376_A0 = 1;
     GPIO_SetBits(RD_PORT,RD_PIN);           // CH376_RD =1;


    GPIO_ResetBits(CS_PORT,CS_PIN);           // CH376_CS = 0;


    GPIO_ResetBits(WR_PORT,WR_PIN);           // CH376_WR = 0;






    GPIO_ResetBits(CS_PORT,CS_PIN);           // CH376_CS = 0;
    delay50ms();


    GPIO_SetBits(WR_PORT,WR_PIN);           // CH376_WR =1;




    GPIO_SetBits(CS_PORT,CS_PIN);           // CH376_CS = 1;




    GPIO_ResetBits(A0_PORT,A0_PIN);         // CH376_A0 = 0;








    CH376_DATA_DAT_OUT(0xffff);
}




/*******************************************************************************
* Function Name  : CH376_WR_DAT_PORT
* Description    : 写CH376数据子函数
* Input          : - dat: 8位数据
* Output         : None
* Return         : None
* Attention : None
*******************************************************************************/
void CH376_WR_DAT_PORT( u16 dat )
{
    CH376_DATA_DIR_OUT( );  /* 设置并口方向为输出 */
delay20us();
    CH376_DATA_DAT_OUT( dat );  /* 向CH376的并口输出数据 */




    GPIO_ResetBits(A0_PORT,A0_PIN);            // CH376_A0 = 0;


    GPIO_ResetBits(CS_PORT,CS_PIN);           // CH376_CS = 0;


    GPIO_ResetBits(WR_PORT,WR_PIN);           // CH376_WR = 0;


delay20us();
    GPIO_ResetBits(CS_PORT,CS_PIN);           // CH376_CS = 0;
delay20us();
    GPIO_SetBits(WR_PORT,WR_PIN);           // CH376_WR =1;




    GPIO_SetBits(CS_PORT,CS_PIN);           // CH376_CS = 1;




    CH376_DATA_DAT_OUT(0xffff);  /* 禁止数据输出 */
    


}


/*******************************************************************************
* Function Name  : CH376_RD_DAT_PORT
* Description    : 读CH376数据子函数
* Input          : None
* Output         : None
* Return         : 8位数据
* Attention : 等待读到数据
*******************************************************************************/
uint8_t CH376_RD_DAT_PORT( void )
{
    
    
    uint8_t mData;
    // mDelay0_5uS( );  /* 确保读写周期大于0.6uS */
    
     CH376_DATA_DIR_OUT( );  /* 设置并口方向为输出 */
    CH376_DATA_DAT_OUT(0xffff);  /* 禁止数据输出 */
    GPIO_ResetBits(A0_PORT,A0_PIN);            // CH376_A0 = 0;
    
    CH376_DATA_DIR_IN( );  /* 设置并口方向为输入 */
    CH376_DATA_DAT_OUT(0x0000);  /* 禁止数据输出 */


    GPIO_ResetBits(CS_PORT,CS_PIN);           // CH376_CS = 0;


    GPIO_ResetBits(RD_PORT,RD_PIN);           // CH376_WR = 0;


    GPIO_ResetBits(CS_PORT,CS_PIN);           // CH376_CS = 0;
delay50ms();
delay20us();
    mData = CH376_DATA_DAT_IN( );  /* 从CH376的并口输入数据 */


    GPIO_SetBits(RD_PORT,RD_PIN);           // CH376_RD =1;
delay50ms();
    GPIO_SetBits(CS_PORT,CS_PIN);           // CH376_CS = 1;
         CH376_DATA_DIR_OUT( );  /* 设置并口方向为输出 */
    CH376_DATA_DAT_OUT(0xffff);  /* 禁止数据输出 */


    return( mData );
    
    
}








void device_376(void)
{
    
    sys_DATA_IoInit();
    sysReset();
        CH376_WR_CMD_PORT( CMD_SET_USB_MODE );
CH376_WR_DAT_PORT( 0);  
    delay50ms();
    CH376_WR_CMD_PORT( CMD_SET_USB_MODE );
CH376_WR_DAT_PORT( 1);  /* 设置为使用内置固件的USB设备方式 */
for ( ;; ) {  /* 等待操作成功,通常需要等待10uS-20uS */
if ( CH376_RD_DAT_PORT( )==CMD_RET_SUCCESS ) break;
}




}




void IO_cfg()            //GPIO初始化
{
   GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量




   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;     //选择引脚2 3 5 作为中断信号输入端
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                   //选择输入模式为浮空输入
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                       //输出频率最大50MHz
   GPIO_Init(GPIOA,&GPIO_InitStructure);                                   //设置PA.2 /PA.3 /PA.5
}




void EXTIX_Init(void)
{


    
    
       NVIC_InitTypeDef NVIC_InitStructure;     //定义结构体变量


   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);    //选择中断分组2,3个中断源,需2bit进行优先级设置
                                                      //高两位用于设置抢占式 优先级;
     //低两位用于设置响应式 优先级
   
   NVIC_InitStructure.NVIC_IRQChannel = EXTI_Line0;     //选择中断通道2
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //抢占式中断优先级设置为0
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         //响应式中断优先级设置为0
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能中断


   NVIC_Init(&NVIC_InitStructure);


   




}




void EXTI_cfg()      //将相应的IO口与中断线路进行连接
{
   EXTI_InitTypeDef EXTI_InitStructure;      //定义结构体变量


   EXTI_ClearITPendingBit(EXTI_Line0);      //清空中断标志   PA.2 中断口




   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //选择中断管脚PA.2 PA.3 PA.5




   EXTI_InitStructure.EXTI_Line = EXTI_Line0;  //选择中断线路2 3 5
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;                   //设置为中断请求,非事件请求
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;    //设置中断触发方式为上下降沿触发
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;                         //外部中断使能


   EXTI_Init(&EXTI_InitStructure);
}




void ioInterruptSet(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;

EXTI_ClearITPendingBit(EXTI_Line0);


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;         
  GPIO_Init(GPIOA,&GPIO_InitStructure);               


  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);  // 
EXTI_InitStructure.EXTI_Line = EXTI_Line0;                   //选择中断线路0
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;          //设置为中断请求,非事件请求
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;      //下降沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                    //外部中断使能
  EXTI_Init(&EXTI_InitStructure);      

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);           //选择中断分组2
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;          //选择中断通道2
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中断优先级设置为0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //响应式中断优先级设置为0
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //使能中断
  NVIC_Init(&NVIC_InitStructure);
}




///***********************************************************************************
//****函数名称:端点1数据上传函数
//****函数作用:
//****函数描述:
//************************************************************************************/
//void ch372ep1up()
//{
// unsigned char i;
// CH375_WRCMD(CMD_WR_USB_DATA5);
// CH375_WRDAT(0x04);
// for(i=0;i<4;i++)
// CH375_WRDAT(MouseData[i]);
// IsBusying=1;
//
//}
/***********************************************************************************
****函数名称:端点0数据上传函数
****函数作用:
****函数描述:
************************************************************************************/
void mCh375Ep0Up()
{
unsigned char i,len;
if(mVarSetupLength)
{ //长度不为0传输具体长度的数据
if(mVarSetupLength<=8)
{
len=mVarSetupLength;
mVarSetupLength=0;
        } //长度小于8则长输要求的长度
else
{
len=8;
mVarSetupLength-=8;
}                        //长度大于8则传输8个,切总长度减8
   CH376_WR_CMD_PORT(CMD_WR_USB_DATA3);//发出写端点0的命令
        CH376_WR_DAT_PORT(len);//写入长度
    for(i=0;i!=len;i++)
{
CH376_WR_DAT_PORT(request.buffer[i]);              //循环写入数据
}


    }
else
{
CH376_WR_CMD_PORT(CMD_WR_USB_DATA3);//发出写端点0的命令
CH376_WR_DAT_PORT(0);                  //上传0长度数据,这是一个状态阶段


}

}
/***********************************************************************************
****函数名称:描述符复制函数
****函数作用:
****函数描述:
************************************************************************************/
void mCh375DesUp()
{
unsigned char k;        
for (k=0; k!=8; k++ ) 
{
         request.buffer[k]=*VarSetupDescr;   //依次复制8个描述符,
         VarSetupDescr++;
    }
}




/***********************************************************************************
****函数名称:外部中断0的响应函数
****函数作用:通过判断375的终端类型值进行相应的处理
****函数描述:
************************************************************************************/
void EXTI0_IRQHandler(void)
{
unsigned char i,temp,length,len;
unsigned char c1;
   // ;//SendStr("......进入中断......\r\n");
//unsigned char   *pBuf;
//unsigned char   mBuf[64];
    EXTI_ClearITPendingBit(EXTI_Line0);  //清空中断标志位,防止持续进入中断
CH376_WR_CMD_PORT(CMD_GET_STATUS);  /* 向CH375芯片发送获取中断状态的命令;CMD_GET_STATUS为命令码,数值大小在CH375INC.H 头文件中*/
temp =CH376_RD_DAT_PORT();  /* 读取中断状态 */


switch(temp)                                  //判断中断类型(状态),具体区分请见375头文件中的定义
{
   case USB_INT_EP0_SETUP:
;//SendStr("......接收到SETUP......\r\n");
CH376_WR_CMD_PORT(CMD_RD_USB_DATA);
length=CH376_RD_DAT_PORT();
for(i=0;i<length;i++)
{
request.buffer[i]=CH376_RD_DAT_PORT();
//SendHex(request.buffer[i]);
;//SendStr("\r\n");
}
if(length==8)//如果长度是8
{
mVarSetupLength=request.buffer[6]&0x7f;//控制传输的数据长度最长是128字节
if(request.r.bmReuestType&0x40)//6-5=10厂商请求
;//SendStr("......厂商请求......\r\n");
if(request.r.bmReuestType&0x20)//6-5=01类请求
;//SendStr("......类请求......\r\n");
if(!(request.r.bmReuestType&0x60))//6-5=00标准请求,一共11中标准请求
{
mVarSetupRequest=request.r.bRequest;//将标准请求保存
   switch(request.r.bRequest)//判断标准请求
   {
   case DEF_USB_GET_CONFIG://获取配置
    ;//SendStr("......获取配置......\r\n");
   break;
   case DEF_USB_GET_DESCR://获取描述符
   ;//SendStr("......获取描述符......\r\n");
   switch(request.buffer[3])//判断描述符的类型
   {
   case 1://设备描述符
   ;//SendStr("......请求设备描述符......\r\n");
   VarSetupDescr=DevDes;
   break;
   case 2://配置描述符
   ;//SendStr("......请求配置描述符......\r\n");
VarSetupDescr=ConDes;
   break;
   case 3://字数串描述符
    ;//SendStr("......请求字符串描述符......\r\n");
//VarSetupDescr=
if(request.buffer[4]==0)
{
;//SendStr("......请求语言描述符......\r\n");
VarSetupDescr=LangDes;
mVarSetupLength=4;
           }
if(request.buffer[2]==1)
{
;//SendStr("......请求厂商字符串......\r\n");
VarSetupDescr=Chang;
mVarSetupLength=0x14;
}
if (request.buffer[2]==2)
{
;//SendStr("......请求产品字符串......\r\n");
VarSetupDescr=SerDes;
mVarSetupLength=0x16;
}
if(request.buffer[2]==3)
{
;//SendStr("......请求产品序列号......\r\n");
VarSetupDescr=Chan;
mVarSetupLength=0x16;
}
   break;
   case 4://接口描述符
    ;//SendStr("......请求接口描述符......\r\n");
    break;
   case 5://端点描述符
    ;//SendStr("......请求端点描述符......\r\n");
    break;
case 0x22://获取HID报告描述符
;//SendStr("......请求HID......\r\n");
VarSetupDescr=Hid_des;
mVarSetupLength=0x34;
break;
default://没有定义
   ;//SendStr("......不支持的描述符请求......\r\n");
   break;
    }
   mCh375DesUp();
   break;
    case DEF_USB_GET_INTERF://获取接口
   ;//SendStr("......获取接口......\r\n");
   break;
    case DEF_USB_GET_STATUS://获取状态
    ;//SendStr("......获取状态......\r\n");
    break;
   case DEF_USB_SYNC_FRAME://同步帧
   ;//SendStr("......同步帧......\r\n");
   break;
case DEF_USB_CLR_FEATURE://清除特性
;//SendStr("......清除特性......\r\n");
break;
case DEF_USB_SET_ADDRESS://设置地址
;//SendStr("......设置地址......\r\n");
VarUsbAddress=request.buffer[2];
break;
case DEF_USB_SET_CONFIG://设置配置
;//SendStr("......设置配置......\r\n");
break;
case DEF_USB_SET_DESCR://设置描述
;//SendStr("......设置描述......\r\n");
CH375CONFLAG=0;
if(request.buffer[2]!=0)
{
CH375CONFLAG=1;
}
break;
case DEF_USB_SET_FEATURE://设置特性
;//SendStr("......设置特性......\r\n");
break;
case DEF_USB_SET_INTERF://设置接口
;//SendStr("......设置接口......\r\n");
break;
   default :
   ;//SendStr("......不支持的标准请求......\r\n");
   CH376_WR_CMD_PORT (CMD_UNLOCK_USB);//释放缓冲区
   break;
   }
}

}
mCh375Ep0Up();
break;
case USB_INT_EP0_OUT:
CH376_WR_CMD_PORT(CMD_RD_USB_DATA);//发出读数据命令
if(length=CH376_RD_DAT_PORT())
{ //长度为0跳出
for(len=0;len!=length;len++)
c1=CH376_RD_DAT_PORT();//取出下传数据
}
break;
case USB_INT_EP0_IN:
;//SendStr("......端点0IN......\r\n");
if(mVarSetupRequest==DEF_USB_GET_DESCR)
{
mCh375DesUp();
mCh375Ep0Up();
;//SendStr("......描述符上传成功......\r\n");
}
else 
if(mVarSetupRequest==DEF_USB_SET_ADDRESS)
   { //设置地址
   CH376_WR_CMD_PORT(CMD_SET_USB_ADDR);
   CH376_WR_DAT_PORT(VarUsbAddress);//设置USB地址,设置下次事务的USB地址
   }
CH376_WR_CMD_PORT(CMD_UNLOCK_USB);//释放缓冲区
break;
case USB_INT_EP1_OUT:
;//SendStr("......端点1OUT......\r\n");
break;
case USB_INT_EP1_IN:
;//SendStr("......端点1IN......\r\n");
CH376_WR_CMD_PORT(CMD_UNLOCK_USB);
IsBusying=0;
break;
case USB_INT_EP2_OUT:
;//SendStr("......端点2OUT......\r\n");
break;
case USB_INT_EP2_IN:
;//SendStr("......端点2IN......\r\n");
break;
case USB_INT_USB_SUSPEND:
;//SendStr("......USB挂起......\r\n");
break;
default:
;//SendStr("......总线复位......\r\n");
if((temp&0x03)==0x03)
{ //总线复位
CH375FLAGERR=0;            //错误清0
CH375CONFLAG=0;        //配置清0
mVarSetupLength=0;
}
CH376_WR_CMD_PORT (CMD_UNLOCK_USB);//释放缓冲区
break;
break;

}
}

0 0