⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc_usb.c

📁 IAR EWARM嵌入式系统编程与实践光盘源码
💻 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 + -