📄 usb.c
字号:
unsigned char D12_FULLEMPTY;
unsigned char D12_INT_BUSRESET;
unsigned char D12_INT_SUSPENDCHANGE;
unsigned char D12_INT_ENDP0IN;
unsigned char D12_INT_ENDP0OUT;
unsigned char D12_INT_ENDP1IN;
unsigned char D12_INT_ENDP1OUT;
unsigned char D12_INT_ENDP2IN;
unsigned char D12_INT_ENDP2OUT;
unsigned char D12_SETUPPACKET;
unsigned char USB_IDLE;
unsigned char USB_TRANSMIT;
unsigned char USB_RECEIVE;
unsigned char USB_ENDPOINT_DIRECTION_MASK;
unsigned char MAX_CONTROLDATA_SIZE;
unsigned char EP0_PACKET_SIZE;
unsigned char EP1_PACKET_SIZE;
unsigned char EP2_PACKET_SIZE;
unsigned char GenEpBuf[4];
unsigned char EpBuf[64];
unsigned char USB_REQUEST_TYPE_MASK;
unsigned char USB_REQUEST_MASK;
unsigned char USB_STANDARD_REQUEST;
unsigned char USB_RECIPIENT;
unsigned char USB_RECIPIENT_DEVICE;
unsigned char USB_RECIPIENT_INTERFACE;
unsigned char USB_RECIPIENT_ENDPOINT;
unsigned char MAX_ENDPOINTS;
unsigned char D12_STALL;
unsigned char DEVICE_ADDRESS_MASK;
unsigned int USB_FEATURE_REMOTE_WAKEUP;
unsigned char USB_DEVICE_DESCRIPTOR_TYPE;
unsigned int USB_FEATURE_ENDPOINT_STALL;
unsigned char D12_NOLAZYCLOCK;
unsigned char D12_SETTOONE;
unsigned char D12_CLOCK_12M;
unsigned char D12_SOFTCONNECT;
unsigned char DeviceDescr[12]={0x12,0x01,0x10,0x01,0x0dc,0x00,0x00,0x10,0x71,0x04,0x66,
0x06,0x00,0x01,0x00,0x00,0x00,0x01};
unsigned char ConfigDescr[46]={0x09,0x02,0x2e,0x00,0x01,0x01,0x00,0x0a0,0x32,0x09,0x04,0x00,
0x00,0x04,0x0dc,0x0a0,0x0b0,0x00,0x07,0x05,0x81,0x03,0x10,
0x00,0x0a,0x07,0x05,0x01,0x03,0x10,0x00,0x0a,0x07,0x05,0x82,
0x02,0x40,0x00,0x0a,0x07,0x05,0x02,0x02,0x40,0x00,0x0a};
typedef union_epp_flags//USB事件标志
{struct_flags
{unsigned char timer;//时间溢出
unsigned char bus_reset;//总线复位标志
unsigned char suspend;//挂起改变标志
unsigned char setup_packet;//收到SETUP包
unsigned char remote_wakeup;//远程唤醒标志(未使用)
unsigned char in_isr;//USB中断服务标志
unsigned char control_state;//控制端点处理状态:0为空闲IDEL,1为发送TRANSMIT,2为接收RECEIVE
unsigned char configuration;//配置标志:0为未配置,1为已配置
unsigned char command://未使用
unsigned char ep1_rxdone;//端点1收到数据标志
unsigned char ep2_rxdone;//端点2收到数据标志
unsigned char ep1buf_full;//端点1输出双缓冲区满标志
unsigned char ep2buf_full;//端点2输出双缓冲区满标志
}bits;
unsigned short value
}EPPFLAGS;
typedef struct_device_request//USB设备请求寄存器
{unsigned char bmRequesetType;//请求类型(数据传输类型、方向、接收器)
unsigned char bRequest;//USB请求
unsigned short wValue;//USB请求值
unsigned short windex;//USB请求索引
unsigned short wLength;//计数长度
}DEVICE_REQUEST;
typedef struct_control_xfer//SETUP包数据缓冲区
{DEVICE_REQUSET DeviceRequest;//USB设备请求结构体,8个字节
unsigned short wLength;//传输数据的总字节数
unsigned short wCount;//传输字节数统计
unsigned char *pData;//传输数据的指针
unsigned char dataBuffer[MAX_CONTROLDATA_SIZE];//请求的数据
}CONTROL_XFER;
EPPFLAGS bEPPflags;//前后台之间工作状态标志
CONTROL_XFER ContralData;//保存SETUP包请求的类型和请求的数据
//若采用多地址/数据方式进行口的模拟,寄存器的更改频繁,故采用单地址/数据,用A0进行模拟
//函数用于将一个字节的数据输入PDIUSBD12,主副板不同,下面是主板程序
//下面是硬件提取层EPPHAL.C
void rom_initial(void)
{USB_FEATURE_REMOTE_WAKEUP=0x0001;
D12_FULLEMPTY=0x01;//第0位有效
D12_INT_BUSRESET=0x40;//第6位有效
D12_INT_SUSPENDCHANGE=0x80;//第7位有效
D12_INT_ENDP0IN=0x02;//第1位有效
D12_INT_ENDP0OUT=0x01;//第0位有效
D12_INT_ENDP1IN=0x08;//第3位有效
D12_INT_ENDP1OUT=0x04;//第2位有效
D12_INT_ENDP2IN=0x20;//第5位有效
D12_INT_ENDP2OUT=0x10;//第4位有效
D12_SETUPPACKET=0x20;//第5位有效
USB_IDLE=0x00;
USB_TRANSMIT=0x01;
USB_RECEIVE=0x02;
USB_ENDPOINT_DIRECTION_MASK=0x80;//第7位有效
MAX_CONTROLDATA_SIZE=8;
EP0_PACKET_SIZE=16;
EP1_PACKET_SIZE=4;
EP2_PACKET_SIZE=64;
USB_REQUEST_TYPE_MASK=0x60;
USB_REQUEST_MASK=0x0f;
USB_STANDARD_REQUEST=0x00;
USB_RECIPIENT=0x1f;
USB_RECIPIENT_DEVICE=0x00;
USB_RECIPIENT_INTERFACE=0x01;
USB_RECIPIENT_ENDPOINT=0x02;
MAX_ENDPOINTS=0x03;
D12_STALL=0x02;
DEVICE_ADDRESS_MASK=0x7f;
USB_DEVICE_DESCRIPTOR_TYPE=0x01;
USB_FEATURE_ENDPOINT_STALL=0x0000;
D12_NOLAZYCLOCK=0x02;
D12_SETTOONE=0x40;
D12_CLOCK_12M=0x03;
D12_SOFTCONNEC=0x10;
}
unsigned int SWAP(unsigned int swap_data_in)//整型数据高低字节交换
{unsigned int swap_data_out;
unsigned char swap_byte;
asm{ldd awap_data;
stab swap_byte
tab
ldaa swap_byte
std swap_data_out
}
return swap_data_out;
}
unsigned char MSB(unsigned int data)
{unsigned char aa;
aa=data>>8;
aa=aa & 0x0ff;
return aa;
}
void command_outportb(unsigned char data)//参数为命令类型要求输出的数值
{asm{ldaa #$97
staa PORTE//片选
ldaa #$0ff
staa PORTB//A0
ldaa #$95
staa PORTE//WR
ldaa data
staa PORTA//数据线
nop
ldaa #$97
staa PORTE//上升沿锁存
ldaa #$9f
staa PORTE//信号恢复
}
}
void data_outportb(unsigned char data)//参数为数据类型要求输出的数值
{asm{ldaa #$97
staa PORTE
ldaa #$07f
staa PORTB
ldaa #$95
staa PORTE
nop
ldaa data
staa PORTA
nop
ldaa #$97
staa PORTE
ldaa #$9f
staa PORTE
}
}
unsigned char inportb(void)//参数为数据类型要求输入的数值
{unsigned char read_byte;
asm{ldaa #$97
staa PORTE
ldaa #$07f
staa PORTB
ldaa #$87
staa PORTE
ldaa PORTA
staa read_byte
nop
ldaa #$97
staa PORTE
ldaa #$9f
staa PORTE
}
return read_byte;
}
//下面是命令接口程序D12CI.C
//设置地址使能命令
void D12_SetAddressEnable(unsigned char bAddress, unsigned char bEnable)
{command_outportb(0x0D0);
if(bEnable)
bAddress |= 0x80;
data_outportb(bAddress);
}
//设置端点使能命令
void D12_SetEndpointEnable(unsigned char bEnable)
{command_outportb(0x0D8);
if(bEnable)
data_outportb(1);
else
data_outportb(0);
}
//设置模式命令
void D12_SetMode(unsigned char bConfig, unsigned char bClkDiv)
{command_outportb(0x0F3);
data_outportb(bConfig);
data_outportb(bClkDiv);
}
//读取中断寄存器 注意整型数和浮点书字节的顺序
unsigned short D12_ReadInterruptRegister(void)
{unsigned char b1;
unsigned int j;
command_outportb(0x0F4);
b1=inportb();
j=inportb();
j<<=8;//先读低字节,再读高字节
j+=b1;
return j;
}
//端点选择命令
unsigned char D12_SelectEndpoint(unsigned char bEndp)
{unsigned char c;
command_outportb(bEndp);
c=inportb();
return c;
}
//读取端点最后处理状态
unsigned char D12_ReadLastTransactionStatus(unsigned char bEndp)
{command_outportb(0x40+bEndp);
return inportb();
}
//读取端点状态
unsigned char D12_ReadEndpointStatus(unsigned char bEndp)
{unsigned char c;
command_outportb(0x80+bEndp);
c=inportb();
return c;
}
//设置端点状态
void D12_SetEndpointStatus(unsigned char bEndp, unsigned char bStalled)
{command_outportb(0x40+bEndp);
data_outportb(bStalled);
}
//发送恢复命令
void D12_SendResume(void)
{
command_outportb(0x0F6);
}
//读取当前桢标志
unsigned short D12_ReadCurrentFrameNumber(void)
{unsigned short i,j;
command_outportb(0x0F5);
i=inportb();
j=inportb();
i+=(j<<8);
return i;
}
/*//读取ID号
unsigned short D12_ReadChipID(void)
{unsigned short i,j;
outportb(portbase+D12_COMMAND, 0xFD);
i=inportb(portbase+D12_DATA);
j=inportb(portbase+D12_DATA);
i += (j<<8);
return i;
}*/
//读取端点数据
unsigned char D12_ReadEndpoint(unsigned char endp, unsigned char *buf, unsigned char len)
{unsigned char i, j;
command_outportb(endp);
if((inportb() & D12_FULLEMPTY)==0)//判断缓冲区为满或空状态,值为0x01
{return 0; //缓冲区为空,返回
}
command_outportb(0x080+endp);
i=inportb();
i=i&0x60;
if(endp==2)
{if(i==0x60)
bEPPflags.bits.ep1buf_full=1;//标志端点1缓冲区全满
else bEPPflags.bits.ep1buf_full=0;
}
if(endp==4)
{if(i==0x60)
bEPPflags.bits.ep2buf_full=1;//标志端点2缓冲区全满
else bEPPflags.bits.ep2buf_full=0;
}
command_outportb(0x0f0);
j=inportb();//该字节为任意字节,没有意义
j=inportb();//数据字节的数目/长度
if(j>len)//用于将大于端点容量的数据分批传输
j=len;
for(i=0;i<j;i++)
*(buf+i)=inportb();//传输数据到指定的地址
command_outportb(0x0F2);//缓冲区清零
return j;
}
//把数据写入端点
unsigned char D12_WriteEndpoint(unsigned char endp, unsigned char * buf, unsigned char len)
{unsigned char i;
command_outportb(endp);//选择写入的端点
inportb();
command_outportb(0x0F0);
data_outportb(0);//写入规定数据0
data_outportb(len);//写入传送字节的数目
for(i=0;i<len;i++)
data_outportb(*(buf+i));
command_outportb(0x0FA);//使缓冲区有效
return len;//len的数值必须要由相关的计算而得
}
//端点应答处理
void D12_AcknowledgeEndpoint(unsigned char endp)
{command_outportb(endp);//选择端点
command_outportb(0x0F1);//应答设置
if(endp==0)
command_outportb(0x0F2);//缓冲区清零
}
//下面是中断服务程序
//#pragma TRAP_PROC
void fn_usb_isr()
{unsigned int i_st;//为保持与子程序的一致性
unsigned char i_st_byte;
bEPPflags.bits.in_isr=1;//中断服务标志
i_st=D12_ReadInterruptRegister();//读取中断寄存器
asm{ldd i_st;
stab i_st_byte;
}//只取低字节,高字节没有意义
if(i_st_byte!=0)
{if(i_st_byte & D12_INT_BUSRESET)
bEPPflags.bits.bus_reset=1;//复位
//if(i_st & D12_INT_EOT)
// dma_eot();
if(i_st_byte & D12_INT_SUSPENDCHANGE)
bEPPflags.bits.suspend=1;//挂起改变
if(i_st_byte & D12_INT_ENDP0IN)
ep0_txdone();//端点0 IN 中断
if(i_st_byte & D12_INT_ENDP0OUT)
ep0_rxdone();//端点0 OUT 中断
if(i_st_byte & D12_INT_ENDP1IN)
ep1_txdone();//端点1 IN 中断
if(i_st_byte & D12_INT_ENDP1OUT)
ep1_rxdone();//端点1 OUT 中断
if(i_st_byte & D12_INT_ENDP2IN)
main_txdone();//端点2 IN 中断
if(i_st_byte & D12_INT_ENDP2OUT)
main_rxdone();//端点2 OUT 中断
}
}
bEPPflags.bits.in_isr=0;//清中断服务标志
}
//端点0 OUT中断
void ep0_rxdone(void)
{unsigned char ep_last,i;
ep_last=D12_ReadLastTransactionStatus(0); // Clear interrupt flag 清中断标志
if(ep_last & D12_SETUPPACKET)//接收到SETUP包
{ControlData.wLength=0;//传输数据的总字节数
ControlData.wCount=0;//传输字节数统计
if(D12_ReadEndpoint(0,sizeof(ControlData.DeviceRequest),(unsigned char *)(&(ControlData.DeviceRequest)))!=sizeof(DEVICE_REQUEST))
//SETUP包出错,返回
{D12_SetEndpointStatus(0,1);//停止控制输出端点
D12_SetEndpointStatus(1,1);//停止控制输入端点
bEPPflags.bits.control_state=USB_IDLE;//控制端点进入空闲状态
return;
}
//数据高低字节交换,USB的结构与MOTOROLA 的数据结构不同,需要高低字节交换
ControlData.DeviceRequest.wValue=SWAP(ControlData.DeviceRequest.wValue);
ControlData.DeviceRequest.wIndex=SWAP(ControlData.DeviceRequest.wIndex);
ControlData.DeviceRequest.wLength=SWAP(ControlData.DeviceRequest.wLength);
//对控制端点的输入/输出进行应答
D12_AcknowledgeEndpoint(0);//对控制输出端点进行应答
D12_AcknowledgeEndpoint(1);//对控制输入端点进行应答
ControlData.wLength=ControlData.DeviceRequest.wLength;//将USB的请求计数长度赋给传输数据的字节数
ControlData.wCount=0;//传输字节数统计清零
if(ControlData.DeviceRequest.bmRequestType && (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
//检查传输的类型,这里是从主机传输数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -