本帖最后由 dong_abc 于 2011-5-4 00:59 编辑
首先建议看看午夜粪车的笔记
USB之枚举--午夜粪车的笔记.rar
(21.61 KB)
然后再建议看看五谷道场的笔记
USB之数据包阐述--五谷道场的笔记.rar
(26.87 KB)
看了上面的笔记再看例程便很容易理解了,当然USB通信里的一些协议和细节就要去查阅相关资料了
/*******************************************************************
main.c file
USB HID设备实例(USB鼠标/键盘),分析官方例程做的笔记,希望能给比我
还菜的鸟带来点小小帮助。按住HOT学习板中间那个按键,鼠标便往右移动
********************************************************************/
#include "main.h"
/********************************************************************
函数功能:系统初始化。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void Sys_Init(void)
{
UNLOCKREG(); // 芯片注册解锁
SYSCLK->PWRCON.XTL12M_EN = 1; // 设定12M外部晶振
DrvSYS_Delay(5000); // 等待时钟就绪
/*
在主程序中,PLL时钟频率应该设置为48MHz,因为USB PHY也要PLL提供
时钟信号,系统时钟设置为外部12MHz,用来处理USB和HID的事件。
*/
DrvSYS_SetPLLMode(0); // Enable PLL
DrvSYS_Delay(1000);
DrvSYS_SelectHCLKSource(2); // Switch to PLL clock
DrvSYS_Delay(100);
SystemCoreClockUpdate(); // Update system core clock
Uart_Init(); // 串口初始化配置
GPIOB->IEN = (1 << 15); // GPIOB_15中断使能
NVIC_EnableIRQ(EINT1_IRQn); // EINT1中断使能
}
void PowerDown(void)
{
printf("Enter power down ...\n");
UNLOCKREG();
/* Wakeup Enable */
USBD->INTEN.WAKEUP_EN = 1;
/* Deep sleep */
outp32(0xE000ED10, 4);
SYSCLK->PWRCON.PD_WAIT_CPU = 1;
SYSCLK->PWRCON.PWR_DOWN = 1;
__WFI();
SYSCLK->PWRCON.PWR_DOWN = 0;
if(DrvUSB_GetUsbState() & eDRVUSB_SUSPENDED)
{
/* Note HOST to resume USB tree if it is suspended and remote wakeup enabled */
if(DrvUSB_IsRemoteWakeupEnabled())
{
/* Enable PHY before sending Resume('K') state */
USBD->ATTR.PHY_EN = 1;
/* Keep remote wakeup for 1 ms */
USBD->ATTR.RWAKEUP = 1;
DrvSYS_Delay(1000); /* Delay 1ms */
USBD->ATTR.RWAKEUP = 0;
}
}
printf("device wakeup!\n");
}
/********************************************************************
函数功能:系统主函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
int main (void)
{
int32_t i32Ret = 0;
E_DRVUSB_STATE eUsbState;
Sys_Init();
/*
硬件初始化完成后,执行函数DrvUSB_Open() 来为HID设备初始化USB端点信息结构,
现在系统准备好使能中断并等待插入USB主机。插入USB主机后,USB状态将从
eDRVUSB_DETACHED 变为eDRVUSB_ATTACHED ,插入主机后执行函数HID_Init
来初始化HID供应商描述符为HID键盘或者HID鼠标。
这个函数可以用来复位USB 控制器,初始化USB 端点、中断和USB 驱动结构。
如果在调用DrvUSB_Open 之前,USB 已经插入,函数DrvUSB_Open 会处理这
种情况。用户在调用DrvUSB_Open 之前必须填好结构sEpDescription 和g_sBusOps.
DrvUSB_DispatchEvent便是用来写入sEpDescription 和g_sBusOps.
*/
i32Ret = DrvUSB_Open((void *)DrvUSB_DispatchEvent);
if(i32Ret != 0)
return i32Ret;
while(1)
{
_DRVUSB_ENABLE_MISC_INT(0); //使能/关闭各种USB 中断.
_DRVUSB_ENABLE_FLDET_INT(); //使能 float-detection 中断.USB 插入/拔出将发生中断
//设置HID报告描述符和报告缓冲区
HID_Init();
//使能各种USB中断.
_DRVUSB_ENABLE_MISC_INT(INTEN_WAKEUP | INTEN_WAKEUPEN | INTEN_FLDET | INTEN_USB | INTEN_BUS);
PowerDown(); //PowerDown直到USB 设备已经连接到主机.
//检测USB总线并分派USB相关事件,一直到拔出USB主机
while(1)
{
/*
USB 状态描述
eDRVUSB_DETACHED: USB 设备已经脱离主机.
eDRVUSB_ATTACHED: USB 设备已经连接到主机.
eDRVUSB_POWERED: The USB is powered.
eDRVUSB_DEFAULT: 缺省USB 状态.
eDRVUSB_ADDRESS: USB 设备已经被分配地址.
eDRVUSB_CONFIGURED: USB设备已经被设置CONFIGURATION.
eDRVUSB_SUSPENDED: USB 暂停.
*/
eUsbState = DrvUSB_GetUsbState();
//USB 设备已经脱离主机
if (eUsbState == eDRVUSB_DETACHED)
{
printf("USB Detached!\n");
break;
}
//USB 设备已经暂停
if(eUsbState & eDRVUSB_SUSPENDED)
{
PowerDown();
}
//USB设备已经被设置CONFIGURATION
if (eUsbState == eDRVUSB_CONFIGURED)
{
HID_SetInReport(); //HID设备传输中断返回报告
}
}
_DRVUSB_ENABLE_MISC_INT(0); //使能/关闭各种USB 中断.
}
}
NUC1xx_HID_V1.0.rar
(425.89 KB)
|