关于stm32的USB学习笔记之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设备的状态
WORD USB_DeviceStatus;
//用来存储设备的地址
BYTE USB_DeviceAddress;
//用来存储USB当前使用的设备的配置
BYTE USB_Configuration;
//此配置使用端点
DWORD USB_EndPointMask;
//用于标志此端点是否已经被停止0~15依次代表15个端点
DWORD USB_EndPointHalt;
//此配置使用的接口数
BYTE USB_NumInterfaces;
//每个接口可用的当前接口可替换值
BYTE USB_AltSetting[USB_IF_NUM];
/*用于临时存储控制传输时的数据包*/
USB_SETUP_PACKET SetupPacket;
/*用于向主机发送数据的EP0的数据结构*/
USB_EP_DATA EP0Data;
/*EP0Buf用于向USB发送数据时用的缓冲区*/
BYTE EP0Buf[USB_MAX_PACKET0];
/*功能:复位USB的一些数据标志
*参数:无
*返回值:无
*/
void USB_ResetCore(void)
{
//默认为总线供电,因为我们的USB现在不都是插在电脑上才能工作的么&^_^
USB_DeviceStatus = USB_POWER;
//在枚举之初地址当然是0
USB_DeviceAddress = 0;
//配置描述符的标识从1开始,这里也先置为0
USB_Configuration = 0;
//目前使用的是端点0
USB_EndPointMask = 0x00010001;
//没有停止的端点
USB_EndPointHalt = 0x00000000;
}
/*功能:建立阶段,读取建立数据包
*参数:无
*返回值:无
*/
void USB_SetupStage(void)
{
USB_ReadEP(0x00,(BYTE*)&SetupPacket);
}
/*功能:建立阶段,In握手包
*参数:无
*返回值:无
*/
void USB_StatusInStage(void)
{
USB_WriteEP(0x80,NULL,0);
}
/*功能:建立阶段,Out握手包
*参数:无
*返回值:无
*/
void USB_StatusOutStage(void)
{
USB_ReadEP(0x00,EP0Buf);
}
/*功能:数据In阶段
*参数:无
*返回值:无
*/
void USB_DataInStage(void)
{
DWORD cnt;
//先计算引次要发送多少数据
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;
}
/*功能:数据Out阶段
*参数:无
*返回值:无
*/
void USB_DataOutStage(void)
{
DWORD cnt;
cnt = USB_ReadEP(0x00,EP0Data.pData);
EP0Data.pData+=cnt;
EP0Data.Count-=cnt;
}
/*功能:获取USB设备的状态
*参数:无
*返回值:TRUE --->成功
* FALSE --->错误
*/
__inline BOOL USB_GetStatus(void)
{
DWORD n,m;
switch(SetupPacket.bmRequestType.BM.Recipient)
{
//接收端是设备
case REQUEST_TO_DEVICE:
//返回设备状态给他
EP0Data.pData = (BYTE *)&USB_DeviceStatus;
//将状态信息发送给主机
USB_DataInStage();
break;
//接收端是接口
case REQUEST_TO_INTERFACE:
/*配置描述符的标识从1开始,并且请求的接口号不能大于接口的数目,因为接口数目从0开始
*因为我们接口描述符中的接口号是一个字节所以这里wIndex中的数据中人低字节有效
*/
if((USB_Configuration !=0)&&(SetupPacket.wIndex.WB.L < USB_NumInterfaces))
{
//清0两个字节,因为根据USB协议此处必须返回0
*((__packed WORD *)EP0Buf) = 0;
EP0Data.pData = EP0Buf;
//发送给主机
USB_DataInStage();
}
//此接口出现了错误
else
return FALSE;
break;
case REQUEST_TO_ENDPOINT:
//端点号高1位0方向,低4位为端点号
n = SetupPacket.wIndex.WB.L & 0x8f;
//m的高16位代表in端点的标志,低16位代表out端点的标志
m = (n&0x80)?(1<<16 )<< (n&0x0f) :(1< //如果配置标识不为0,或配置标识为0,但是是端点0时,才算正常 if((USB_Configuration !=0)||((n&0x0f)==0)&&(USB_EndPointMask & m)) { //查看此端点是否已经停用 *((__packed WORD *)EP0Buf) = (USB_EndPointHalt &m )?1:0; EP0Data.pData = EP0Buf; //将数据发送给主机 USB_DataInStage(); } //说明配置描述符出了问题 else return FALSE; break; default: return FALSE; } return TRUE; } /*功能:设置/清除USB设备的特征 *参数:sc 0----->清除 1----->设置 *返回值:TRUE --->成功 * FALSE --->错误 */ __inline BOOL USB_SetClrFeature(DWORD sc) { DWORD n,m; switch(SetupPacket.bmRequestType.BM.Recipient) { //接收端是设备,则清除或设置设备的特性 case REQUEST_TO_DEVICE: if(SetupPacket.wValue.W == USB_FEATURE_REMOTE_WAKEUP) { if(sc) { printf("设置设备远程唤醒特性rn"); //设置USB状态为使能远程唤醒 USB_DeviceStatus |= USB_GETSTATUS_REMOTE_WAKEUP; /*stm32硬件本身就支持远程唤醒,这里就不用设置了 *当然,软件支不支持在于对中断屏蔽位的设置 */ } else