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

📄 usb.c

📁 在msp430F149平台上使用CH375完成对U盘写文件的操作
💻 C
字号:
#include <msp430x14x.h>
#include <string.h>

#define  USB_RESET_ALL              0x05  /* 等40ms,执行硬件复位                                              */
#define  USB_CHECK_EXIST            0x06  /* 输入:任意数据 输出:按位取反 测试工作状态                        */
#define  SET_USB_MODE               0x15  /* 输入:模式代码 输出:操作状态(等20us) 设置工作模式                */
#define  USB_GET_STATUS             0x22  /* 输出:中断状态 获取中断状态并取消请求                             */
#define  USB_SET_BAUDRATE           0x02  /* 输入:分频系数和分频常数 输出:操作状态(等1ms) 设置串口通讯波特率 */
#define  RD_USB_DATA                0x28  /* 输出:数据长度和数据流 从当前USB中断的端点缓冲区读取数据块        */
#define  WR_USB_DATA7               0x2B  /* 输入:数据长度和数据流 向USB主机端点的输出缓冲器写入数据块        */
#define  USB_ABORT_NAK              0x17  /* 放弃当前NAK的重试                                                 */
#define  USB_DISK_INIT              0x51  /* 初始化USB存储设备 (产生中断)                                      */
#define  USB_DISK_SIZE              0x53  /* 获取USB存储设备的容量 (产生中断)                                  */
#define  USB_DISK_READ              0x54  /* 输入:LBA地址和扇区数 从USB存储设备读数据块 (产生中断)            */
#define  USB_DISK_RD_GO             0x55  /* 继续USB存储设备的读操作 (产生中断)                                */
#define  USB_DISK_WRITE             0x56  /* 输入:LBA地址和扇区数 向USB存储设备写数据块 (产生中断)            */
#define  USB_DISK_WR_GO             0x57  /* 继续USB存储设备的写操作 (产生中断)                                */
#define  USB_GET_IC_VER             0x01  /* 输出:版本号 获取芯片及固件版本                                   */
#define  USB_ENTER_SLEEP            0x03  /* 进入低功耗睡眠挂起状态                                            */
#define  USB_SET_DISK_LUN           0x0B  /* 输入:数据34H和逻辑单元号 设置USB存储设备的当前逻辑单元号         */
#define  USB_DISK_INQUIRY           0x58  /* 查询USB存储设备的特性 (产生中断)                                  */
#define  USB_DISK_READY             0x59  /* 检查USB存储设备是否就绪 (产生中断)                                */
#define  USB_DISK_R_SENSE           0x5A  /* 检查USB存储设备的错误 (产生中断)                                  */
#define  USB_DISK_MAX_LUN           0x5D  /* 获取USB存储设备的最大单元号 (产生中断)                            */
/*                                操作状态                                                                     */
#define  CMD_RET_SUCCESS            0x51  /* 操作成功                         */
#define  CMD_RET_ABORT              0x5F  /* 操作失败                         */
/*                                中断状态                                                                      */
#define  USB_INT_SUCCESS            0x14  /* 主机方式:USB事务或传输操作成功             */
#define  USB_INT_CONNECT            0x15  /* 主机方式:检测到USB设备连接事件             */
#define  USB_INT_DISCONNECT         0x16  /* 主机方式:检测到USB设备断开事件             */
#define  USB_INT_BUF_OVER           0x17  /* 主机方式:USB控制传输的数据太多,缓冲区溢出 */
#define  USB_INT_DISK_READ          0x1D  /* 主机方式:USB存储设备读操作,请求数据读出   */
#define  USB_INT_DISK_WRITE         0x1E  /* 主机方式:USB存储设备写操作,请求数据写入   */
#define  USB_INT_DISK_ERR           0x1F  /* 主机方式:USB存储设备操作失败               */
/*                                   其他                                                                       */
#define  USB_SUCCESS                0x00  /* USB函数操作成功                  */
#define  USB_ABORT                  0xFF  /* USB函数操作失败                  */

#define  USB_CS                     0x01  /* 片选控制输入(低电平有效)               */
#define  USB_INT                    0x02  /* 中断请求输出(低电平有效)               */
#define  USB_WR                     0x04  /* 写选通输入(低电平有效)                 */
#define  USB_RD                     0x08  /* 读选通输入(低电平有效)                 */
#define  USB_A0                     0x10  /* 地址线输入:A0 = 0写命令;A0 = 1读写数据 */

#define  USB_CTL_INIT()             {P2OUT = (P2OUT | 0x0F) & 0xEF;\
                                     P2DIR = (P2DIR | 0x1D) & 0xFD;}
#define  USB_DB_INIT()              {P1DIR = 0x00;}

#define  USB_CLRB(BIT)              {P2OUT &= ~BIT;}
#define  USB_SETB(BIT)              {P2OUT |= BIT;}
#define  USB_CTL_RESET()            {P2OUT = (P2OUT | 0x0F) & 0xEF;}

