?? usbcore.c
字號:
//bmAttributes字段。D1~D0為端點傳輸類型選擇。
//該端點為中斷端點。中斷端點的編號為3。其它位保留為0。
0x03,
//wMaxPacketSize字段。該端點的最大包長。端點1的最大包長為16字節。
//注意低字節在先。
0x10,
0x00,
//bInterval字段。端點查詢的時間,我們設置為10個幀時間,即10ms。
0x0A,
/**********************輸出端點描述符***********************/
//bLength字段。端點描述符長度為7字節。
0x07,
//bDescriptorType字段。端點描述符編號為0x05。
0x05,
//bEndpointAddress字段。端點的地址。我們使用D12的輸出端點1。
//D7位表示數據方向,輸出端點D7為0。所以輸出端點1的地址為0x01。
0x01,
//bmAttributes字段。D1~D0為端點傳輸類型選擇。
//該端點為中斷端點。中斷端點的編號為3。其它位保留為0。
0x03,
//wMaxPacketSize字段。該端點的最大包長。端點1的最大包長為16字節。
//注意低字節在先。
0x10,
0x00,
//bInterval字段。端點查詢的時間,我們設置為10個幀時間,即10ms。
0x0A
};
////////////////////////配置描述符集合完畢//////////////////////////
/************************語言ID的定義********************/
code uint8 LanguageId[4]=
{
0x04, //本描述符的長度
0x03, //字符串描述符
//0x0409為美式英語的ID
0x09,
0x04
};
////////////////////////語言ID完畢//////////////////////////////////
/**************************************************/
/********* 本轉換結果來自 **********/
/********* Http://computer00.21ic.org **********/
/********* 作者: 電腦圈圈 **********/
/********* 歡迎大家使用 **********/
/********* 版權所有,盜版請寫明出處 **********/
/**************************************************/
//http://computer00.21ic.org/user1/2198/archives/2007/42769.html
//字符串“電腦圈圈的USB專區 Http://group.ednchina.com/93/”的Unicode編碼
//8位小端格式
code uint8 ManufacturerStringDescriptor[82]={
82, //該描述符的長度為82字節
0x03, //字符串描述符的類型編碼為0x03
0x35, 0x75, //電
0x11, 0x81, //腦
0x08, 0x57, //圈
0x08, 0x57, //圈
0x84, 0x76, //的
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x13, 0x4e, //專
0x3a, 0x53, //區
0x20, 0x00, //
0x48, 0x00, //H
0x74, 0x00, //t
0x74, 0x00, //t
0x70, 0x00, //p
0x3a, 0x00, //:
0x2f, 0x00, ///
0x2f, 0x00, ///
0x67, 0x00, //g
0x72, 0x00, //r
0x6f, 0x00, //o
0x75, 0x00, //u
0x70, 0x00, //p
0x2e, 0x00, //.
0x65, 0x00, //e
0x64, 0x00, //d
0x6e, 0x00, //n
0x63, 0x00, //c
0x68, 0x00, //h
0x69, 0x00, //i
0x6e, 0x00, //n
0x61, 0x00, //a
0x2e, 0x00, //.
0x63, 0x00, //c
0x6f, 0x00, //o
0x6d, 0x00, //m
0x2f, 0x00, ///
0x39, 0x00, //9
0x33, 0x00, //3
0x2f, 0x00 ///
};
/////////////////////////廠商字符串結束/////////////////////////////
//字符串“《圈圈教你玩USB》之USB鍵盤”的Unicode編碼
//8位小端格式
code uint8 ProductStringDescriptor[34]={
34, //該描述符的長度為34字節
0x03, //字符串描述符的類型編碼為0x03
0x0a, 0x30, //《
0x08, 0x57, //圈
0x08, 0x57, //圈
0x59, 0x65, //教
0x60, 0x4f, //你
0xa9, 0x73, //玩
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x0b, 0x30, //》
0x4b, 0x4e, //之
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x2e, 0x95, //鍵
0xd8, 0x76 //盤
};
////////////////////////產品字符串結束////////////////////////////
//字符串“2008-07-12”的Unicode編碼
//8位小端格式
code uint8 SerialNumberStringDescriptor[22]={
22, //該描述符的長度為22字節
0x03, //字符串描述符的類型編碼為0x03
0x32, 0x00, //2
0x30, 0x00, //0
0x30, 0x00, //0
0x38, 0x00, //8
0x2d, 0x00, //-
0x30, 0x00, //0
0x37, 0x00, //7
0x2d, 0x00, //-
0x31, 0x00, //1
0x32, 0x00 //2
};
//////////////////////產品序列號字符串結束/////////////////////////
/********************************************************************
函數功能:延時x毫秒函數。
入口參數:x:延時的毫秒數。
返 回:無。
備 注:無。
********************************************************************/
void DelayXms(uint16 x)
{
uint16 i;
uint16 j;
for(i=0;i<x;i++)
for(j=0;j<227;j++); //循環語句延時
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函數功能:USB斷開連接函數。
入口參數:無。
返 回:無。
備 注:無。
********************************************************************/
void UsbDisconnect(void)
{
#ifdef DEBUG0
Prints("斷開USB連接。\r\n");
#endif
D12WriteCommand(D12_SET_MODE); //寫設置模式命令
D12WriteByte(0x06); //設置模式的第一字節
D12WriteByte(0x47); //設置模式的第二字節
DelayXms(1000); //延遲1秒
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函數功能:USB連接函數。
入口參數:無。
返 回:無。
備 注:無。
********************************************************************/
void UsbConnect(void)
{
#ifdef DEBUG0
Prints("連接USB。\r\n");
#endif
D12WriteCommand(D12_SET_MODE); //寫設置模式命令
D12WriteByte(0x16); //設置模式的第一字節
D12WriteByte(0x47); //設置模式的第二字節
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函數功能:總線掛起中斷處理函數。
入口參數:無。
返 回:無。
備 注:無。
********************************************************************/
void UsbBusSuspend(void)
{
#ifdef DEBUG0
Prints("USB總線掛起。\r\n");
#endif
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函數功能:總線復位中斷處理函數。
入口參數:無。
返 回:無。
備 注:無。
********************************************************************/
void UsbBusReset(void)
{
#ifdef DEBUG0
Prints("USB總線復位。\r\n");
#endif
Ep1InIsBusy=0; //復位后端點1輸入緩沖區空閑。
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函數功能:根據pData和SendLength將數據發送到端點0的函數。
入口參數:無。
返 回:無。
備 注:無。
********************************************************************/
void UsbEp0SendData(void)
{
//將數據寫到端點中去準備發送
//寫之前要先判斷一下需要發送的數據是否比端點0
//最大長度大,如果超過端點大小,則一次只能發送
//最大包長的數據。端點0的最大包長在DeviceDescriptor[7]
if(SendLength>DeviceDescriptor[7])
{
//按最大包長度發送
D12WriteEndpointBuffer(1,DeviceDescriptor[7],pSendData);
//發送后剩余字節數減少最大包長
SendLength-=DeviceDescriptor[7];
//發送一次后指針位置要調整
pSendData+= DeviceDescriptor[7];
}
else
{
if(SendLength!=0)
{
//不夠最大包長,可以直接發送
D12WriteEndpointBuffer(1,SendLength,pSendData);
//發送完畢后,SendLength長度變為0
SendLength=0;
}
else //如果要發送的數據包長度為0
{
if(NeedZeroPacket==1) //如果需要發送0長度數據
{
D12WriteEndpointBuffer(1,0,pSendData); //發送0長度數據包
NeedZeroPacket=0; //清需要發送0長度數據包標志
}
}
}
}
////////////////////////End of function//////////////////////////////
/********************************************************************
函數功能:端點0輸出中斷處理函數。
入口參數:無。
返 回:無。
備 注:無。
********************************************************************/
void UsbEp0Out(void)
{
#ifdef DEBUG0
Prints("USB端點0輸出中斷。\r\n");
#endif
//讀取端點0輸出最后傳輸狀態,該操作清除中斷標志
//并判斷第5位是否為1,如果是,則說明是建立包
if(D12ReadEndpointLastStatus(0)&0x20)
{
D12ReadEndpointBuffer(0,16,Buffer); //讀建立過程數據
D12AcknowledgeSetup(); //應答建立包
D12ClearBuffer(); //清緩沖區
//將緩沖數據填到設備請求的各字段中
bmRequestType=Buffer[0];
bRequest=Buffer[1];
wValue=Buffer[2]+(((uint16)Buffer[3])<<8);
wIndex=Buffer[4]+(((uint16)Buffer[5])<<8);
wLength=Buffer[6]+(((uint16)Buffer[7])<<8);
//下面的代碼判斷具體的請求,并根據不同的請求進行相關操作
//如果D7位為1,則說明是輸入請求
if((bmRequestType&0x80)==0x80)
{
//根據bmRequestType的D6~5位散轉,D6~5位表示請求的類型
//0為標準請求,1為類請求,2為廠商請求。
switch((bmRequestType>>5)&0x03)
{
case 0: //標準請求
#ifdef DEBUG0
Prints("USB標準輸入請求:");
#endif
//USB協議定義了幾個標準輸入請求,我們實現這些標準請求即可
//請求的代碼在bRequest中,對不同的請求代碼進行散轉
//事實上,我們還需要對接收者進行散轉,因為不同的請求接收者
//是不一樣的。接收者在bmRequestType的D4~D0位中定義。
//我們這里為了簡化操作,有些就省略了對接收者的判斷。
//例如獲取描述符的請求,只根據描述符的類型來區別。
switch(bRequest)
{
case GET_CONFIGURATION: //獲取配置
#ifdef DEBUG0
Prints("獲取配置。\r\n");
#endif
break;
case GET_DESCRIPTOR: //獲取描述符
#ifdef DEBUG0
Prints("獲取描述符——");
#endif
//對描述符類型進行散轉,對于全速設備,
//標準請求只支持發送到設備的設備、配置、字符串三種描述符
switch((wValue>>8)&0xFF)
{
case DEVICE_DESCRIPTOR: //設備描述符
#ifdef DEBUG0
Prints("設備描述符。\r\n");
#endif
pSendData=DeviceDescriptor; //需要發送的數據
//判斷請求的字節數是否比實際需要發送的字節數多
//這里請求的是設備描述符,因此數據長度就是
//DeviceDescriptor[0]。如果請求的比實際的長,
//那么只返回實際長度的數據
if(wLength>DeviceDescriptor[0])
{
SendLength=DeviceDescriptor[0];
if(SendLength%DeviceDescriptor[7]==0) //并且剛好是整數個數據包時
{
NeedZeroPacket=1; //需要返回0長度的數據包
}
}
else
{
SendLength=wLength;
}
//將數據通過EP0返回
UsbEp0SendData();
break;
case CONFIGURATION_DESCRIPTOR: //配置描述符
#ifdef DEBUG0
Prints("配置描述符。\r\n");
#endif
pSendData=ConfigurationDescriptor; //需要發送的數據為配置描述符
//判斷請求的字節數是否比實際需要發送的字節數多
//這里請求的是配置描述符集合,因此數據長度就是
//ConfigurationDescriptor[3]*256+ConfigurationDescriptor[2]。
//如果請求的比實際的長,那么只返回實際長度的數據
SendLength=ConfigurationDescriptor[3];
SendLength=SendLength*256+ConfigurationDescriptor[2];
if(wLength>SendLength)
{
if(SendLength%DeviceDescriptor[7]==0) //并且剛好是整數個數據包時
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -