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

📄 usb.c

📁 51单片机硬盘MP3播放器 的原理图及源代码 增加了USB下载文件功能; 汉字LCD显示功能;子文件夹功能等。并对软件做了一些修改。并将硬件电路图画出来了。由于做得仓促
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************************
  本程序仅供广大电子爱好者制作MP3学习和参考使用,不得用于其它用途,否则后果自负

   USB.C File
   Created by Computer-lov. Date: 2004.9.27
   Last edited date: 2005.5.31
   version 1.1
   Copyright (c) 2005 Computer-lov
   All rigths reserved
*************************************************************************************/

#include "AT89C51SND1C.H"
#include "USB.H"
#include "MASS_STORAGE.H"
#include "IDE.h"
#include "LCD.H"
#include "hardware.h"
#include "keyboard.h"
#include "mp3.h"


CONTROL_DATA_BUFF xdata Control_Data;

CBW xdata cbw;
CSW xdata csw;

unsigned char bdata SCSI_Register;
sbit SCSI_Command    =   SCSI_Register^0;
sbit SCSI_Data       =   SCSI_Register^1;


unsigned char *pData;

unsigned char code DISK_INF[36]
=                                      //磁盘信息
{
 0x00,
 0x00,
 0x02,
 0x02,
 0x1F,
 0x00,0x00,0x00,
 0x49,0x44,0x45,0xA1,0xFA,0x55,0x53,0x42, 
 0xC1,0xF5,0xC8,0xD9,0xD7,0xD4,0xBC,0xBA,0xD7,0xF6,0xB5,0xC4,0x4D,0x50,0x33,0x20,
 0x31,0x2E,0x30,0x31
};


