📄 usb.c
字号:
/************************************************************************************
本程序仅供广大电子爱好者制作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 + -