關(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
//用來(lái)指示USB設(shè)備的狀態(tài)
WORD USB_DeviceStatus;
//用來(lái)存儲(chǔ)設(shè)備的地址
BYTE USB_DeviceAddress;
//用來(lái)存儲(chǔ)USB當(dāng)前使用的設(shè)備的配置
BYTE USB_Configuration;
//此配置使用端點(diǎn)
DWORD USB_EndPointMask;
//用于標(biāo)志此端點(diǎn)是否已經(jīng)被停止0~15依次代表15個(gè)端點(diǎn)
DWORD USB_EndPointHalt;
//此配置使用的接口數(shù)
BYTE USB_NumInterfaces;
//每個(gè)接口可用的當(dāng)前接口可替換值
BYTE USB_AltSetting[USB_IF_NUM];
/*用于臨時(shí)存儲(chǔ)控制傳輸時(shí)的數(shù)據(jù)包*/
USB_SETUP_PACKET SetupPacket;
/*用于向主機(jī)發(fā)送數(shù)據(jù)的EP0的數(shù)據(jù)結(jié)構(gòu)*/
USB_EP_DATA EP0Data;
/*EP0Buf用于向USB發(fā)送數(shù)據(jù)時(shí)用的緩沖區(qū)*/
BYTE EP0Buf[USB_MAX_PACKET0];
/*功能:復(fù)位USB的一些數(shù)據(jù)標(biāo)志
*參數(shù):無(wú)
*返回值:無(wú)
*/
void USB_ResetCore(void)
{
//默認(rèn)為總線供電,因?yàn)槲覀兊腢SB現(xiàn)在不都是插在電腦上才能工作的么&^_^
USB_DeviceStatus = USB_POWER;
//在枚舉之初地址當(dāng)然是0
USB_DeviceAddress = 0;
//配置描述符的標(biāo)識(shí)從1開(kāi)始,這里也先置為0
USB_Configuration = 0;
//目前使用的是端點(diǎn)0
USB_EndPointMask = 0x00010001;
//沒(méi)有停止的端點(diǎn)
USB_EndPointHalt = 0x00000000;
}
/*功能:建立階段,讀取建立數(shù)據(jù)包
*參數(shù):無(wú)
*返回值:無(wú)
*/
void USB_SetupStage(void)
{
USB_ReadEP(0x00,(BYTE*)&SetupPacket);
}
/*功能:建立階段,In握手包
*參數(shù):無(wú)
*返回值:無(wú)
*/
void USB_StatusInStage(void)
{
USB_WriteEP(0x80,NULL,0);
}
/*功能:建立階段,Out握手包
*參數(shù):無(wú)
*返回值:無(wú)
*/
void USB_StatusOutStage(void)
{
USB_ReadEP(0x00,EP0Buf);
}
/*功能:數(shù)據(jù)In階段
*參數(shù):無(wú)
*返回值:無(wú)
*/
void USB_DataInStage(void)
{
DWORD cnt;
//先計(jì)算引次要發(fā)送多少數(shù)據(jù)
if(EP0Data.Count > USB_MAX_PACKET0)
cnt = USB_MAX_PACKET0;
else
cnt = EP0Data.Count;
//這里寫端點(diǎn)卻主機(jī)讀,則將Dir位置1
cnt = USB_WriteEP(0x80,EP0Data.pData,cnt);
EP0Data.pData += cnt;
EP0Data.Count -= cnt;
}
/*功能:數(shù)據(jù)Out階段
*參數(shù):無(wú)
*返回值:無(wú)
*/
void USB_DataOutStage(void)
{
DWORD cnt;
cnt = USB_ReadEP(0x00,EP0Data.pData);
EP0Data.pData+=cnt;
EP0Data.Count-=cnt;
}
/*功能:獲取USB設(shè)備的狀態(tài)
*參數(shù):無(wú)
*返回值:TRUE --->成功
* FALSE --->錯(cuò)誤
*/
__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ā)送給主機(jī)
USB_DataInStage();
break;
//接收端是接口
case REQUEST_TO_INTERFACE:
/*配置描述符的標(biāo)識(shí)從1開(kāi)始,并且請(qǐng)求的接口號(hào)不能大于接口的數(shù)目,因?yàn)榻涌跀?shù)目從0開(kāi)始
*因?yàn)槲覀兘涌诿枋龇械慕涌谔?hào)是一個(gè)字節(jié)所以這里wIndex中的數(shù)據(jù)中人低字節(jié)有效
*/
if((USB_Configuration !=0)&&(SetupPacket.wIndex.WB.L < USB_NumInterfaces))
{
//清0兩個(gè)字節(jié),因?yàn)楦鶕?jù)USB協(xié)議此處必須返回0
*((__packed WORD *)EP0Buf) = 0;
EP0Data.pData = EP0Buf;
//發(fā)送給主機(jī)
USB_DataInStage();
}
//此接口出現(xiàn)了錯(cuò)誤
else
return FALSE;
break;
case REQUEST_TO_ENDPOINT:
//端點(diǎn)號(hào)高1位0方向,低4位為端點(diǎn)號(hào)
n = SetupPacket.wIndex.WB.L & 0x8f;
//m的高16位代表in端點(diǎn)的標(biāo)志,低16位代表out端點(diǎn)的標(biāo)志
m = (n&0x80)?(1<<16 )<< (n&0x0f) :(1< //如果配置標(biāo)識(shí)不為0,或配置標(biāo)識(shí)為0,但是是端點(diǎn)0時(shí),才算正常 if((USB_Configuration !=0)||((n&0x0f)==0)&&(USB_EndPointMask & m)) { //查看此端點(diǎn)是否已經(jīng)停用 *((__packed WORD *)EP0Buf) = (USB_EndPointHalt &m )?1:0; EP0Data.pData = EP0Buf; //將數(shù)據(jù)發(fā)送給主機(jī) USB_DataInStage(); } //說(shuō)明配置描述符出了問(wèn)題 else return FALSE; break; default: return FALSE; } return TRUE; } /*功能:設(shè)置/清除USB設(shè)備的特征 *參數(shù):sc 0----->清除 1----->設(shè)置 *返回值:TRUE --->成功 * FALSE --->錯(cuò)誤 */ __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)然,軟件支不支持在于對(duì)中斷屏蔽位的設(shè)置 */ } else