📄 lpc_usb.c
字号:
// 定义主模块
#include "lpc_usb.h"
Fnpr IntrCallback;
/*************************************************************************
* 说明:USB_Cmd函数,执行USB引擎发送命令
* 参数:unsigned char Command
* unsigned char Data
* 返回值:unsigned int - 命令执行结果
*************************************************************************/
unsigned int USB_Cmd (unsigned short Command, unsigned char Data) {
unsigned int cpu_sr, tmp = 0;
cpu_sr = disable_interrupts(); // 禁止中断并保存当前中断标志状态
DEVINTCLR = USB_CommRegEmptyInterrupt + USB_CommDataFullInterrupt; //清除数据寄存器满和命令寄存器空中断
CMDCODE = ((Command&0xFF) << 16) + USB_CMD_WR; // 命令装入USB引擎
while ((DEVINTS & USB_CommRegEmptyInterrupt) == 0); // 等待直到命令被接受
DEVINTCLR = USB_CommRegEmptyInterrupt; // 清除命令寄存器空中断
switch (Command) { // 确定下一帧命令
case CMD_USB_SET_ADDRESS:
case CMD_USB_CFG_DEV:
case CMD_USB_SET_MODE:
case CMD_USB_SET_DEV_STAT:
CMDCODE = (Data << 16) + USB_DATA_WR;
while ((DEVINTS & USB_CommRegEmptyInterrupt) == 0);
break;
case CMD_USB_RD_FRAME_NUMB:
case CMD_USB_RD_TEST_REG:
CMDCODE = (Command << 16) + USB_DATA_RD;
while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
DEVINTCLR = USB_CommDataFullInterrupt;
tmp = CMDDATA;
CMDCODE = (Command << 16) + USB_DATA_RD;
while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
DEVINTCLR = USB_CommDataFullInterrupt;
tmp |= CMDDATA << 8;
break;
case CMD_USB_GET_DEV_STAT:
case CMD_USB_GET_ERROR:
case CMD_USB_RD_ERROR_STAT:
case CMD_USB_CLR_BUF:
CMDCODE = (Command << 16) + USB_DATA_RD;
while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
tmp = CMDDATA;
break;
default:
switch (Command & 0xE0) {
case CMD_USB_SEL_EP:
case CMD_USB_SEL_CLR_INT_EP:
CMDCODE = (Command << 16) + USB_DATA_RD;
while ((DEVINTS & USB_CommDataFullInterrupt) == 0);
tmp = CMDDATA;
break;
case CMD_USB_SET_EP_STAT:
CMDCODE = (Data << 16) + USB_DATA_WR;
while ((DEVINTS & USB_CommRegEmptyInterrupt) == 0);
break;
}
break;
}
DEVINTCLR = USB_CommRegEmptyInterrupt + USB_CommDataFullInterrupt;
restore_interrupts(cpu_sr); // 恢复中断标志
return(tmp);
}
/*************************************************************************
* 说明:USB_Init函数,USB总线初始化。
* 参数:int IntrSlot
* Fnpr UserIntrCallback
* USB_DEV_INT_PRIORITY_DEF DevIntrPrio
* 返回值:USB_ERROR_CODE_DEF
* 0: USB_OK
* 1: USB_ERROR
*************************************************************************/
USB_ERROR_CODES_DEF USB_Init(int IntrSlot, Fnpr UserIntrCallback,USB_DEV_INT_PRIORITY_DEF DevIntrPrio) {
int p = 1, m = 48000000 / FOSC, Fpll, i;
if (IntrSlot > VIC_Slot15) {
return(USB_INTR_ERROR);
}
for (i = 0; i < 4 ; ++i, p <<= 1) { //寻找合适的 P 值
Fpll = (FOSC << 1) * p * m;
if ((Fpll >= Fcco_MIN) && (Fpll <= Fcco_MAX)) {
break;
}
}
if (i >= 4) {
return(USB_PLL_ERROR); // 无法找到合适的 P 值
}
PM_OpenPeripheral(0x80000000); // 打开USB
PINSEL1_bit.P0_23 = 1; // 允许 Vbus 检测,1--连接正常,2--连接中
PINSEL1_bit.P0_31 = 2;
/* 为USB引擎初始化 PLL - 48MHz */
PLL48CFG_bit.MSEL = m-1;
PLL48CFG_bit.PSEL = i;
PLL48CON_bit.PLLE = true; // 允许 PLL
PLL48FEED = PLLFEED_DATA1;
PLL48FEED = PLLFEED_DATA2;
while (!PLL48STAT_bit.PLOCK); // 等待 PLL 锁定
PLL48CON_bit.PLLC = true; // 连接 PLL
PLL48FEED = PLLFEED_DATA1;
PLL48FEED = PLLFEED_DATA2;
IntrCallback = UserIntrCallback;
VIC_SetVectoredIRQ(USB_ISR,(LPC_VicIrqSlots_t)IntrSlot,VIC_USB); // USB中断连接到VIC
VIC_EnableInt(1<<VIC_USB);
DEVINTPRI = DevIntrPrio; // 初始化USB引擎
REALIZEENDP = ENDPINTEN = 0x3;// 初始化端点
ENDPINTCLR = 0xFFFFFFFF;
DEVINTCLR = 0x3FF; // 清除所有中断标志
DEVINTEN = 0x20E; // 允许所有中断
USBINTS_bit.EN_USB_INTS = 1; // 允许USB中断
return (USB_OK);
}
/*************************************************************************
* 说明:USB_RealizeEndPoint函数,允许或禁止端点。
* 参数:USB_ENDOPINT_DEF EndPoint - endpoiunt index
* int MaxPacketSize - When is 0 disable relevant endpoint
* USB_INT_PRIORITY_DEF IntrPriority
* int IntrEna
* 返回值:无
*************************************************************************/
void USB_RealizeEndPoint( USB_ENDOPINT_DEF EndPoint,int MaxPacketSize,
USB_INT_PRIORITY_DEF IntrPriority, int IntrEna) {
unsigned int Mask = (1 << EndPoint);
if (MaxPacketSize) {
REALIZEENDP |= Mask; // 端点实现
ENDPIND = EndPoint; // 设置端点数据最大包大小
MAXPACKSIZE = MaxPacketSize;
while ((DEVINTS & USB_EPRealizeInterrupt) == 0); // 等待实现完成
DEVINTCLR = USB_EPRealizeInterrupt; // 清除端点实现标志
if (IntrPriority) { // 设置端点中断优先级
ENDPINTPRI |= Mask;
}
ENDPINTCLR = Mask; // 清除端点终端标志
if (IntrEna) ENDPINTEN |= Mask; // 允许端点中断
}
else {
Mask =~ Mask;
REALIZEENDP &= Mask; // 禁止相关端点及中断
ENDPINTEN &= Mask;
}
}
/*************************************************************************
* 说明:USB_ClearBuffer函数,清除相关端点缓冲区。
* 参数:USB_ENDOPINT_DEF EndPoint - 端点索引
* 返回值:数据包覆盖状态
*************************************************************************/
unsigned int USB_ClearBuffer(USB_ENDOPINT_DEF EndPoint) {
USB_Cmd(CMD_USB_SEL_EP | EndPoint,0); // 选择端点
return(USB_Cmd(CMD_USB_CLR_BUF,0)); // 清除选择端点
}
/*************************************************************************
* 说明:USB_ValidateBuffer函数无,仅使输入端点有效。
* 参数:USB_ENDOPINT_DEF EndPoint - 端点索引
* 返回值:
*************************************************************************/
void USB_ValidateBuffer(USB_ENDOPINT_DEF EndPoint) {
if (EndPoint & 1) {
USB_Cmd(CMD_USB_SEL_EP | EndPoint,0);
USB_Cmd(CMD_USB_VAL_BUF,0);
}
}
/*************************************************************************
* 说明:USB_SetAdd函数,设置设备地址。
* 参数:unsigned int DevAdd - 设备地址为0 - 127
* 返回值:无
*************************************************************************/
void USB_SetAdd(unsigned int DevAdd) {
for(int i=2;i;--i) {
USB_Cmd(CMD_USB_SET_ADDRESS,DevAdd | 0x80);
}
}
/*************************************************************************
* 说明:USB_ISR中断函数。
* 参数:无
* 返回值:无
*************************************************************************/
void USB_ISR (void) {
IntrCallback();
VICVectAddr = 0; // 清除VIC中断
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -