關(guān)于stm32的USB學(xué)習(xí)筆記之usbcore.c
[cpp] view plaincopyprint?
#include
#include "usbreg.h"
#include "usbcore.h"
#include "usbuser.h"
#include "usbcfg.h"
#include "usb.h"
#include "usb_hw.h"
#include "usbdesc.h"
#include "hid.h"
#include "hiduser.h"
#define _DEBUG_
#include "debug.h"
#pragma diag_suppress 111,1441
//用來指示USB設(shè)備的狀態(tài)
WORD USB_DeviceStatus;
//用來存儲設(shè)備的地址
BYTE USB_DeviceAddress;
//用來存儲USB當(dāng)前使用的設(shè)備的配置
BYTE USB_Configuration;
//此配置使用端點
DWORD USB_EndPointMask;
//用于標(biāo)志此端點是否已經(jīng)被停止0~15依次代表15個端點
DWORD USB_EndPointHalt;
//此配置使用的接口數(shù)
BYTE USB_NumInterfaces;
//每個接口可用的當(dāng)前接口可替換值
BYTE USB_AltSetting[USB_IF_NUM];
/*用于臨時存儲控制傳輸時的數(shù)據(jù)包*/
USB_SETUP_PACKET SetupPacket;
/*用于向主機發(fā)送數(shù)據(jù)的EP0的數(shù)據(jù)結(jié)構(gòu)*/
USB_EP_DATA EP0Data;
/*EP0Buf用于向USB發(fā)送數(shù)據(jù)時用的緩沖區(qū)*/
BYTE EP0Buf[USB_MAX_PACKET0];
/*功能:復(fù)位USB的一些數(shù)據(jù)標(biāo)志
*參數(shù):無
*返回值:無
*/
void USB_ResetCore(void)
{
//默認(rèn)為總線供電,因為我們的USB現(xiàn)在不都是插在電腦上才能工作的么&^_^
USB_DeviceStatus = USB_POWER;
//在枚舉之初地址當(dāng)然是0
USB_DeviceAddress = 0;
//配置描述符的標(biāo)識從1開始,這里也先置為0
USB_Configuration = 0;
//目前使用的是端點0
USB_EndPointMask = 0x00010001;
//沒有停止的端點
USB_EndPointHalt = 0x00000000;
}
/*功能:建立階段,讀取建立數(shù)據(jù)包
*參數(shù):無
*返回值:無
*/
void USB_SetupStage(void)
{
USB_ReadEP(0x00,(BYTE*)&SetupPacket);
}
/*功能:建立階段,In握手包
*參數(shù):無
*返回值:無
*/
void USB_StatusInStage(void)
{
USB_WriteEP(0x80,NULL,0);
}
/*功能:建立階段,Out握手包
*參數(shù):無
*返回值:無
*/
void USB_StatusOutStage(void)
{
USB_ReadEP(0x00,EP0Buf);
}
/*功能:數(shù)據(jù)In階段
*參數(shù):無
*返回值:無
*/
void USB_DataInStage(void)
{
DWORD cnt;
//先計算引次要發(fā)送多少數(shù)據(jù)
if(EP0Data.Count > USB_MAX_PACKET0)
cnt = USB_MAX_PACKET0;
else
cnt = EP0Data.Count;
//這里寫端點卻主機讀,則將Dir位置1
cnt = USB_WriteEP(0x80,EP0Data.pData,cnt);
EP0Data.pData += cnt;
EP0Data.Count -= cnt;
}
/*功能:數(shù)據(jù)Out階段
*參數(shù):無
*返回值:無
*/
void USB_DataOutStage(void)
{
DWORD cnt;
cnt = USB_ReadEP(0x00,EP0Data.pData);
EP0Data.pData+=cnt;
EP0Data.Count-=cnt;
}
/*功能:獲取USB設(shè)備的狀態(tài)
*參數(shù):無
*返回值:TRUE --->成功
* FALSE --->錯誤
*/
__inline BOOL USB_GetStatus(void)
{
DWORD n,m;
switch(SetupPacket.bmRequestType.BM.Recipient)
{
//接收端是設(shè)備
case REQUEST_TO_DEVICE:
//返回設(shè)備狀態(tài)給他
EP0Data.pData = (BYTE *)&USB_DeviceStatus;
//將狀態(tài)信息發(fā)送給主機
USB_DataInStage();
break;
//接收端是接口
case REQUEST_TO_INTERFACE:
/*配置描述符的標(biāo)識從1開始,并且請求的接口號不能大于接口的數(shù)目,因為接口數(shù)目從0開始
*因為我們接口描述符中的接口號是一個字節(jié)所以這里wIndex中的數(shù)據(jù)中人低字節(jié)有效
*/
if((USB_Configuration !=0)&&(SetupPacket.wIndex.WB.L < USB_NumInterfaces))
{
//清0兩個字節(jié),因為根據(jù)USB協(xié)議此處必須返回0
*((__packed WORD *)EP0Buf) = 0;
EP0Data.pData = EP0Buf;
//發(fā)送給主機
USB_DataInStage();
}
//此接口出現(xiàn)了錯誤
else
return FALSE;
break;
case REQUEST_TO_ENDPOINT:
//端點號高1位0方向,低4位為端點號
n = SetupPacket.wIndex.WB.L & 0x8f;
//m的高16位代表in端點的標(biāo)志,低16位代表out端點的標(biāo)志
m = (n&0x80)?(1<<16 )<< (n&0x0f) :(1< //如果配置標(biāo)識不為0,或配置標(biāo)識為0,但是是端點0時,才算正常 if((USB_Configuration !=0)||((n&0x0f)==0)&&(USB_EndPointMask & m)) { //查看此端點是否已經(jīng)停用 *((__packed WORD *)EP0Buf) = (USB_EndPointHalt &m )?1:0; EP0Data.pData = EP0Buf; //將數(shù)據(jù)發(fā)送給主機 USB_DataInStage(); } //說明配置描述符出了問題 else return FALSE; break; default: return FALSE; } return TRUE; } /*功能:設(shè)置/清除USB設(shè)備的特征 *參數(shù):sc 0----->清除 1----->設(shè)置 *返回值:TRUE --->成功 * FALSE --->錯誤 */ __inline BOOL USB_SetClrFeature(DWORD sc) { DWORD n,m; switch(SetupPacket.bmRequestType.BM.Recipient) { //接收端是設(shè)備,則清除或設(shè)置設(shè)備的特性 case REQUEST_TO_DEVICE: if(SetupPacket.wValue.W == USB_FEATURE_REMOTE_WAKEUP) { if(sc) { printf("設(shè)置設(shè)備遠(yuǎn)程喚醒特性rn"); //設(shè)置USB狀態(tài)為使能遠(yuǎn)程喚醒 USB_DeviceStatus |= USB_GETSTATUS_REMOTE_WAKEUP; /*stm32硬件本身就支持遠(yuǎn)程喚醒,這里就不用設(shè)置了 *當(dāng)然,軟件支不支持在于對中斷屏蔽位的設(shè)置 */ } else