📄 mainusb.c
字号:
#include<reg52.h>
#include<Absacc.h>
#include <intrins.h>
//#include <stdio.h>
//#include <string.h>
#define ENABLE EA=1
#define DISABLE EA=0
#define Cmdaddr 0x1000
#define Dataddr 0x0000
#define Setup_flag 0x01
#define Trans_flag 0x02
#define Uchar unsigned char
#define Uint unsigned int
#define SWAP(x) ((((x) & 0xFF) << 8) | (((x) >> 8) & 0xFF))
#define EP0_OUT 0x01
#define EP0_IN 0x02
#define EP1_OUT 0x04
#define EP1_IN 0x08
#define EP2_OUT 0x10
#define EP2_IN 0x20
#define BUS_RESET 0x40
#define SUSPCH 0x80
/****************************** Declare *************************************/
void InitSys();
void Delay(int);
void Disconnect();
void Connect();
void InitSerial();
void InitINT0();
void Readintregister(char *ir1,char *ir2);
void Ep0out();
void Ep0in();
void Ep1out();
void Ep1in();
void Ep2out();
void Ep2in();
void Busreset();
void Suspch();
void Dosetup();
void Readep(char,char);
void Writeep(char n, char len, char *p);
void Answerep(char);
void Prints(char *p);
void Printn(Uchar);
void Ep1trans(Uchar *p);
sbit CSUSB=P1^7;
sbit SUSP=P1^0;
sbit TestL=P1^4;
//Uchar Flagint; //中断标志,便于主程序区分中断类型
Uchar Flag; //系统的操作标志
Uchar Ep1leftsize=0;
Uchar *TestP;
Uchar *transp,translen; //发送长数据时用的临时变量
struct DEVICE_REQUEST //记录设备请求的结构体缓冲区
{
Uchar bmrequesttype;
Uchar brequest;
Uint wvalue;
Uint windex;
Uint wlength;
}Device_request;
struct DEVICE_DESCRIPTOR //固件_设备描述表的结构体
{
Uchar blength;
Uchar bdecriptortype;
Uint bcdusb;
Uchar bdeviceclass;
Uchar bdevicesubclass;
Uchar bdeviceportocol;
Uchar bmaxpacketsize0;
Uint idvendor;
Uint idproduct;
Uint bcddevice;
Uchar imanufacturer;
Uchar iproduct;
Uchar iserialnumber;
Uchar bnumconfigurations;
};
code struct DESCRIPTORS //固件_各类描述表(存储于ROM中)
{
struct DEVICE_DESCRIPTOR Device_descriptor;
}Descriptors=
{
0x12,
0x01,
SWAP(0x0110),
0xFF,
0xFF,
0,
16,
SWAP(0x0471),
SWAP(0x0666),
SWAP(0x0100),
0,
0,
0,
1
};
/****************************** Main() *************************************/
main()
{
Uchar i;
i=0;
InitSys();
Prints("\nOK! Let's begin:---> \n");
Prints("step_1\n");
while(1)
{
Delay(100);
Prints("step_");
Printn(i ++);
Prints("\n");
if(Flag&Setup_flag) //如果有Setup包进入
{
DISABLE;
Flag^=Setup_flag; //setup标志清除
ENABLE;
Dosetup(); //响应setup包
}
}
}
/****************************** Function *************************************/
void Prints(char *p)
{
while(*p!='\0')
{
if(*p == '\n')
{
SBUF = '\r';
}
Delay(7);
SBUF=*p++;
Delay(7);
}
}
void Printn(Uchar n)
{
Uchar m;
m=n/0x10; //高位
if(m<0x0A) SBUF=0x30+m;
else SBUF=0x41+m-0x0A;
Delay(7);
m=n%0x10; //低位
if(m<0x0A) SBUF=0x30+m;
else SBUF=0x41+m-0x0A;
Delay(3);
}
void InitSys(void)
{
/*
CSUSB=0; //片选D12
SUSP=0; //取消挂起,唤醒D12
TestL=1;
*/
P0 = 0xFF;
P1 = 0xFF;
P2 = 0xFF;
P3 = 0xFF;
CSUSB = 0x0;
SUSP = 0;
CSUSB=1;
CSUSB=0;
InitSerial();
InitINT0();
SUSP = 0;
Disconnect();
Delay(500);
Connect();
ENABLE; //使能中断
}
void InitSerial()
{
IE=IE|0x90; //初始化串口
SCON=0x50;
TMOD=TMOD|0x20; //Timer1工作在方式2下
TH1=0xFD; // 波特率 9600
TL1=0xFD;
TR1=1;
TI=0;
RI=0;
}
void InitINT0()
{
IE|=0x81;
IT0=0; //外部中断设置为电平触发
}
void Readintregister(char *ir1,char *ir2)
{
XBYTE[Cmdaddr]=0xF4;
*ir1=XBYTE[Dataddr];
*ir2=XBYTE[Dataddr];
return ;
}
void Dosetup()
{
Uchar type,req;
Uchar i;
type=Device_request.bmrequesttype;
req=Device_request.brequest;
Printn(req);
if(req==6) //如果设备请求为Get_Descriptor
{
//Prints("gd\t");
if(Device_request.wvalue==1) //如果要求获取的是设备描述符
{
transp=&Descriptors.Device_descriptor; //*transp指向设备描述符开头
//Flag|=Trans_flag; //传输标志置1,表示当前处于传输状态
//translen=sizeof(struct DEVICE_DESCRIPTOR);
//Printn(translen);
Writeep(1,16,transp);
//transp+=16;
//translen-=16;
translen=0;
}
}
else if(req==5) //如果设备请求为Set_address
{
XBYTE[Cmdaddr]=0xD0;
XBYTE[Dataddr]=(Uchar)(Device_request.wvalue/0x100);
Printn((Uchar)(Device_request.wvalue/0x100));
//for(transp=&Device_request,i=0;i<16;i++,transp++)
//Printn(*transp);
Writeep(1,0,0);
}
}
void Readep(char n,char *p)
{
char len,i;
XBYTE[Cmdaddr]=n; //选择端点
if(XBYTE[Dataddr]&0x01==0) //如果缓冲区为空
{
return;
}
//若不为空
XBYTE[Cmdaddr]=0xF0; //读缓冲区
len=XBYTE[Dataddr];
len=XBYTE[Dataddr];
if(len==0) return;
for(i=0;i<len;i++)
{
*p=XBYTE[Dataddr];
//Printn(*p);
p++;
}
XBYTE[Cmdaddr]=0xF2; //清空缓冲区
}
void Writeep(char n, char len, char *p)
{
char i;
XBYTE[Cmdaddr]=n; //选择端点
i=XBYTE[Dataddr]; //选读一个字节
XBYTE[Cmdaddr]=0xF0; //写缓冲区的命令
XBYTE[Dataddr]=0;
XBYTE[Dataddr]=len;
for(i=0;i<len;i++)
{
XBYTE[Dataddr]=*p;
//SBUF=*p;Delay(10);
p++;
}
XBYTE[Cmdaddr]=0xFA; //使能缓冲区
}
void Answerep(char n)
{
XBYTE[Cmdaddr]=n;
XBYTE[Cmdaddr]=0xF1;
if(n==0) //若0收到setup包,writeep中的清除缓冲区命令是无效的;
XBYTE[Cmdaddr]=0xF2; //在此,应答了setup之后的清除命令才是有效的。
}
void Ep0out()
{
char epstate,lastreg; //端点状态 和 最后处理状态寄存器
XBYTE[Cmdaddr]=0x80;
epstate=XBYTE[Dataddr]; //读端点状态
//Printn(epstate);
XBYTE[Cmdaddr]=0x40;
lastreg=XBYTE[Dataddr]; //读最后处理状态
//Printn(lastreg);
if(lastreg&0x20) //如果收到的有Setup包
{
Flag|=Setup_flag; //Setup包的标志置1,表示有Setup包进入
Readep(0,&Device_request); //读端点0
Answerep(0);
Answerep(1); //应答Setup包,使得可以清除缓冲区(F2)和使能缓冲区(FA)
//SUSP=1;
}
}
void Ep0in()
{
Uchar lastreg;
XBYTE[Cmdaddr]=0x41;
lastreg=XBYTE[Dataddr]; //读最后处理状态,清除中断
//Printn(lastreg);
if(translen==0) Writeep(1,0,0);
/*if(Flag&Trans_flag)
return;
if(translen>16)
{
Writeep(1,16,transp);
translen-=16;
transp+=16;
}
else if(translen!=0)
{
Writeep(1,translen,transp);
translen=0;
}
else
{
Writeep(1,0,0);
Flag^=Trans_flag;
}*/
}
void Ep1out()
{
}
void Ep1in()
{
}
void Ep2out()
{
}
void Ep2in()
{
}
void Busreset()
{
TestL=0;Delay(1);TestL=1;
//SUSP=1;
}
void Suspch()
{
}
void Connect()
{
XBYTE[Cmdaddr]=0xF3;
XBYTE[Dataddr]=0x12;
XBYTE[Dataddr]=0x80;
}
void Disconnect()
{
XBYTE[Cmdaddr]=0xF3;
XBYTE[Dataddr]=0x02;
XBYTE[Dataddr]=0x80;
}
void Delay(int n)
{
int i;
for(;n>0;n--)
for(i=0;i<100;i++)
{;}
}
/****************************** INT *************************************/
void Serial() interrupt 4
{
char c;
DISABLE;
if(TI==1)
{
TI=0;
}
if(RI==1)
{
c=SBUF;
RI=0;
}
ENABLE;
}
void int0() interrupt 0
{
unsigned char ir1,ir2;
DISABLE;
Readintregister(&ir1,&ir2);
if(ir1&EP0_OUT) //假如端点0输出中断发生
{
Prints("0o\t");
Ep0out();
}
if(ir1&EP0_IN) //假如端点0输入中断发生
{
Prints("0i\t");
Ep0in();
}
if(ir1&EP1_OUT) //假如端点0输入中断发生
{
Prints("1o\t");
Ep1out();
}
if(ir1&EP1_IN) //假如端点0输入中断发生
{
Prints("1i\t");
Ep1in();
}
if(ir1&EP2_OUT) //假如端点0输入中断发生
{
Prints("2o\t");
Ep2out();
}
if(ir1&EP2_IN) //假如端点0输入中断发生
{
Prints("2i\t");
Ep2in();
}
if(ir1&BUS_RESET) //假如总线复位中断发生
{
Prints("br\t");
Busreset();
}
if(ir1&SUSPCH) //假如端点0输入中断发生
{
Prints("sc\t");
Suspch();
}
ENABLE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -