📄 usbd12.c
字号:
uchar Read_EPsta(uchar endp)//-----------------
{
uchar status;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,0x80+endp); //读取端点状态命令
status=InB( ); //读取端点状态
if(USB_FLAG.in_isr == 0)
EN_GINT();
return status;
}
/*******************************************
函数名称: Read_LttransSta
功 能: 读取最后处理状态寄存器
参 数: endp--端点索引号,取值0 ~ 5
返回值 : status--端点最后处理的状态
/********************************************/
uchar Read_LttransSta(uchar endp)
{
uchar status;
OutB(CMD,0x40+endp); //输出读取最后处理状态寄存器命令
Delayus(5);
status=InB( );
return status; //读取状态
}
/*******************************************
函数名称: Set_EPsta
功 能: 设置端点状态
参 数: endp--端点索引号,取值0 ~ 5
stall--设置状态值
返回值 : 无
/********************************************/
void Set_EPsta(uchar endp,uchar stall)
{
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,0x40+endp); //发送设置端点状态命令
Delayus(1);
OutB(CMD,stall); //设置端点状态
if(USB_FLAG.in_isr == 0)
EN_GINT();
}
/*******************************************
函数名称: Set_Sresume
功 能: 设置发送恢复
参 数: 无
返回值 : 无
/********************************************/
void Set_Sresume(void)
{
OutB(CMD,0xF6); //设置发送恢复
}
/*******************************************
函数名称: Read_EP
功 能: 读取端点数据
参 数: endp--端点索引号,取值 0 ~ 5
len--要读取的数据长度
buf--接收数据指针
返回值 : num--实际读到的字节数
/********************************************/
uchar Read_EP(uchar endp,uchar len,uchar * buf)
{
uchar i,num;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,endp); //发送选择端点命令
Delayus(1);
if((InB( )&FULLEMPTY)==0)
{ //如果缓冲区为空----------------------------------------
if(USB_FLAG.in_isr == 0)
EN_GINT();
return 0; //则返回读到0字节
}
OutB(CMD,0xF0); //发送读缓冲区命令
Delayus(1);
num=InB( ); //读取保留字节
num=InB( ); //读取数据字节的数目/长度
if(num>len) //如果大于要求读的字节数目
{
num=len; //则只读取要求的字节长度
}
for(i=0; i<num; i++)
*(buf+i)=InB( ); //读取要求的字节数目/长度
OutB(CMD,0xF2); //清缓冲区,新的信息包才可以重新被接受
if(USB_FLAG.in_isr == 0)
EN_GINT();
return num; //返回读到的字节数
}
/*******************************************
函数名称: Write_EP
功 能: 将数据写入端点
参 数: endp--端点索引号,取值 0 ~ 5
len--要写入的数据长度
buf--发送数据指针
返回值 : num--实际写入的字节数
/********************************************/
uchar Write_EP(uchar endp,uchar len,uchar * buf)
{
uchar i;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD,endp); //发送选择端点命令
Delayus(1);
i=InB( ); //可选地读取一个字节
OutB(CMD,0xF0); //发送写缓冲区命令
Delayus(1);
OutB(DAT,0); //写入一个保留字节
Delayus(1);
OutB(DAT,len); //写入即将写入的字节数目
Delayus(1);
for(i=0; i<len; i++)
{
OutB(DAT,*(buf+i)); //写入指定的字节
}
Delayus(1);
OutB(CMD,0xFA); //使缓冲区有效
if(USB_FLAG.in_isr == 0)
EN_GINT();
return len; //返回写入的字节数
}
/*******************************************
函数名称: Ack_EP
功 能: 应答Setup
参 数: endp--端点索引号,取值 0 ~ 5
返回值 : 无
/********************************************/
void Ack_EP(uchar endp)
{
OutB(CMD,endp); //选择端点
Delayus(1);
OutB(CMD,0xF1); //应答Setup指令
Delayus(1);
if(endp==0)
{
OutB(CMD,0xF2); //清空该端点缓冲区
}
}
/*******************************************
函数名称: Clear_buf
功 能: 清指定端点的缓冲区(包括双缓冲区)
参 数: endp--端点索引号,取值 0 ~ 5
返回值 : 无
/********************************************/
void Clear_buf(uchar endp)
{
OutB(CMD,endp); //选择端点
Delayus(1);
OutB(CMD,0xF2); //清空第1个缓冲区
if (endp>=4)
{
OutB(CMD,endp); //选择端点
Delayus(1);
OutB(CMD,0xF2); //清空第2个缓冲区
}
}
/*******************************************
函数名称: Stall_ep0
功 能: 使控制端点处于停止状态
参 数: 无
返回值 : 无
/********************************************/
void Stall_ep0(void)
{
Set_EPsta(0,1);
Set_EPsta(1,1);
}
/*******************************************
函数名称: S_trans
功 能: 通过端点索引 1 发送数据(DATA 类型)
参 数: buf--发送数据指针
len--发送数据长度
返回值 : 无
/********************************************/
void S_trans(uchar * buf, uchar len)
{
if(len<=EP0_PACKET_SIZE)
{ //长度小于EP0最大信息包大小才允许发送
Write_EP(1,len,buf);
}
}
/*******************************************
函数名称: Code_trans
功 能: 通过端点索引 1 发送数据(CODE类型)
参 数: buf--发送数据指针
len--发送数据长度
返回值 : 无
/********************************************/
void Code_trans(uchar *pRomData, uint len)
{
ControlData.wCount = 0; //传输字节数计数器清0
if(ControlData.wLength > len)
ControlData.wLength = len; //传输数据总字节数不得超过len
ControlData.pData = pRomData; //传输数据指针指向pRomData
if( ControlData.wLength >= EP0_PACKET_SIZE)
{ //传输数据总字节数大于端点0最大信息包大小
Write_EP(1, EP0_PACKET_SIZE, ControlData.pData); //发送端点0最大信息包大小个字节
ControlData.wCount += EP0_PACKET_SIZE; //统计已发送字节数
UEN_GINT();
USB_FLAG.control_state = USB_TRANSMIT; //标志数据发送状态
EN_GINT();
}
else
{
Write_EP(1, ControlData.wLength, pRomData); //写入传输数据总字节数
ControlData.wCount += ControlData.wLength; //统计已发送字节数
UEN_GINT();
USB_FLAG.control_state = USB_IDLE; //标志空闲状态
EN_GINT();
}
}
/*******************************************
函数名称: USB_INT1
功 能: D12中断服务函数
参 数: 无
返回值 : 无
/********************************************/
void USB_INT1(void)
{
uint int_sta;
uchar a,b;
UEN_GINT(); //进入D12中断服务程序时关中断
USB_FLAG.in_isr = 1;//-----------------------------
int_sta=Read_IntR(); //读取PDIUSBD12中断寄存器值
//a=int_sta;
//b=int_sta>>8;
//Uart_sendB(a);
//Uart_sendB(b);
if(int_sta!=0)
{
if(int_sta&INT_BUSRESET)
USB_FLAG.bus_reset=1; //USB总线复位标志
if(int_sta&INT_ENDP0IN)
Ep0_txdone(); //控制端点发送数据处理
if(int_sta&INT_ENDP0OUT)
Ep0_rxdone(); //控制端点接收数据处理
if(int_sta&INT_ENDP1IN)
Ep1_txdone(); //端点 1发送数据处理
if(int_sta&INT_ENDP1OUT)
Ep1_rxdone(); //端点 1接收数据处理
if(int_sta&INT_ENDP2IN)
Ep2_txdone(); //端点 2发送数据处理
if(int_sta&INT_ENDP2OUT)
Ep2_rxdone(); //端点 2接收数据处理
}
USB_FLAG.in_isr = 0;
EN_GINT(); //退出D12中断服务程序时开中断
}
/*******************************************
函数名称: Ep0_rxdone
功 能: 通过端点索引 0 接收数据
参 数: 无
返回值 : 无
/********************************************/
void Ep0_rxdone(void)
{
uchar ep_last,i;
ep_last=Read_LttransSta(0); //清除中断寄存器状态,取得最后处理状态
if (ep_last&SETUPPACKET)
{ //如果收到了建立包(Setup包)
ControlData.wLength=0; //传输字节总数清0
ControlData.wCount=0; //传输字节计数器清0
if(Read_EP(0,sizeof(ControlData.DeviceRequest),(uchar * )(&(ControlData.DeviceRequest)))!= sizeof(DEVICE_REQUEST))//从端点0读8个字节失败
{
Set_EPsta(0,1); //停止控制端点0
Set_EPsta(1,1); //停止控制端点1
USB_FLAG.control_state = USB_IDLE; //设置为等待状态
return;
}
/******** 接收建立包成功 **********///-------------------------
Ack_EP(0); //对控制端点0进行建立包应答
Ack_EP(1); //对控制端点1进行建立包应答
ControlData.wLength=ControlData.DeviceRequest.wLength; //取出要传输数据的总字节数
ControlData.wCount = 0;//------------------------------
if(ControlData.DeviceRequest.bmRequestType&(uchar)USB_ENDPOINT_DIRECTION_MASK)
{
//如果控制传输是控制读取
USB_FLAG.setup_packet=1; //通知control_handler()处理Setup包
USB_FLAG.control_state=USB_TRANSMIT; //设置为发送状态
}
else
{ //控制传输是控制写入
if(ControlData.DeviceRequest.wLength==0)
{
USB_FLAG.setup_packet=1; //通知control_handler()处理Setup包
USB_FLAG.control_state=USB_IDLE; //设置为等待状态
}
else
{
if(ControlData.DeviceRequest.wLength>MAX_CTLDAT_SIZE)
{
//数据长度出错
USB_FLAG.control_state=USB_IDLE; //设置为等待状态
Set_EPsta(0,1); //停止控制端点0
Set_EPsta(1,1); //停止控制端点1
}
else
{
USB_FLAG.control_state=USB_RECEIVE; //设置为接收状态
}
}// set command with data
}// else set command
}// if setup packet
/***** 下面为控制写入的数据阶段 ***************/
else if(USB_FLAG.control_state==USB_RECEIVE)
{ //如果为接收状态
i=Read_EP(0,EP0_PACKET_SIZE,ControlData.dataBuffer+ControlData.wCount); //从端点0接收数据
ControlData.wCount+=i; //统计已接收的字节数
if(i!=EP0_PACKET_SIZE||ControlData.wCount>=ControlData.wLength)
{ //数据接收完毕
USB_FLAG.setup_packet=1; //通知control_handler()处理Setup包
USB_FLAG.control_state=USB_IDLE; //设置为等待状态
}
}
else
{
USB_FLAG.control_state = USB_IDLE; //设置等待状态
}
}
/*******************************************
函数名称: Ep0_txdone
功 能: 通过端点索引 0 发送数据
参 数: 无
返回值 : 无
/********************************************/
void Ep0_txdone(void)
{
uint i=ControlData.wLength-ControlData.wCount; //计算未发送的字节数
Read_LttransSta(1); //清除中断寄存器标志位
if (USB_FLAG.control_state!=USB_TRANSMIT)
{ //非发送状态
return; //返回
}
if(i>=EP0_PACKET_SIZE)
{ //未发送字节数大于16,发送16个字节
Write_EP(1,EP0_PACKET_SIZE,ControlData.pData+ControlData.wCount);
ControlData.wCount+= EP0_PACKET_SIZE;
USB_FLAG.control_state=USB_TRANSMIT;
}
else if(i!=0)
{ //发送所有未发送的字节
Write_EP(1,i,ControlData.pData+ControlData.wCount);
ControlData.wCount+=i;
USB_FLAG.control_state=USB_IDLE; //置状态为等待状态
}
else if (i == 0)
{
Write_EP(1, 0, 0); //发送完毕,发0个字节
USB_FLAG.control_state = USB_IDLE;
}
}
/*******************************************
函数名称: Ep1_txdone
功 能: 端点1发送处理函数
参 数: 无
返回值 : 无
/********************************************/
void Ep1_txdone(void)
{
Read_LttransSta(3); //清中断标志位
}
/*******************************************
函数名称: Ep1_rxdone
功 能: 端点1接收处理函数
参 数: 无
返回值 : 无
/********************************************/
void Ep1_rxdone(void)
{
uchar len;
Read_LttransSta(2); //清中断标志位
len=Read_EP(2,sizeof(GenEpBuf),GenEpBuf); //读取数据
if(len!=0)
USB_FLAG.ep1_rxdone = 1; //标志接收到数据
}
/*******************************************
函数名称: Ep2_txdone
功 能: 端点2发送处理函数
参 数: 无
返回值 : 无
/********************************************/
void Ep2_txdone(void)
{
Read_LttransSta(5); //清中断标志位
}
/*******************************************
函数名称: Ep2_rxdone
功 能: 端点2接收处理函数
参 数: 无
返回值 : 无
/********************************************/
void Ep2_rxdone(void)
{
uchar len;
Read_LttransSta(4); //清中断标志位
len=Read_EP(4,EP2_PACKET_SIZE,EpBuf); //读取缓冲区中的数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -