⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbd12.c

📁 1.实现单片机驱动USBD12的固件
💻 C
📖 第 1 页 / 共 3 页
字号:
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 + -