📄 usbfunctions.c
字号:
Ep2_rxdone(); //端点 2接收数据处理
}
USB_FLAG.in_isr = 0;
}
}
/*******************************************
函数名称: 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
功 能: 控制传输
参 数: 无
返回值 : 无
********************************************/
void Control_handler(void)
{
uchar type,req;
type=ControlData.DeviceRequest.bmRequestType&USB_REQUEST_TYPE_MASK;
//读取请求代码
req=ControlData.DeviceRequest.bRequest&USB_REQUEST_MASK;
if(type==USB_STANDARD_REQUEST)
(*StandardDeviceRequest[req])(); //标准请求处理
else
Stall_ep0(); //无效请求,返回STALL
}
/*******************************************
函数名称: Reserved
功 能: 保留子程序
参 数: 无
返回值 : 无
********************************************/
void Reserved(void)
{
Stall_ep0(); //返回STALL
}
/*******************************************
函数名称: Init_unconfig
功 能: 进入地址状态,禁止0除外的所有端点
参 数: 无
返回值 : 无
********************************************/
void Init_unconfig(void)
{
Set_EPen(0); //禁止0除外的所有端点
}
/*******************************************
函数名称: Init_config
功 能: 配置处理,允许端点收发
参 数: 无
返回值 : 无
********************************************/
void Init_config(void)
{
Set_EPen(1); //使能普通/同步端点使能
}
/*******************************************
函数名称: Get_status
功 能: 主机要求获取状态,设备返回16位的状态描述给主机
参 数: 无
返回值 : 无
********************************************/
void Get_status(void)
{
uchar endp,txdat[2],c;
uchar bRecipient=ControlData.DeviceRequest.bmRequestType&USB_RECIPIENT; //取得设备请求类型
if (bRecipient==USB_RECIPIENT_DEVICE)//对设备请求
{
if(USB_FLAG.remote_wakeup==1)
{
txdat[0]=3; //支持远程唤醒、自供电
}
else
{
txdat[0]=1; //不支持远程唤醒、自供电
}
txdat[1]=0; //高8位为0
S_trans(txdat,2); //发送16位的状态到主机
}
else if (bRecipient == USB_RECIPIENT_INTERFACE) //对接口请求
{
txdat[0]=0;
txdat[1]=0;
S_trans(txdat, 2); //发送16位的状态到主机
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT) //对端点请求
{
endp = (uchar)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (uchar)USB_ENDPOINT_DIRECTION_MASK)
{
c = Sel_EP(endp*2+1); //读取输入端点状态
}
else
{
c = Sel_EP(endp*2); //读取输出端点状态
}
if(c & STALL)
{
txdat[0] = 1; //端点禁止
}
else
{
txdat[0] = 0; //端点有效
}
txdat[1] = 0;
S_trans(txdat, 2); //发送16位的状态到主机
}
else
{
Stall_ep0(); //非标准请求,发STALL
}
}
/*******************************************
函数名称: Clr_feature
功 能: 清除特性
参 数: 无
返回值 : 无
********************************************/
void Clr_feature(void)
{
uchar endp; //读取请求类型中的接收方
uchar bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT; //读取请求类型
if (bRecipient == USB_RECIPIENT_DEVICE //对设备请求
&&ControlData.DeviceRequest.wValue==USB_FEATURE_REMOTE_WAKEUP) //清除远程唤醒特性
{
UEN_GINT();
USB_FLAG.remote_wakeup = 0; //清0远程唤醒标志
EN_GINT();
S_trans(0,0); //返回一个空的数据表示执行完毕
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT //对端点请求
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) //清除端点禁止特性,恢复其使用
{
endp = (uchar)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (uchar)USB_ENDPOINT_DIRECTION_MASK)
{
Set_EPsta(endp*2 + 1, 0); //清除控制输入端点STALL特性
}
else
{
Set_EPsta(endp*2, 0); //清除控制输出端点STALL特性
}
S_trans(0, 0); //返回一个空的数据表示执行完毕
}
else
{
Stall_ep0(); //没有该请求,返回STALL
}
}
/*******************************************
函数名称: Set_feature
功 能: 设置特性
参 数: 无
返回值 : 无
********************************************/
void Set_feature(void)
{
uchar endp; //读取请求类型中的接收方
uchar bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;//读取请求类型
if (bRecipient == USB_RECIPIENT_DEVICE //对设备请求
&& ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP) //设置远程唤醒特性
{
UEN_GINT();
USB_FLAG.remote_wakeup = 1; //置1远程唤醒标志
EN_GINT();
S_trans(0, 0); //返回一个空的数据表示执行完毕
}
else if (bRecipient == USB_RECIPIENT_ENDPOINT //对端点请求
&& ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL) //禁止端点
{
endp = (uchar)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
if (ControlData.DeviceRequest.wIndex & (uchar)USB_ENDPOINT_DIRECTION_MASK)
{
Set_EPsta(endp*2 + 1, 1); //设置输入端点禁止
}
else
{
Set_EPsta(endp*2, 1); //设置输出端点禁止
}
S_trans(0, 0); //返回一个空的数据表示执行完毕
}
else
{
Stall_ep0(); //没有该请求,返回STALL
}
}
/*******************************************
函数名称: Set_addr
功 能: 设置地址
参 数: 无
返回值 : 无
********************************************/
void Set_addr(void)
{
Set_addren((uchar)(ControlData.DeviceRequest.wValue&DEVICE_ADDRESS_MASK), 1);
S_trans(0, 0); //发送一个空的数据响应
}
/*******************************************
函数名称: Get_descriptor
功 能: 获取描述符
参 数: 无
返回值 : 无
********************************************/
void Get_descriptor(void)
{
uchar bDescriptor = MSB(ControlData.DeviceRequest.wValue); //读取请求的描述符类型
if (bDescriptor == USB_DEVICE_DESCRIPTOR_TYPE) //获取设备描述符
{
Code_trans((uchar *)&DeviceDescr, sizeof(USB_DEVICE_DESCRIPTOR));
}
else if (bDescriptor == USB_CONFIGURATION_DESCRIPTOR_TYPE) //获取其它描述符
{
if (ControlData.DeviceRequest.wLength > CONFIG_DESCRIPTOR_LENGTH)
{
ControlData.DeviceRequest.wLength = CONFIG_DESCRIPTOR_LENGTH;
} //发送描述符内容
Code_trans((uchar *)&(usb_descr.ConfigDescr), ControlData.DeviceRequest.wLength);
}
else
{
Stall_ep0(); //没有该请求,返回STALL
}
}
/*******************************************
函数名称: Get_config
功 能: 获取配置
参 数: 无
返回值 : 无
********************************************/
void Get_config(void)
{
uchar c = USB_FLAG.configuration; //取出配置值
S_trans(&c, 1); //发送配置值
}
/*******************************************
函数名称: Set_config
功 能: 设置配置
参 数: 无
返回值 : 无
********************************************/
void Set_config(void)
{
if (ControlData.DeviceRequest.wValue == 0) //配置值不对,设备进入未配置状态
{
S_trans(0, 0); //发向一个空包响应
UEN_GINT();
USB_FLAG.configuration = 0; //标记未配置
EN_GINT();
Init_unconfig(); //进入地址状态,禁止0除外的所有端点
}
else if (ControlData.DeviceRequest.wValue == 1) //配置设备
{
S_trans(0, 0); //发向一个空包响应
Init_unconfig(); //进入地址状态,禁止0除外的所有端点
Init_config(); //配置处理,允许端点收发
UEN_GINT();
USB_FLAG.configuration = 1; //标志已配置
EN_GINT();
}
else
{
Stall_ep0(); //没有该请求,返回STALL
}
}
/*******************************************
函数名称: Get_interface
功 能: 获取接口信息
参 数: 无
返回值 : 无
********************************************/
void Get_interface(void)
{
uchar txdat = 0; //本设备只有一个接口
S_trans(&txdat, 1); //发送一个字节
}
/*******************************************
函数名称: Set_interface
功 能: 设置接口信息
参 数: 无
返回值 : 无
********************************************/
void Set_interface(void)
{
if (ControlData.DeviceRequest.wValue == 0 && ControlData.DeviceRequest.wIndex == 0)
{
S_trans(0, 0); //发送一个空的数据表示执行完毕
}
else
{
Stall_ep0(); //没有该请求,返回STALL
}
}
/*******************************************
函数名称: USB_connect
功 能: 连接USB总线
参 数: 无
返回值 : 无
********************************************/
void USB_connect(void)
{
//SoftConnect 连接上,并设置为无LazyClock,模式为非同步模式
Set_DMA(0x00);
Set_mode(NOLAZYCLOCK|SOFTCONNECT, SETTOONE | CLOCK_12M);
}
/*******************************************
函数名称: Set_interface
功 能: 设置接口信息
参 数: 无
返回值 : 无
********************************************/
void USB_disconnect(void)
{
//SoftConnect 断开
Set_mode(NOLAZYCLOCK, SETTOONE | CLOCK_12M);
}
/*******************************************
函数名称: USB_reconnect
功 能: 重新连接USB总线
参 数: 无
返回值 : 无
********************************************/
void USB_reconnect(void)
{
USB_disconnect(); //断开芯片与USB总线连接
Delayms(200);
Set_addren(0,1);
Set_EPen(1);
USB_connect(); //连接到USB总线
}
/*******************************************
函数名称: Read_chipID
功 能: 读取芯片的ID
参 数: 无
返回值 : 无
********************************************/
uint Read_chipID(void)
{
uint i,j;
if(USB_FLAG.in_isr == 0)
UEN_GINT();
OutB(CMD, 0xFD);
i=InB( );
j=InB( );
i += (j<<8);
if(USB_FLAG.in_isr == 0)
EN_GINT();
return i;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -