大師,
?
???? 目前有個(gè)項(xiàng)目用STC12的單片機(jī),11.0592晶振,CH376S模塊(網(wǎng)購),USB鍵盤。想通過串口獲取USB鍵盤或USB激光掃描槍的數(shù)據(jù)。使用了論壇的程序,但不成功。
?
論壇里是總線方式,我改了三個(gè)用串口讀寫的函數(shù)。
?
我用串口1與USB通信,用串口2 顯示數(shù)據(jù)
?
? CH376_WR_CMD_PORT( 0x06 );
?
? CH376_WR_DAT_PORT( 0x55 );
?
? s = CH376_RD_DAT_PORT( );
?
?? SerialPortTwo_Send(s);
?
可以正常串口2輸出0AAH
但后續(xù)點(diǎn)擊鍵盤沒有反應(yīng)。
?
是否仍有其他代碼需要修改,才能正常獲取鍵盤數(shù)據(jù)。
?
代碼如下:
?
?
/****************************************
**? Copyright? (C)? WCH? 1999-2009??? **
**? Web:? http://www.winchiphead.com? **
****************************************
**? USB 1.1 Host Examples for CH376?? **
**? KC7.0@MCS-51????????????????????? **
** ?Version: v1.0???????????????????? **
**? Author: tech14????????????????? ? **
**? Time? : 2009/11/18??????????????? **
****************************************
*/
/* 用CH376操作HID設(shè)備,比如鍵盤,鼠標(biāo),兼容HID復(fù)合設(shè)備*/
?
?
#include
#include
#include
?
#include "CH376INC.H"
?
#include "hid.h"
?
// 獲取設(shè)備描述符
const?? unsigned char code SetupGetDevDescr[] = { 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00 };
// 獲取配置描述符
const?? unsigned char code SetupGetCfgDescr[] = { 0x80, 0x06, 0x00, 0x02, 0x00, 0x00, 0x09, 0x00 };
// 設(shè)置USB地址
const?? unsigned char code SetupSetUsbAddr[] = { 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
// 設(shè)置USB配置
//const unsigned char code SetupSetUsbConfig[] = { 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// SET IDLE
const?? unsigned char code SetupSetidle[]={0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00};???????
// 獲取HID 報(bào)告描述符
const?? unsigned char code SetupGetHidDes[]={0x81,0x06,0x00,0x22,0x00,0x00,0x81,0x00};???
// SET REPORT
const?? unsigned char code SetupSetReport[]={0x21,0x09,0x00,0x02,0x00,0x00,0x01,0x00};????
?
?
//單片機(jī)總線方式操作CH376
#define CH376_CMD_PORT? *(unsigned char volatile xdata *)0xBDF1
#define CH376_DAT_PORT? *(unsigned char volatile xdata *)0xBCF0
?
#define CH376_INT_WIRE?? INT0?????? //定義CH376中斷引腳,可省略;
?
struct _Device_Atti{
? ? UINT8 Device_connect;????? //設(shè)備連接狀態(tài) 1:連接,0:斷開
? ? UINT8 Device_compat;?????? //0:非復(fù)合設(shè)備,1表示復(fù)合設(shè)備?
? ? UINT8 Cfg_value;?????????? //設(shè)備配置描述符中配置值
? struct _Device{
? ? UINT8 Device_type;? ?????? //設(shè)備類型 1:鍵盤,2:鼠標(biāo)
? ? UINT8 Device_inf;?? ?????? //設(shè)備接口號(hào)默認(rèn)為0? 最多支持兩個(gè)接口設(shè)備
? ? UINT8 Device_endp;???????? //設(shè)備端點(diǎn)地址 最多支持一個(gè)端點(diǎn)
? ? UINT8 Device_size;???????? //設(shè)備端點(diǎn)大小
? ? UINT16 Device_report_len;?? //設(shè)備報(bào)表長度
??? UINT8 tog;????????????? ?? //端點(diǎn)的同步標(biāo)志
? }Device[2];
}Device_Atti = { 0 };
?
UINT8 receive_mode = 0x00,send_mode = 0x00;
UINT8 data_buf[160];
UINT8 status;
bit?? flag_config_2; //第二次獲取配置描述符標(biāo)志
UINT8 report_cou;??? //實(shí)際獲取的報(bào)表長度
?
//**********************************************
//* NAME:??? mDelay2uS( )??????????????????????????????????
//* FUCTION: 延時(shí)2us子函數(shù)????????????????????????????????
//* 輸入?yún)?shù):無
//* 輸出參數(shù):無???????????????????????????????????
//* 說明:??? 根據(jù)單片機(jī)的主頻進(jìn)行調(diào)整?????????????????????????????????
//**********************************************
?
void mDelay2uS( )
{
?UINT8 i;
?for(i=6;i!=0;i--);
?
}
?
//**********************************************
//* NAME:??? mDelay50mS( )?????????????????????????????????
//* FUCTION: 延時(shí)50ms子函數(shù)???????????????????????????????????
//* 輸入?yún)?shù):無
//* 輸出參數(shù):無???????????????????????????????????
//* 說明:??? 根據(jù)單片機(jī)的主頻進(jìn)行調(diào)整?????????????????????????????????
//**********************************************
?
void mDelay50mS( )
{
?UINT8 i,j,h;
?for (h=1;h!=0;h--)
? for(i=250;i!=0;i--)
?? ?for(j=250;j!=0;j--);
}
?
void mDelaymS(unsigned char delay)
{?? unsigned char i,h;
??? do{
??? ?? for ?(h=0;h!=1;h++)
??? ?? {
??? ??? for(i=0;i!=250;i++){;}
??????? for(i=0;i!=250;i++){;}
??????? for(i=0;i!=150;i++){;}
??????? }
??? }while(--delay);
}
?
?
/* ****************************************************
*
* 名稱 :?? SerialPortTwo_Send
* 功能 :?? 利用串口2發(fā)送數(shù)據(jù)
* 入口函數(shù):Text,用于表示需要發(fā)送的數(shù)據(jù)
*
*******************************************************/
void SerialPortTwo_Send(uchar Text) //利用串口2進(jìn)行數(shù)據(jù)發(fā)送
{
??? uchar temp = 0;
?
??? IE2?? = 0x00;
??? S2CON = S2CON & 0xfd;?????? //清除標(biāo)志位
??? S2BUF = Text;
??? do
??? {
??????? temp = S2CON;
??????? temp = temp & 0x02;
??? }
??? while(temp == 0);?????? ? //等待發(fā)送完成
?
??? S2CON = S2CON & 0xfd;?? ? //清除發(fā)送完成標(biāo)志
??? IE2?? = 0x01;
}
?
/* ********************************************************
*
* ? 名稱 :?? SendStr
* ? 功能 : ? 將對(duì)應(yīng)的數(shù)據(jù)通過串口2發(fā)送給上位機(jī)
* 入口函數(shù):? *s發(fā)送內(nèi)容
* 出口函數(shù):
*
************************************************************/
void SendStrTwo(uchar *s)?? //發(fā)送某一數(shù)組數(shù)據(jù)
?{
?
//? SerialPortTwo_Send('#');
?
??? while(*s!= ' ')
??? {
??????? SerialPortTwo_Send(*s);
??????? s++;
??? }
//? SerialPortTwo_Send('*');
?}
?
?
?
//**********************************************
//* NAME:??? CH376_WR_CMD_PORT( UINT8 cmd )????????????????????????????????
//* FUCTION: 寫CH376命令子函數(shù)????????????????????????????????
//* 輸入?yún)?shù):8位命令碼
//* 輸出參數(shù):無???????????????????????????????????
//* 說明:對(duì)于速度較快的單片機(jī),則需要1.5uS延時(shí)???????????????????????????????????
//**********************************************
?
void CH376_WR_CMD_PORT( UINT8 cmd )
{
?// CH376_CMD_PORT = cmd;
//? mDelay2uS( );???????????? //對(duì)于高速單片機(jī)需要2us的延時(shí)
?
?TI = 0;
??? SBUF = SER_SYNC_CODE1;? /* 啟動(dòng)操作的第1個(gè)串口同步碼 */
??? while ( TI == 0 );
??? TI = 0;
??? SBUF = SER_SYNC_CODE2;? /* 啟動(dòng)操作的第2個(gè)串口同步碼 */
??? while ( TI == 0 );
??? TI = 0;
??? SBUF = cmd;? /* 串口輸出 */
??? while ( TI == 0 );
?
?
}
?
?
//**********************************************
//* NAME:??? CH376_WR_DAT_PORT( UINT8 dat )????????????????????????????????
//* FUCTION: 寫CH376數(shù)據(jù)子函數(shù)????????????????????????????????
//* 輸入?yún)?shù):8位數(shù)據(jù)
//* 輸出參數(shù):無???????????????????????????????????
//* 說明:對(duì)于速度較快的單片機(jī),則需要0.6uS延時(shí)???????????????????????????????????
//**********************************************
?
void CH376_WR_DAT_PORT( UINT8 dat )
{
?//CH376_DAT_PORT = dat;
?
?? TI = 0;
??? SBUF = dat;? /* 串口輸出 */
??? while ( TI == 0 );
?
}
?
//**********************************************
//* NAME:??? CH376_RD_DAT_PORT( void )?????????????????????????????????
//* FUCTION: 讀CH376數(shù)據(jù)子函數(shù)????????????????????????????????
//* 輸入?yún)?shù):無
//* 輸出參數(shù):8位數(shù)據(jù)??????????????????????????????????
//* 說明:對(duì)于速度較快的單片機(jī),則需要0.6uS延時(shí)???????????????????????????????????
//**********************************************
?
UINT8 CH376_RD_DAT_PORT( void )
{
?// return(CH376_DAT_PORT);
?
?? UINT32?? i;
??? for ( i = 0; i < 500000; i ++ ) {? /* 計(jì)數(shù)防止超時(shí) */
??????? if ( RI ) {? /* 串口接收到 */
??????????? RI = 0;
??????????? ?// SerialPortTwo_Send(SBUF);
??????????? return( SBUF );? /* 串口輸入 */
??? ??? }
??? }
??? return( 0 );? /* 不應(yīng)該發(fā)生的情況 */
}
?
?
//**********************************************
//* NAME:??? StdioInit( void )?????????????????????????????????
//* FUCTION: 單片機(jī)串口初始化,用于檢測程序????????????????????????????????
//* 輸入?yún)?shù):無
//* 輸出參數(shù):無???????????????????????????????????
//* 說明: 單片機(jī)主頻24M使用定時(shí)器1 波特率9600???????????????????????????????????
//**********************************************
?
void??? StdioInit( )
{
?
?
?
??? //串口1設(shè)置
??? TMOD = 0x20;//設(shè)置波特率
?
??? TH1? = 0xfd;//Baudrate=9600;f4->1200
??? TL1? = 0xfd;
??? PCON = 0x00;
??? SCON = 0x50;//串行通信設(shè)置
//? RI=0;
?
??? //串口2設(shè)置
??? AUXR &= 0xf7;//波特率不倍速
??? S2CON = 0x50;//8位數(shù)據(jù),可變波特率
??? BRT?? = 0xB8;//設(shè)定獨(dú)立波特率發(fā)生器重裝值 0x70 4800? 0xB8? 9600
??? AUXR |= 0xc; //獨(dú)立波特率發(fā)生器時(shí)鐘為Fosc,即12T
??? AUXR |= 0x10;//啟動(dòng)獨(dú)立波特率發(fā)生器
?//?? IE2?? = 0X01;//開啟串口2中斷
?
??? TMOD |= 0x01;
??? TH0 = 0x4c;???? //重新賦值
??? TL0 = 0x00;
?
??? TR1? = 1;
?
?
?
?
}
?
//**********************************************
//* NAME:??? Set_USB_Mode( UINT8 mode )????????????????????????????????
//* FUCTION: 設(shè)置CH376的工作模式 0x06 為主機(jī)模式??????????????????????????????????
//* 輸入?yún)?shù):模式代碼
//* 輸出參數(shù):操作狀態(tài) TRUE:成功,FALSE失敗???????????????????????????????????
//* 說明: 設(shè)置CH376的工作模式????????????????????????????????
//**********************************************
?
UINT8 Set_USB_Mode( UINT8 mode ) {?
??? UINT8 i;
??? CH376_WR_CMD_PORT( CMD_SET_USB_MODE );
??? CH376_WR_DAT_PORT( mode );
??? receive_mode=send_mode=0x00;? //主機(jī)端復(fù)位USB數(shù)據(jù)同步標(biāo)志
??? for( i=0; i!=100; i++ ) {??? //等待設(shè)置模式操作完成,不超過30uS
??????? if ( CH376_RD_DAT_PORT()==CMD_RET_SUCCESS ) return( TRUE );? //成功
??? }
?
??? return( FALSE );????????????? //CH376出錯(cuò),例如芯片型號(hào)錯(cuò)或者處于串口方式或者不支持
}
?
?
//*****************************************************
//* NAME:??? set_freq(void)????????????????????????????????
//* FUCTION: 設(shè)置CH376的進(jìn)入低速模式??????????????????????????????????
//* 輸入?yún)?shù):無
//* 輸出參數(shù):無???????????????????????????????????
//* 說明: 對(duì)于鼠標(biāo)鍵盤等低速設(shè)備,要先設(shè)置ch376為低速模式????????????????????????????????
//******************************************************
?
void set_freq(void)
{??
??? CH376_WR_CMD_PORT(0x0b);??? // 切換使375B進(jìn)入低速模式
??? CH376_WR_DAT_PORT(0x17);
??? CH376_WR_DAT_PORT(0xd8);
}
?
?
?
//*****************************************************
//* NAME:???? RD_USB_DATA( UINT8 *buf )????????????????????????????????
//* FUCTION:? 從CH376的端點(diǎn)緩沖區(qū)讀取接收到的數(shù)據(jù)?????????????????????????????????
//* 輸入?yún)?shù): 數(shù)據(jù)緩沖區(qū)的地址
//* 輸出參數(shù):返回接收的數(shù)據(jù)長度???????????????????????????????????
//* 說明:??? 從CH376的主機(jī)端點(diǎn)緩沖區(qū)中讀取接收到的數(shù)據(jù)???????????????????????????????????
//******************************************************
?
UINT8 RD_USB_DATA( UINT8 *buf ) {?
??? UINT8 i, len;
??? CH376_WR_CMD_PORT( CMD01_RD_USB_DATA0 ); ?? ?????????// 從CH37X讀取數(shù)據(jù)塊
??? len=CH376_RD_DAT_PORT();???????????????????????????? // 后續(xù)數(shù)據(jù)長度
??? for ( i=0; i!=len; i++ ) *buf++=CH376_RD_DAT_PORT();
??? return( len );
}
?
?
//*****************************************************
//* NAME:???? WR_USB_DATA( UINT8 len, UINT8 *buf )?????????????????????????????????
//* FUCTION:? 往CH376的端點(diǎn)緩沖區(qū)寫入數(shù)據(jù)塊???????????????????????????????
//* 輸入?yún)?shù): 要寫入數(shù)據(jù)塊的長度,寫入數(shù)據(jù)緩沖區(qū)的地址
//* 輸出參數(shù):無???????????????????????????????????
//* 說明:??? 往CH376的主機(jī)端點(diǎn)緩沖區(qū)中寫入要發(fā)送的數(shù)據(jù)塊?????????????????????????????????
//******************************************************
?
void WR_USB_DATA( UINT8 len, UINT8 *buf ) {?
??? CH376_WR_CMD_PORT( CMD10_WR_HOST_DATA );???? // 向CH376的端點(diǎn)緩沖區(qū)寫入準(zhǔn)備發(fā)送的數(shù)據(jù)
??? CH376_WR_DAT_PORT( len );??????????????????? // 后續(xù)數(shù)據(jù)長度, len不能大于64
??? while( len-- ) CH376_WR_DAT_PORT( *buf++ );
}
?
?
//*****************************************************
//* NAME:???? issue_token(UINT8 endptog, UINT8 endp_and_pid )??????????????????????????????
//* FUCTION:? 執(zhí)行USB事務(wù)?????????????????????????????
//* 輸入?yún)?shù): 同步標(biāo)志,端點(diǎn)號(hào)和令牌
//* 輸出參數(shù):無???????????????????????????????????
//* 說明:??? 高4位目的端點(diǎn)號(hào), 低4位令牌PID??????????????????????????????????
//******************************************************
?
void issue_token(UINT8 endptog, UINT8 endp_and_pid ) {?
??? CH376_WR_CMD_PORT( CMD2H_ISSUE_TKN_X );
??? CH376_WR_DAT_PORT( endptog );
??? CH376_WR_DAT_PORT( endp_and_pid );
??? mDelay2uS();?
}
?
///*------------------------------------------------
//??????????????????? 發(fā)送一個(gè)字節(jié)
//------------------------------------------------*/
//
//void SendByte(unsigned char dat)
//{
// SBUF = dat;
// while(!TI);
//????? TI = 0;
//}
?
//*****************************************************
//* NAME:???? wait_interrupt( )????????????????????????????
//* FUCTION:? 等待中斷,并且獲取中斷狀態(tài)???????????????????????????????
//* 輸入?yún)?shù): 無
//* 輸出參數(shù):中斷狀態(tài)?????????????????????????????????
//* 說明:??? CH376操作完成中斷(INT#低電平)?? ????????????????????????????????? ?
//******************************************************
?
UINT8 wait_interrupt( ) {?
??? while( CH376_INT_WIRE );
??? CH376_WR_CMD_PORT( CMD_GET_STATUS );
??? return( CH376_RD_DAT_PORT() );
}
?
?
?
//*****************************************************
//* NAME:???? Get_Dev_Descr( )?????????????????????????????
//* FUCTION:? 獲取設(shè)備描述符???????????????????????????????
//* 輸入?yún)?shù): 無
//* 輸出參數(shù):成功返回1,否則返回0????????????????????????????????
//* 說明:??? 該程序采用外置固件模式獲取設(shè)備描述符?? ?????????????????????????????????? ?
//******************************************************
?
UINT8 Get_Dev_Descr( )
{??
??? UINT8 descr_len;
??? UINT8? *p=data_buf;
??? send_mode=0x00;
??? WR_USB_DATA(8,SetupGetDevDescr);
?
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_SETUP);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)?????? ???????????????????????????????????????????????//SETUP階段操作成功
??? {
??????? receive_mode=0x80;
??? }
??? else return(0);
?
??? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????????? //DATA階段操作成功
??? {
??????? descr_len=data_buf[0]-RD_USB_DATA(data_buf);???
??????? while(descr_len>0)
??????? {??
??????????? receive_mode ^= 0x80;
??????????? p+=0x08;
??????????? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??????????? if(status==USB_INT_SUCCESS)???????????????????????????????????????????? //DATA階段操作成功
??????????????? descr_len-=RD_USB_DATA(p);?
??????????? else return(0);
???????????
??????? }
??? }
??? else return(0);
?
??? send_mode=0x40;
??? WR_USB_DATA(0,SetupGetDevDescr);
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_OUT);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????? ??? //狀態(tài)階段操作成功
??????? return(1);?
??? else return(0);
}
?
?
?
//*****************************************************
//* NAME:???? Get_Cfg_Descr( PUINT8 buf )??????????????????????????????
//* FUCTION:? 獲取配置描述符???????????????????????????????
//* 輸入?yún)?shù): 接收緩沖區(qū)地址
//* 輸出參數(shù):成功返回1,否則返回0????????????????????????????????
//* 說明:? ??該程序采用外置固件模式獲取配置描述符?? ?????????????????????????????????? ?
//******************************************************
?
UINT8 Get_Cfg_Descr( PUINT8 buf )
{
??? unsigned char descr_len;
??? unsigned char *p=data_buf;
??? send_mode=0x00;
??? WR_USB_DATA(8,buf);
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_SETUP);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????????? //SETUP階段操作成功
??? {
??????? receive_mode=0x80;
??? }
??? else return(0);
??? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????????? //DATA階段操作成功
??? {??
??? ??? receive_mode ^= 0x80;
??????? if(flag_config_2)?????????????????????????????????????????????????????? ??? //第二次獲取設(shè)備的配置描述符
??? ???????? descr_len=data_buf[2]-RD_USB_DATA(data_buf);
??????? else descr_len=data_buf[0]-RD_USB_DATA(data_buf);??
??????? while(descr_len>0)
??????? {??
??????????? p+=0x08;
??????????? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??????????? if(status==USB_INT_SUCCESS)???????????????????????????????????????????? //DATA階段操作成功
??????????? ? {
??????????? ??? receive_mode ^= 0x80;
??????????????? descr_len-=RD_USB_DATA(p);?
??????????? ?? }
??????????? else return(0);
???????????
??????? }
??? }
??? else return(0);
??? send_mode = 0x40;
??? WR_USB_DATA(0,SetupGetCfgDescr);
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_OUT);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????????? //狀態(tài)階段操作成功
??????? return(1);?
??? else return(0);
}
?
?
void parse_config_descr( )
{
? Device_Atti.Device_connect = 1;?????????????????????? ??????????????????? //表示設(shè)備連接
? Device_Atti.Cfg_value = ((PUSB_CFG_DESCR)data_buf)->bConfigurationValue;? //保留配置描述符中的配置值
?
?if(((PUSB_CFG_DESCR)data_buf)->bNumInterfaces==1)????? ? ????????????????? //只有一個(gè)接口設(shè)備
? {
??? Device_Atti.Device_compat = 0;????????????????????? ? ????????????????? //非復(fù)合設(shè)備
?
?#define HID_Dev? ((PHID_DEVICE)data_buf)
???
? ? Device_Atti.Device[0].Device_type =? HID_Dev->hid_itf_descr.bInterfaceProtocol; //設(shè)備類型:0x01 鍵盤,0x02 鼠標(biāo)
??? Device_Atti.Device[0].Device_inf? =? HID_Dev->hid_itf_descr.bInterfaceNumber;?? //設(shè)備的接口號(hào)
??? Device_Atti.Device[0].Device_endp =? HID_Dev->endp_descr.bEndpointAddress;????? //設(shè)備端點(diǎn)地址
? ? Device_Atti.Device[0].Device_size =? HID_Dev->endp_descr.wMaxPacketSize;??????? //設(shè)備端點(diǎn)大小
??? Device_Atti.Device[0].Device_report_len =? (HID_Dev->hid_class_descr.wDescriptorLength>>8)|(HID_Dev->hid_class_descr.wDescriptorLength<<8); ?? //報(bào)表長度,大小端數(shù)據(jù)格式轉(zhuǎn)換
?
? }
?
?else if(((PUSB_CFG_DESCR)data_buf)->bNumInterfaces==2)???? ? ????????????? //2個(gè)接口設(shè)備
? {
??? Device_Atti.Device_compat = 1;????????????????????? ? ????????????????? //復(fù)合設(shè)備
?
?#define HID_Dev1? ((PHID_COMPOSITE_DEVICE1)data_buf)
???
? ? Device_Atti.Device[0].Device_type =? HID_Dev1->hid_itf_descr1.bInterfaceProtocol;
??? Device_Atti.Device[0].Device_inf? =? HID_Dev1->hid_itf_descr1.bInterfaceNumber;
??? Device_Atti.Device[0].Device_endp =? HID_Dev1->endp_descr1.bEndpointAddress;
? ? Device_Atti.Device[0].Device_size =? HID_Dev1->endp_descr1.wMaxPacketSize;
??? Device_Atti.Device[0].Device_report_len =? (HID_Dev1->hid_class_descr1.wDescriptorLength>>8)|(HID_Dev1->hid_class_descr1.wDescriptorLength<<8); //報(bào)表長度,大小端數(shù)據(jù)格式轉(zhuǎn)換
?
? ? Device_Atti.Device[1].Device_type =? HID_Dev1->hid_itf_descr2.bInterfaceProtocol;
??? Device_Atti.Device[1].Device_inf? =? HID_Dev1->hid_itf_descr2.bInterfaceNumber;
??? Device_Atti.Device[1].Device_endp =? HID_Dev1->endp_descr2.bEndpointAddress;
? ? Device_Atti.Device[1].Device_size =? HID_Dev1->endp_descr2.wMaxPacketSize;
??? Device_Atti.Device[1].Device_report_len =? (HID_Dev1->hid_class_descr2.wDescriptorLength>>8)|(HID_Dev1->hid_class_descr2.wDescriptorLength<<8); //報(bào)表長度,大小端數(shù)據(jù)格式轉(zhuǎn)換
?
? }
?
}
?
?
UINT8 set_config( UINT8 cfg ) {?
??? CH376_WR_CMD_PORT( CMD_SET_CONFIG );?
??? CH376_WR_DAT_PORT( cfg );?
??? return( wait_interrupt() );?
}
?
?
UINT8 set_idle( UINT8 inf )
{
??? send_mode=0x00;
??? memcpy(data_buf,SetupSetidle,8);
??? data_buf[4] = inf;
??? WR_USB_DATA(8,data_buf);??????????????????????????????? //SETUP數(shù)據(jù)總是8字節(jié)
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_SETUP);
??? status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????? //SETUP階段操作成功
??? {
??????? receive_mode=0x80;
??????? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN );status=wait_interrupt();
??????? if(status==USB_INT_SUCCESS)???????????????????????? //狀態(tài)階段操作成功
??????? {
??????????? if(RD_USB_DATA(data_buf)!=0)
??????????? return(0);
??????? }
??????? else return(0);
??? }
??? else return(0);
??? return(1);?
}
?
?
?
UINT8 get_report_descr_ex( UINT8 inf,UINT16 len)???????
{
??? unsigned char descr_len;
??? unsigned char *p=data_buf;
??? unsigned char report_cou_temp=0;
??? report_cou=0;
??? send_mode=0x00;
??? memcpy(data_buf,SetupGetHidDes,8);
??? data_buf[4] = inf;
??? data_buf[6] = len+0x40;????????????????
??? WR_USB_DATA(8,data_buf);???????
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_SETUP);status=wait_interrupt();?
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????????? //SETUP階段操作成功
??? {??
??? ??? receive_mode=0x80;?
??? }
??? else return(0);
??? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???? ??????????????????????????????????????????????? //DATA階段操作成功
??? {??
??? ??
??? ?? RD_USB_DATA(data_buf);
??????? report_cou+=8;?
??????? descr_len=data_buf[6]-0x08;???????????????????????????????????????????????? //剩余描述符長度計(jì)算
??????? while(descr_len>0)
??????? {??
??????????? receive_mode ^= 0x80;
??????????? p+=0x08;
??????????? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??????????? if(status==USB_INT_SUCCESS)???????????????????????????????????????????? // DATA階段操作成功
??????????? {??
??????????? ??? report_cou_temp=RD_USB_DATA(p);
??????????????? if(report_cou_temp!=0x08){report_cou+=report_cou_temp;break;}
??????????????? else {descr_len-=0x08;report_cou+=8;}
??????????? }
??????????? else return(0);
???????????
??????? }
??? }
??? else return(0);
??? send_mode=0x40;
??? WR_USB_DATA(0,data_buf);
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_OUT);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????????????????????????????? //狀態(tài)階段操作成功
??????? return(1);?
??? else return(0);
}
?
?
UINT8 set_report( )
{??
??? send_mode=0x00;
??? WR_USB_DATA(8,SetupSetReport);????????????????????????????????????????????????? //SETUP數(shù)據(jù)總是8字節(jié)
??? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_SETUP);status=wait_interrupt();
??? if(status==USB_INT_SUCCESS)???????????????????????????? ??????????????????????? //SETUP階段操作成功
??? {??
??? ??? send_mode ^= 0x40;
??????? data_buf[0]=0x01;
??????? WR_USB_DATA(1,data_buf);
??????? issue_token(send_mode,( 0 << 4 ) | DEF_USB_PID_OUT);status=wait_interrupt();
??????? if(status==USB_INT_SUCCESS) ??????????????????????????????????????????????? //DATA階段操作成功
??????? {??
??????? ??? receive_mode=0x80;
??????????? issue_token(receive_mode,( 0 << 4 ) | DEF_USB_PID_IN);status=wait_interrupt();
??????????? if(status==USB_INT_SUCCESS)???????????????????????????????????????????? //狀態(tài)階段操作成功
??????????? {??
??????????? ??? if(RD_USB_DATA(data_buf)!=0)
??????????????? return(0);
??????????? }
??????????? else return(0);
??????? }
??????? else return(0);
??? }??
??? else return(0);
???
???
??? return(1);
}
?
?
//*****************************************************
//* NAME:???? get_int_in(UINT8 tog,UINT8 endp_int)?????????????????????????????
//* FUCTION:? 獲取HID類設(shè)備的數(shù)據(jù)?????????????????????????????
//* 輸入?yún)?shù): 該設(shè)備的同步標(biāo)志,端點(diǎn)號(hào)
//* 輸出參數(shù):操作狀態(tài)?????????????????????????????????
//* 說明:??? 支持復(fù)合設(shè)備的操作? ????????????????????????????????? ?
//******************************************************
?
UINT8 get_int_in(UINT8 tog,UINT8 endp_int)
{
??? UINT8 s,t,j;
??? tog = tog ? 0x80 : 0x00;
??? issue_token(tog,( endp_int << 4 ) | DEF_USB_PID_IN);
??? s = wait_interrupt( );
??? ?if(s == USB_INT_SUCCESS)
??? ?{
??????? ? t = RD_USB_DATA(data_buf);??????????????????????????????????????? //鍵盤中斷端點(diǎn)數(shù)據(jù)長度一般為8字節(jié),鼠標(biāo)為4字節(jié)
???????
??????? for(j=0;j!=t;j++)?? SerialPortTwo_Send(data_buf[j]);
? ????? if( endp_int == Device_Atti.Device[0].Device_endp )
??????? ?Device_Atti.Device[0].tog = Device_Atti.Device[0].tog ? FALSE : TRUE;
? ? ????else
??????? ?Device_Atti.Device[1].tog = Device_Atti.Device[1].tog ? FALSE : TRUE;
??? }
??? ?SerialPortTwo_Send('g');//
??? return s;
}
?
?
?
void Reset_Device( )
{??
??? Set_USB_Mode( 7 );? ??????????????????????????????????????????????????? //復(fù)位USB設(shè)備,CH376向USB信號(hào)線的D+和D-輸出低電平
??? mDelaymS(10);
??? Set_USB_Mode( 6 );? ??????????????????????????????????????????????????? //結(jié)束復(fù)位,將CH376設(shè)置成主機(jī)模式
??? while ( wait_interrupt()!=USB_INT_CONNECT );? ????????????????????????? //等待復(fù)位之后的設(shè)備端再次連接上來
?
}
?
//*****************************************************
//* NAME:???? set_addr( UINT8 addr )???????????????????????????????
//* FUCTION:? 設(shè)置USB設(shè)備地址,并且設(shè)置USB主機(jī)端要操作的USB設(shè)備地址????????????????????? ???????
//* 輸入?yún)?shù): 地址值(1~127)
//* 輸出參數(shù):操作狀態(tài)?????????????????????????????????
//* 說明:???
//******************************************************
?
UINT8 set_addr( UINT8 addr ) {
??? UINT8 status;
??? CH376_WR_CMD_PORT( CMD_SET_ADDRESS );?
??? CH376_WR_DAT_PORT( addr );?
??? status=wait_interrupt();? ????????????????????????????????????????????? //等待CH376操作完成
??? if ( status==USB_INT_SUCCESS ) {? ????????????????????????????????????? //操作成功
??????? CH376_WR_CMD_PORT( CMD_SET_USB_ADDR );? ??????????????????????????? //設(shè)置USB主機(jī)端的USB地址
??????? CH376_WR_DAT_PORT( addr );? ??????????????????????????????????????? //當(dāng)目標(biāo)USB設(shè)備的地址成功修改后,應(yīng)該同步修改主機(jī)端的USB地址
??? }
??? return( status );
}
?
?
?
void main( void )
{
? UINT8 i,s;
? mDelay50mS( );??? ?? //CH376上電之后需要延時(shí)40ms左右
?
? StdioInit( );
//? SendByte('A');?
//? printf("start \n");
?
?// SendStrTwo("QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ");
?
//做測試命令,檢測單片機(jī)和CH376硬件連接,以及讀寫時(shí)序是否正確?
? CH376_WR_CMD_PORT( 0x06 );
?
? CH376_WR_DAT_PORT( 0x55 );
?
? s = CH376_RD_DAT_PORT( );
?
?? SerialPortTwo_Send(s);
?
//? SendByte('B');
?
? SerialPortTwo_Send(Set_USB_Mode( 6 )+0x30);? ???????????????????????????????? //設(shè)置USB主機(jī)模式, 如果設(shè)備端是CH37X, 那么5和6均可
?
? set_freq( );? ?????? ???????????????????????????????? //使376進(jìn)入低速模式
?
//? SendByte('C');
?
?while(1)
?{
? //? printf(" \n wait usb device : \n");
??? while ( wait_interrupt()!=USB_INT_CONNECT );
??? SerialPortTwo_Send('A');
??? mDelaymS(50);
??? Reset_Device();
??? SerialPortTwo_Send('B');??????????????????????????????????? //復(fù)位usb設(shè)備
??? mDelaymS(50);
??? set_freq( );?????? ???????????????????????????????? //使376進(jìn)入低速模式
??? mDelaymS(50);
?
//獲取設(shè)備描述符
??? if(Get_Dev_Descr()==1)
??? {
??????? for(i=0;i!=data_buf[0];i++)
??? ??? SerialPortTwo_Send('D'); // printf("%02x ",(unsigned int)data_buf[i]);?
??? ??? //? printf("\n");
??? }
??? else SerialPortTwo_Send('E');//printf("\n get device descr failed \n");
?
//設(shè)置地址?????
??? SerialPortTwo_Send(set_addr(5));???????????????????????????????????????
?
//獲取配置描述符
??? if( Get_Cfg_Descr( SetupGetCfgDescr ) == 1)
??? ?{
?? ???? for(i=0;i!=data_buf[0];i++)
??? ????? SerialPortTwo_Send(data_buf[i]);?
??????? ?// SerialPortTwo_Send("\n");
??? ?}
??? ?s = ((PUSB_CFG_DESCR)data_buf)->wTotalLengthL;
??? ?memcpy( data_buf,SetupGetCfgDescr,8);
???? data_buf[6] = s;
?
??? ?flag_config_2 = 1;
??? if( Get_Cfg_Descr( data_buf ) == 1)
??? ?{
?? ???? for(i=0;i!=((PUSB_CFG_DESCR)data_buf)->wTotalLengthL;i++)
??????? ? SerialPortTwo_Send(data_buf[i]);?
??????? ?// SerialPortTwo_Send("\n");
??? ?}
?
//保存配置描述符中設(shè)備信息
??? parse_config_descr( );
?
?
#if 0
#endif
? SendStrTwo("line838");
//設(shè)置USB配置??
?? s = set_config( Device_Atti.Cfg_value );
? //?? SerialPortTwo_Send(" cfg %02x \n",(UINT16)s);
?
//設(shè)置HID類設(shè)備的IDLE
?? s = set_idle( Device_Atti.Device[0].Device_inf );
?? if(s == 1)
????? SerialPortTwo_Send('O');
?? else?? SerialPortTwo_Send('N');
?
//獲取HID類設(shè)備的報(bào)表描述符
? ?s = get_report_descr_ex( Device_Atti.Device[0].Device_inf,Device_Atti.Device[0].Device_report_len);
??? if( s == 1)
??? ?{
??? ?? for(i=0;i!=report_cou;i++)
??? ????? SerialPortTwo_Send(data_buf[i]);
??? ?
??? ?}
?
//如果該HID類設(shè)備是鍵盤,則可以設(shè)置報(bào)表
??? if(Device_Atti.Device[0].Device_type == 0x01)
??? {
??? s = set_report( );
??? if(s==1)?? SerialPortTwo_Send('J');
??? else?? SerialPortTwo_Send('P');
??? }
?
//如果該設(shè)備是復(fù)合設(shè)備,則需要配置另外一個(gè)接口設(shè)備
#if 1
??? if(Device_Atti.Device_compat == 1)
??? {
//設(shè)置IDLE
??? ?s = set_idle( Device_Atti.Device[1].Device_inf );
????? if(s == 1)
?? ????SerialPortTwo_Send('Q');
???? else?? SerialPortTwo_Send('R');
?
//獲取報(bào)表描述符
???? s = get_report_descr_ex( Device_Atti.Device[1].Device_inf,Device_Atti.Device[1].Device_report_len);
??? ? if( s == 1)
??? ?? {
??? ??? for(i=0;i!=report_cou;i++)
??? ????? SerialPortTwo_Send(data_buf[i]);?
??? ?? }
?
//如果該設(shè)備是鍵盤,則可以設(shè)置報(bào)表
??? if(Device_Atti.Device[1].Device_type == 0x01)
??? ?{
??? ? s = set_report( );
??? ? if(s==1)?? SerialPortTwo_Send('S');
??? ? else?? SerialPortTwo_Send('T');
?
??? ?}
?
?? }
#endif
?
?
??? CH376_WR_CMD_PORT( CMD20_SET_RETRY );?????? //設(shè)置CH376重試次數(shù)
??? CH376_WR_DAT_PORT( 0x25 );
??? CH376_WR_DAT_PORT( 0x00 );????????????????? //為了保證兼容性對(duì)于部分鼠標(biāo)鍵盤需要設(shè)置有限次重試(0xc0),而對(duì)于復(fù)合設(shè)備,
??? ???????????????????????????????????????????? //比如USB轉(zhuǎn)PS2的設(shè)備,復(fù)合鍵盤,則不需要重試(0x00)
?
?
??? Device_Atti.Device[0].tog = FALSE;????????? //設(shè)置設(shè)備的同步標(biāo)志,默認(rèn)0
??? Device_Atti.Device[1].tog = FALSE;
?
SendStrTwo("line906");
?
?? while(1)
?? {
//獲取設(shè)備1的數(shù)據(jù)
?? s = get_int_in( Device_Atti.Device[0].tog,Device_Atti.Device[0].Device_endp);
?
//如果該設(shè)備是符合設(shè)備,則需要獲取設(shè)備2的數(shù)據(jù)
??? if( Device_Atti.Device_compat )
??? {
??? ?s = get_int_in( Device_Atti.Device[1].tog,Device_Atti.Device[1].Device_endp);
??? }
?
//以下是檢測設(shè)備插拔狀態(tài)
??? CH376_WR_CMD_PORT(CMD01_TEST_CONNECT );???????? //檢測設(shè)備插拔
??? ?s = CH376_RD_DAT_PORT( );
??? ?if(s == USB_INT_DISCONNECT )
??? ?{
????? Device_Atti.Device_connect = 0;
//? ??? Device_Atti = {0};
??? ? break;??????????????????????????????????????? //設(shè)備斷開
?? ?}
?? }
?}
?
}
?
?