code unsigned char SENSE[0x12]=                                      //模式探测返回数据
{
0x70, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned int SWAP(unsigned int temp)                                //高低字节交换
{
 unsigned char i;
 i=((unsigned char *)&temp)[0];
 ((unsigned char *)&temp)[0]=((unsigned char *)&temp)[1];
 ((unsigned char *)&temp)[1]=i;
 return temp;
}

unsigned char LSB(unsigned int temp)                                //取一个整数的低字节
{
 return (unsigned char)temp;
}

unsigned char MSB(unsigned int temp)                                //取一个整数的高字节
{
 return (unsigned char)(temp>>8);
}

code unsigned char LANGUAGE_ID[4]={0x04,0x03,0x09,0x04};            //字符串描述符所用的语言种类        

code unsigned char device_serial_number[18]=                         //设备序列号
{0x12,0x03,0x32,0x00,0x30,0x00,0x37,0x00,0x31,0x00,0x30,0x00,0x39,0x00,0x38,0x00,0x32,0x00};

code DEVICE_DESCRIPTOR_STRUCT device_descriptor=     //设备描述符
{
 sizeof(DEVICE_DESCRIPTOR_STRUCT),                   //设备描述符的字节数大小
 DEVICE_DESCRIPTOR,	                                 //设备描述符类型编号
 0x1001,                                             //USB版本号
 0x00,                                               //USB分配的设备类代码
 0x00,                                               //USB分配的子类代码
 0x00,                                               //USB分配的设备协议代码
 MAX_CONTROL_DATA_SIZE,                              //端点0的最大包大小
 0x7111,                                             //厂商编号
 0xf0ff,                                             //产品编号
 0x0100,                                             //设备出厂编号
 0x00,                                               //设备厂商字符串的索引
 0x00,                                               //描述产品字符串的索引
 0x02,                                               //描述设备序列号字符串的索引
 0x01                                                //可能的配置数量
};

typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
{
 CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;
 INTERFACE_DESCRIPTOR_STRUCT  interface_descritor;
 ENDPOINT_DESCRIPTOR_STRUCT  endpoint_descriptor[ENDPOINT_NUMBER];
}CON_INT_ENDP_DESCRIPTOR_STRUCT;

code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor=
{
//configuration_descriptor                                          //配置描述符
{
 sizeof(CONFIGURATION_DESCRIPTOR_STRUCT),                           //配置描述符的字节数大小
 CONFIGURATION_DESCRIPTOR,                                          //配置描述符类型编号
 (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+sizeof(INTERFACE_DESCRIPTOR_STRUCT)+sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)*256+
 (sizeof(CONFIGURATION_DESCRIPTOR_STRUCT)+sizeof(INTERFACE_DESCRIPTOR_STRUCT)+sizeof(ENDPOINT_DESCRIPTOR_STRUCT)*ENDPOINT_NUMBER)/256,
 0x01,                                                            //只包含一个接口
 0x01,                                                            //该配置的编号
 0x00,                                                            //iConfiguration字段
 0x80,                                                            //采用总线供电,不支持远程唤醒
 0xC8                                                            //从总线获取最大电流400mA
},
//interface_descritor                                             //接口描述符
{
 sizeof(INTERFACE_DESCRIPTOR_STRUCT),                             //接口描述符的字节数大小
 INTERFACE_DESCRIPTOR,                                            //接口描述符类型编号
 0x00,                                                            //接口编号为0
 0x00,                                                            //该接口描述符的编号
 ENDPOINT_NUMBER,                                                 //非0端点数量为2,只使用端点主端点输入和输出
 0x08,                                                            //USB大容量存储设备
 0x06,                                                            //使用的子类,为简化块命令
 0x50,                                                            //使用的协议,这里使用单批量传输协议
 0x00                                                             //接口描述符字符串索引
},

//endpoint_descriptor[]
{
 {                                                                //主端点输入描述
  sizeof(ENDPOINT_DESCRIPTOR_STRUCT),                             //端点描述符的字节数大小
  ENDPOINT_DESCRIPTOR,                                            //端点描述符类型编号
  MAIN_POINT_IN,                                                        //端点号,主输入端点
  ENDPOINT_TYPE_BULK,                                             //使用的传输类型,批量传输
  0x4000,                                                         //该端点支持的最大包尺寸,64字节
  0x00                                                            //中断扫描时间,对批量传输无效
 },
  
 {                                                                //主端点输出描述
  sizeof(ENDPOINT_DESCRIPTOR_STRUCT),                             //端点描述符的字节数大小
  ENDPOINT_DESCRIPTOR,                                            //端点描述符类型编号
  MAIN_POINT_OUT,                                                 //端点号,主输出端点
  ENDPOINT_TYPE_BULK,                                             //使用的传输类型,批量传输
  0x4000,                                                         //该端点支持的最大包尺寸,64字节
  0x00                                                            //中断扫描时间,对批量传输无效
 }
}
};


unsigned int bdata usb_flags_Register;   //程序标志位

sbit USB__bus_reset       = usb_flags_Register^0;
sbit USB_suspend          = usb_flags_Register^1;
sbit USB_remote_wakeup    = usb_flags_Register^2;
sbit USB_int_isr          = usb_flags_Register^3;
sbit USB_not_end          = usb_flags_Register^4;
sbit USB_usb_idle         = usb_flags_Register^5;
sbit USB_usb_busy         = usb_flags_Register^6;
sbit USB_setup_packet_in  = usb_flags_Register^7;
sbit USB_setup_packet_out = usb_flags_Register^8;
sbit USB_set_addr         = usb_flags_Register^9;
sbit USB_usb_endp0_in     = usb_flags_Register^10;
sbit USB_usb_endp1_in     = usb_flags_Register^11;
sbit USB_usb_endp2_out    = usb_flags_Register^12;


unsigned char bdata status_Register;  ////状态寄存器

sbit status_control_out_port   =  status_Register^0;
sbit status_control_in_port    =  status_Register^1;
sbit status_main_out_port      =  status_Register^2;
sbit status_main_in_port       =  status_Register^3;
sbit status_bus_reset          =  status_Register^4;
sbit status_suspend_change     =  status_Register^5;
sbit status_setup_packet       =  status_Register^6;

//*****************   延时x毫秒函数 ***********
void delay(unsigned int x)                
{
 unsigned int i;
 unsigned int j;
 for(i=0;i<x;i++)
 for(j=0;j<230;j++);
}
//********************************************

unsigned char remove_enable;

void read_usb_status(void)             //读USB状态寄存器
{
 status_Register=0;
 if(EORINT){status_bus_reset=1;USBINT=USBINT & (~0x10);return;}
 if(SPINT){status_suspend_change=1;USBINT=USBINT & (~0x01);return;}
 UEPNUM=0;
 if(RXSETUP){status_setup_packet=1;status_control_out_port=1;return;}
 status_control_out_port = RXOUTB0;
 status_control_in_port  = NAKIN;
 cls_NAKIN();
 UEPNUM=1;
 status_main_in_port=NAKIN;
 cls_NAKIN();
 UEPNUM=2;
 status_main_out_port=(RXOUTB0 || RXOUTB1);
 USBINT=0x00;
}

void set_endpoint_enable(void)                  //端点使能
{
 UEPNUM=0;
 UEPCONX=0x80;
 UEPNUM=1;
 UEPCONX=0x86;
 UEPNUM=2;
 UEPCONX=0x82;
}


unsigned char error_count;
void error(unsigned char number)             //出错处理
{
 number=0;
 error_count++;
 LCD_go_home();
 prints("               ");
 LCD_line_feed();
 prints("               ");
 LCD_go_home();
 prints("Error:");
 printf(error_count);
}

unsigned char read_endpoint_buff(unsigned char endp,unsigned char len,unsigned char * buff)   //读终端点缓冲
{
 unsigned char i,j;
 UEPNUM=endp;               //选择端点
 j=UBYCTX;                  //读字节数
 if(j>len)j=len;
 for(i=0;i<j;i++)
  {
   buff[i]=UEPDATX;
  }
 if(RXOUTB0){UEPSTAX=UEPSTAX & (~0x42); return j;}   //清除RXOUTB0 位
 if(RXOUTB1){UEPSTAX=UEPSTAX & (~0x42); return j;}   //清除RXOUTB1 位
}

unsigned char write_endpoint_buff(unsigned char endp,unsigned char len,unsigned char * buff)    //写终端点缓冲
{
 unsigned char i;
 remove_enable=0;
 UEPNUM=endp;               //选择端点
 for(i=0;i<len;i++)         //填数据寄存器
  {
   UEPDATX=buff[i];
  }
 UEPSTAX=UEPSTAX | 0x10;     //设置TXRDY位
 while(!( UEPSTAX & 0x01 ));				//等待TXCMP
 UEPSTAX=UEPSTAX & (~0x01);					//清除TXCMP
 return len;
}

void disconnect_usb(void)
{
 USB_CONNECT=1;
 delay(100);
}

void connect_usb(void)                            //连接USB
{
 USB_CONNECT=0;
}

void init_usb(void)                              //初始化USB
{
 usb_flags_Register=0;
 SCSI_Command=1;
 SCSI_Data=0;
 csw.dCSWSignature=0x55534253;

 USBIEN=0x00;                                    //不允许USB中断
 USBCLK=0x03;                                   
 USBCON=0x80;
 set_endpoint_enable();
 UEPRST=0x07;                                    //端点FIFO复位
 UEPRST=0x00;
}

void usb_bus_reset(void)                         //USB总线复位处理
{
 usb_flags_Register=0;
 SCSI_Command=1;
 SCSI_Data=0;
 csw.dCSWSignature=0x55534253;
 USBADDR=0x80;
 LCD_go_home();
 prints("               ");
 LCD_line_feed();
 prints("               ");
 LCD_go_home();
 prints("移动硬盘模式");
 LCD_line_feed();
 prints("运行中......");
 remove_enable=0;
}

void usb_bus_suspend(void)                       //USB总线挂起处理
{
 LCD_go_home();
 prints("现在可以安全的 ");
 LCD_line_feed();
 prints("拔下USB 连线了 ");
 remove_enable=1;
}

void set_usb_address(void)                       //设置地址
{
 USB_set_addr=1;
 write_endpoint_buff(0,0,0);
 USBADDR=0x80 | (Control_Data.DeviceRequest.wValue);
 USBCON=USBCON | 0x01;
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
}

void get_status(unsigned char receiver)           //获取状态响应
{
 unsigned char status[2];
 switch (receiver)
  {
   case 0:                        //获取设备状态
    status[0]=0x00;
    status[1]=0x00;
    break;
   case 1:                        //获取接口状态
    status[0]=0x00;
    status[0]=0x00;
    break;
   case 2:                        //获取端点状态
    status[0]=0x00;
    status[1]=0x00;
    break;
   }
  UEPNUM=0;
  UEPSTAX=(UEPSTAX | 0x80);       //数据阶段的输入
  write_endpoint_buff(0,2,status);
  UEPSTAX=(UEPSTAX & (~0x80));
  USB_usb_endp0_in=0;
}

void clear_feature(unsigned char receiver)    
{
 receiver=0;
 write_endpoint_buff(0,0,0);
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
}

void set_feature(unsigned char receiver)
{
 receiver=0;
 write_endpoint_buff(0,0,0);
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
}

void set_descriptor(void)
{
 write_endpoint_buff(0,0,0);
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
}

void set_configuration(void)
{
 write_endpoint_buff(0,0,0);
 USBCON=USBCON | 0x02;
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
 UEPNUM=1;
 UEPCONX = 0x86 ;
 UEPNUM=2;
 UEPCONX = 0x82;
 LCD_go_home();
 prints("               ");
 LCD_line_feed();
 prints("               ");
 LCD_go_home();
 prints("移动硬盘模式");
 LCD_line_feed();
 prints("运行中......");
}

void get_configuration(void)               //获取配置状态
{
 unsigned char value=0x01;
 UEPNUM=0;
 UEPSTAX=(UEPSTAX | 0x80);       //数据阶段的输入
 write_endpoint_buff(0,1,&value);
 UEPSTAX=(UEPSTAX & (~0x80));
 USB_usb_endp0_in=0;
}

void set_interface(void)                   //设置接口
{
 write_endpoint_buff(0,0,0);
 USB_usb_endp0_in=0;
 USB_setup_packet_out=0;
}

void get_interface(void)                  //获取接口状态
{
 unsigned char value=0x01;
 UEPNUM=0;
 UEPSTAX=(UEPSTAX | 0x80);                //数据阶段的输入
 write_endpoint_buff(0,1,&value);

⌨️ 快捷键说明

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