#define  USB_RD_INT()               (P2IN & USB_INT)

#define  USB_DB_SET(DATA)           {P1OUT = (DATA); P1DIR = 0xFF;}
#define  USB_DB_READ()              (P1DIR =  0x00 , P1IN  & 0xFF)
#define  USB_DB_RESET()             {P1DIR = 0x00;}

void     USB_SendCmd(char cmd)
{
  USB_DB_SET(cmd);            /* cmd -> D[0-7] */
  
  USB_CLRB(USB_CS);           /* CS:L, WR:L, A0:H, RD:H */
  USB_CLRB(USB_WR);           /* 写命令 */
  USB_SETB(USB_A0);
  USB_SETB(USB_RD);
  
  _NOP();
  _NOP();
  _NOP();
  
  USB_CTL_RESET();            /* CS:H, WR:H, A0:L, RD:H */
  USB_DB_RESET();             /* D[0-7]: input */
}

void     USB_SendData(char data)
{
  USB_DB_SET(data);           /* data -> D[0-7] */
  
  USB_CLRB(USB_CS);           /* CS:L, WR:L, A0:L, RD:H */
  USB_CLRB(USB_WR);           /* 写数据 */
  USB_CLRB(USB_A0);
  USB_SETB(USB_RD);
  
  _NOP();
  _NOP();
  _NOP();
  
  USB_CTL_RESET();            /* CS:H, WR:H, A0:L, RD:H */
  USB_DB_RESET();             /* D[0-7]: input */
}

char     USB_ReadData(void)
{
  char DB_Temp;
  
  USB_CLRB(USB_CS);           /* CS:L, WR:H, A0:L, RD:L */
  USB_SETB(USB_WR);           /* 读数据 */
  USB_CLRB(USB_A0);
  USB_CLRB(USB_RD);
  
  _NOP();
  _NOP();
  _NOP();
  _NOP();
  _NOP();
  _NOP();
  
  DB_Temp = USB_DB_READ();    /* D[0-7] -> DB_Temp */
  
  _NOP();
  _NOP();
  
  USB_CTL_RESET();            /* CS:H, WR:H, A0:L, RD:H */
  USB_DB_RESET();             /* D[0-7]: input */
  
  return DB_Temp;
}

void     USB_Delayms(unsigned int ms)
{
  /*
    适用于8MHz的时钟,不精确
  */
  while(ms--)                
  {
    for(int i = 2000;i != 0;i--);
  }
}

char     USB_WaitInt(void)
{
  char status;
  
  while(USB_RD_INT() != 0x00);
  USB_SendCmd(USB_GET_STATUS);
  status = USB_ReadData();
  
  return status;
}

char     USB_Init(void)
{
  USB_CTL_INIT();                 /* USB控制端初始化 */
  USB_DB_INIT();                  /* USB数据端初始化 */
  
  USB_SendCmd(USB_RESET_ALL);     /* CH375芯片复位 */
  USB_Delayms(40);
  
  USB_SendCmd(USB_CHECK_EXIST);   /* 检查芯片是否可以正常工作 */
  USB_SendData(0xAA);
  if(USB_ReadData() != 0x55)
  {
    return USB_ABORT;
  }
  
  USB_SendCmd(SET_USB_MODE);      /* 设置USB模式 */
  USB_SendData(0x06);             /* 已启动的主机模式,自动产生SOF包 */
  USB_Delayms(1);
  if(USB_ReadData() != CMD_RET_SUCCESS)
  {
    return USB_ABORT;
  }
  
  return USB_SUCCESS;
}

char     USB_ReadSec(unsigned long LBA, char *secBuffer)
{
  char status;
  
  USB_SendCmd(USB_DISK_READ);     /* 发出读扇区指令并指明目的扇区 */
  USB_SendData(LBA & 0xFF);
  USB_SendData((LBA >> 8) & 0xFF);
  USB_SendData((LBA >> 16) & 0xFF);
  USB_SendData((LBA >> 24) & 0xFF);
  USB_SendData(1);
  
  /*
    读出指定扇区的数据并存入secBuff
  */
  int index = 0;
  do
  {
    status = USB_WaitInt();
    if(status == USB_INT_DISK_READ)
    {
      /*
        一次读64个字节的数据
      */
      int length;
      USB_SendCmd(RD_USB_DATA);
      length = USB_ReadData();
      while(length--)
      {
        secBuffer[index++] = USB_ReadData();
      }
      
      /*
        这里需要延时一段时间,否则之后的操作会出现无法预知的行为!
      */
      USB_Delayms(1);
      USB_SendCmd(USB_DISK_RD_GO);   /* 发出继续读取的指令 */
    }
    else
    {
      break;
    }
  }while(1);
  
  if(status == USB_INT_SUCCESS)
  {
    return USB_SUCCESS;
  }
  else
  {
    return USB_ABORT;
  }
}

char     USB_WriteSec(unsigned long LBA, char *secBuffer)
{
  char status;
  
  USB_SendCmd(USB_DISK_WRITE);     /* 发出写扇区指令并指明目的扇区 */
  USB_SendData(LBA & 0xFF);
  USB_SendData((LBA >> 8) & 0xFF);
  USB_SendData((LBA >> 16) & 0xFF);
  USB_SendData((LBA >> 24) & 0xFF);
  USB_SendData(1); 
  
  int index = 0;
  do{
    status = USB_WaitInt();
    if(status == USB_INT_DISK_WRITE)
    {
      /*
        一次写64个字节的数据
      */      
      USB_SendCmd(WR_USB_DATA7);
      USB_SendData(64);
      for(int i = 0;i < 64;i++)
      {
        USB_SendData(secBuffer[index++]);
      }
      /*
        这里不能延时,否则之后的操作会出现无法预知的行为!
      */      
      USB_SendCmd(USB_DISK_WR_GO);
    }
    else
    {
      break;
    }
  }while(1);
  
  if(status == USB_INT_SUCCESS)
  {
    return USB_SUCCESS;
  }
  else
  {
    return USB_ABORT;
  }
}

typedef  struct _DIRDATA{
  char DIR_Name[11];
  char DIR_Attr;
  char DIR_NTRes;
  char DIR_CrtTimeTenth;
  int  DIR_CrtTime;
  int  DIR_CrtDate;
  int  DIR_LstAccDate;
  int  DIR_FstClusHI;
  int  DIR_WrtTime;
  int  DIR_WrtDate;
  int  DIR_FstClusLO;
  long DIR_FileSize;
}DIRDATA;

#define  INT_TO_DATE(i)         ((long)((i) & 0x1F) + \
                                 (long)(((i) >> 5) & 0x0F) * 100 + \
                                 (long)((((i) >> 9) & 0x7F) + 1980) * 10000)
#define  INT_TO_TIME(i)         ((long)((i) & 0x1F) * 2 + \
                                 (long)(((i) >> 5) & 0x3F) * 100 + \
                                 (long)(((i) >> 11) & 0x1F) * 10000)
int      DATE_TO_INT(long date)
{
  int i = 0;
  i += (int)((date / 10000 - 1980) << 9);
  date %= 10000;
  i += (int)((date / 100) << 5);
  date %= 100;
  i += (int)(date);
  return i;
}

int      TIME_TO_INT(long time)
{
  int i = 0;
  i += (int)((time / 10000) << 11);
  time %= 10000;
  i += (int)((time / 100) << 5);
  time %= 100;
  i += (int)(time / 2);
  return i;
}

char     secData[512];
void     main(void)
{
  WDTCTL = WDTPW+WDTHOLD;   
  
  USB_Init();  
  while(USB_WaitInt() != USB_INT_CONNECT);  
  USB_SendCmd(USB_DISK_INIT);
  while(USB_WaitInt() != USB_INT_SUCCESS);
  _NOP();

  USB_ReadSec(0x00000790, secData);
  _NOP();  
  char data[] = "Hello!";
  memset((void *)secData, 0, 512);
  memcpy((void *)secData, (void *)data, strlen(data));
  USB_WriteSec(0x00000792, secData);  
  USB_ReadSec(0x00000792, secData);
  _NOP();
  
  DIRDATA dData;
  USB_ReadSec(0x00000790, secData);
  _NOP();
  char name[11] = {'A', 'L', 'B', 'E', 'R', 'T', ' ', ' ', 'T', 'X', 'T'};
  memcpy((void *)(dData.DIR_Name), (void *)name, 11);
  dData.DIR_Attr = 0x20;
  dData.DIR_NTRes = 0x18;
  dData.DIR_CrtTimeTenth = 0x00;
  dData.DIR_CrtTime = TIME_TO_INT(133500);
  dData.DIR_CrtDate = DATE_TO_INT(20080307);
  dData.DIR_LstAccDate = DATE_TO_INT(20080307);
  dData.DIR_FstClusHI = 0x0000;
  dData.DIR_WrtTime = TIME_TO_INT(133500);
  dData.DIR_WrtDate = DATE_TO_INT(20080307);
  dData.DIR_FstClusLO = 0x0003;
  dData.DIR_FileSize = (long)strlen(data);
  int free = 0;
  for(free = 0;(secData[free] != 0xEB && secData[free] != 0x00) && (free < 512);
      free += 32);
  if(free < 512)
  {
    memcpy((void *)(&secData[free]), (void *)(&dData), sizeof(dData));
    USB_WriteSec(0x00000790, secData);
  }
  _NOP();
  
  USB_ReadSec(0x00000020, secData);
  _NOP();
  long link = 0x0FFFFFFF; 
  memcpy((void *)(&secData[12]), (void *)(&link), 4);
  USB_WriteSec(0x00000020, secData);
  _NOP();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -