📄 usbfunctions.c
字号:
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中断服务函数
参 数: 无
返回值 : 无
********************************************/
#pragma vector=PORT1_VECTOR
__interrupt void USB_INT1(void)
{
uint int_sta;
uchar tmp;
if(P1IFG & BIT5)
{
//UEN_GINT(); //进入D12中断服务程序时关中断
if((USBINT_IFG & BIT(D12_INT))==BIT(D12_INT))
{
USBINT_IFG&=~BIT(D12_INT); //清除中断标志
USB_FLAG.in_isr = 1;
int_sta=Read_IntR(); //读取PDIUSBD12中断寄存器值
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;
}
P1IFG &= ~BIT5;
// EN_GINT(); //退出D12中断服务程序时开中断
}
else if(P1IFG & 0x0f)
{
tmp =~ (P1IN & 0x0f);
switch(tmp) //根据中断读入的数值赋予相应的键值
{
case 0xf1: KeyChar = 1;break;
case 0xf2: KeyChar = 2;break;
case 0xf4: KeyChar = 3;break;
case 0xf8: KeyChar = 4;break;
default: KeyChar = 0;break;
}
P3OUT ^= BIT4; //LED的状态取反
SendFlag = 1; //设置发送键值标志
while((P1IN & 0x0f) != 0x0f); //等待按键被放开
P1IFG &= ~0x0f; //清除中断标志
}
}
/*******************************************
函数名称: 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(Ep1Buf),Ep1Buf); //读取数据
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,Ep2Buf); //读取缓冲区中的数据
if (len!=0)
USB_FLAG.ep2_rxdone = 1;
}
/*******************************************
函数名称: Control_handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -