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

📄 usb.c

📁 一个通过D12与计算机进行USB通信的单片机程序,开发者可以参考
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <reg51.h>                /* special function register declarations   */
#include <stdio.h>
#include <string.h>
#include "d12.h"


unsigned char rcv_data_len;

void main(void)
{

	init_port();					//初始化I/O口
	init_serial();					//初始化串行口
	init_timer0();					//初始化定时器0
	init_special_interrupts();		//设置中断
	MCU_D12CS = 0x1;
	MCU_D12CS = 0x0;
	bEPPflags.value = 0;
	reconnect_USB();				//重新连接USB
	while( TRUE )
	{
		if (bEPPflags.bits.timer)
		{
			DISABLE;				//定时器溢出,检测按键状态
			bEPPflags.bits.timer = 0;
			ENABLE;
			if(bEPPflags.bits.configuration)//设备未配置返回
				check_key_LED();
		}
		if (bEPPflags.bits.bus_reset)
		{							//设备复位处理
			DISABLE;
			bEPPflags.bits.bus_reset = 0;
			ENABLE;
			// Release D12's SUSPEND pin after bus reset
			// Enable 74HCT123 pulse generation before disconnect
			D12SUSPD = 1;
		}
		if (bEPPflags.bits.suspend)
		{							//挂起改变处理
			DISABLE;
			bEPPflags.bits.suspend= 0;
			ENABLE;
			if(D12SUSPD == 1)
			{						//挂起处理
				D12SUSPD = 0;
				P0 = 0xFF;
				P1 = 0xFF;
				P2 = 0xFF;
				P3 = 0xFF;
				D12_SetDMA(0xC3);
				D12SUSPD = 1;
				PCON |= 0x02;
				while (1);
			}
		}
		if (bEPPflags.bits.setup_packet)
		{							//Setup包处理
			DISABLE;
			bEPPflags.bits.setup_packet = 0;
			ENABLE;
			control_handler();		//调用请求处理子程序
			D12SUSPD = 1;
		}
		if(bEPPflags.bits.ep1_rxdone)
		{
			D12_WriteEndpoint(3,rcv_data_len,GenEpBuf);
            bEPPflags.bits.ep1_rxdone = 0 ;
		}
		if(bEPPflags.bits.ep2_rxdone)
		{
			D12_WriteEndpoint(5,rcv_data_len,EpBuf);
            bEPPflags.bits.ep2_rxdone = 0 ;
		}
	}
}

//返回stall应答
void stall_ep0(void)
{
	D12_SetEndpointStatus(0, 1);
	D12_SetEndpointStatus(1, 1);
}

//断开USB总线
void disconnect_USB(void)
{
	// Initialize D12 configuration
	D12_SetMode(D12_NOLAZYCLOCK, D12_SETTOONE | D12_CLOCK_12M);
}

//连接USB总线
void connect_USB(void)
{
	// reset event flags
	DISABLE;
	bEPPflags.value = 0;//清除所有状态
	ENABLE;
	// V2.1 enable normal+sof interrupt
	D12_SetDMA(D12_ENDP4INTENABLE | D12_ENDP5INTENABLE);
	// Initialize D12 configuration
	D12_SetMode(D12_NOLAZYCLOCK|D12_SOFTCONNECT, D12_SETTOONE | D12_CLOCK_12M);
}

//重新连接到USB总线
void reconnect_USB(void)
{
	unsigned long clk_cnt;
	MCU_LED0 = 0;
	MCU_LED1 = 0;
	// Pull-down D12's SUSPEND pin
	// Disable 74HCT123 pulse generation before disconnect
	// Release D12's SUSPEND pin after receiving bus reset from host
	D12SUSPD = 0;
	disconnect_USB();
	printf("Wait for 1 second ...\n");
	clk_cnt = ClockTicks;
	while(ClockTicks < clk_cnt + 20) ;
	connect_USB();
	MCU_LED0 = 1;
	MCU_LED1 = 1;
}

//恢复到未配置状态
void init_unconfig(void)
{
//	unsigned char i;
	D12_SetEndpointEnable(0);	/* Disable all endpoints but EPP0. */
}

//设置配置状态
void init_config(void)
{
	D12_SetEndpointEnable(1);	/* Enable  generic/iso endpoints. */
}

//从端点号1发送数据
void single_transmit(unsigned char * buf, unsigned char len)
{
	if( len <= EP0_PACKET_SIZE)
	{
		D12_WriteEndpoint(1, len, buf);
	}
}
//发送端点号1建立代码
void code_transmit(unsigned char code * pRomData, unsigned short len)
{

	ControlData.wCount = 0;
	if(ControlData.wLength > len) ControlData.wLength = len;
	ControlData.pData = pRomData;
	if( ControlData.wLength >= EP0_PACKET_SIZE)
	{
		D12_WriteEndpoint(1, EP0_PACKET_SIZE, ControlData.pData);//发送16字节数据
		ControlData.wCount += EP0_PACKET_SIZE;
		DISABLE;
		bEPPflags.bits.control_state = USB_TRANSMIT;
		ENABLE;
	}
	else
	{
		D12_WriteEndpoint(1, ControlData.wLength, pRomData);//发送16字节内数据
		ControlData.wCount += ControlData.wLength;
		DISABLE;
		bEPPflags.bits.control_state = USB_IDLE;
		ENABLE;
	}
}

//LED和按键处理子程序
void check_key_LED(void)
{
	static unsigned char c, last_key = 0xf;

	c = MCU_SWM0 & MCU_SWM1;
	c &= 0x0f;
	if (c != last_key)
	{
		D12_WriteEndpoint(3, 1, &c);//发送按键状态
	}
	last_key = c;
	if(bEPPflags.bits.ep1_rxdone)
	{
		DISABLE;
		bEPPflags.bits.ep1_rxdone = 0;
		ENABLE;
		MCU_LED0 = !(GenEpBuf[3] & 0x1);//改变LED状态
		MCU_LED1 = !(GenEpBuf[3] & 0x2);
	}
}

void help_devreq(unsigned char typ, unsigned char req)
{
	typ >>= 5;
	if(typ == USB_STANDARD_REQUEST)
	{
	}
	else if(bEPPflags.bits.verbose) printf("Request Type = %s, bRequest = 0x%bx.\n", _NAME_USB_REQUEST_TYPE[typ],req);
}

//请求处理子程序
void control_handler()
{
	unsigned char type, req;
	type = ControlData.DeviceRequest.bmRequestType & USB_REQUEST_TYPE_MASK;
	req = ControlData.DeviceRequest.bRequest & USB_REQUEST_MASK;
	help_devreq(type, req); //显示设备请求
	if (type == USB_STANDARD_REQUEST) (*StandardDeviceRequest[req])();//调用标准请求
	else if (type == USB_VENDOR_REQUEST) (*VendorDeviceRequest[req])();//调用厂商请求
	else stall_ep0();
}


//定时器0中断处理
timer_isr() interrupt 1
{
	DISABLE;
	ClockTicks++;
	bEPPflags.bits.timer = 1;
	ENABLE;
}

//USB中断处理
usb_isr() interrupt 0
{
	DISABLE;
	fn_usb_isr();
	ENABLE;
}

//USB中断服务子程序
void fn_usb_isr()
{
	unsigned int i_st;

	bEPPflags.bits.in_isr = 1;

	i_st = D12_ReadInterruptRegister();//读取中断寄存器

	if(i_st != 0)
	{
		if(i_st & D12_INT_BUSRESET)
		{
			bus_reset();//USB总线服务
			bEPPflags.bits.bus_reset = 1;
		}
		if(i_st & D12_INT_EOT)
			dma_eot();//DMA传输结束
		if(i_st & D12_INT_SUSPENDCHANGE)
			bEPPflags.bits.suspend = 1;//挂起改变
		if(i_st & D12_INT_ENDP0IN)
			ep0_txdone();//端点0IN中断
		if(i_st & D12_INT_ENDP0OUT)
			ep0_rxdone();//端点0OUT中断
		if(i_st & D12_INT_ENDP1IN)
			ep1_txdone();//端点1IN中断
		if(i_st & D12_INT_ENDP1OUT)
			ep1_rxdone();//端点1OUT中断
		if(i_st & D12_INT_ENDP2IN)
			main_txdone();//端点2IN中断
		if(i_st & D12_INT_ENDP2OUT)
			main_rxdone();//端点2OUT中断
	}
	bEPPflags.bits.in_isr = 0;
}

//总线复位处理子程序
void bus_reset(void)
{
}

//端点0OUT中断
void ep0_rxdone(void)
{
	unsigned char ep_last, i;
	ep_last = D12_ReadLastTransactionStatus(0); //清中断标志
	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;
		}
		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;
		ControlData.wCount = 0;

		if (ControlData.DeviceRequest.bmRequestType & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
		{
			//从主机传输数据
			bEPPflags.bits.setup_packet = 1;
			bEPPflags.bits.control_state = USB_TRANSMIT;		/* get command */
		}
		else
		{
			if (ControlData.DeviceRequest.wLength == 0)
			{
				bEPPflags.bits.setup_packet = 1;
				bEPPflags.bits.control_state = USB_IDLE;		/* set command */
			}
			else
			{
				if(ControlData.DeviceRequest.wLength > MAX_CONTROLDATA_SIZE)
				{
					//接收数据长度为0
					bEPPflags.bits.control_state = USB_IDLE;
					D12_SetEndpointStatus(0, 1);
					D12_SetEndpointStatus(1, 1);
				}
				else
				{
					bEPPflags.bits.control_state = USB_RECEIVE;	//设置接收状态
				}
			} // set command with data
		} // else set command
	} // if setup packet
	else if (bEPPflags.bits.control_state == USB_RECEIVE)
	{
		//接收数据
		i =	D12_ReadEndpoint(0, EP0_PACKET_SIZE,
			ControlData.dataBuffer + ControlData.wCount);
		ControlData.wCount += i;
		if( i != EP0_PACKET_SIZE || ControlData.wCount >= ControlData.wLength)
		{
			//数据接收完毕
			bEPPflags.bits.setup_packet = 1;
			bEPPflags.bits.control_state = USB_IDLE;
		}
	}
	else
	{
		bEPPflags.bits.control_state = USB_IDLE;//进入等待状态
	}
}

//端点0IN处理
void ep0_txdone(void)
{

	short i = ControlData.wLength - ControlData.wCount;
        
	D12_ReadLastTransactionStatus(1); //清中断标志位
	if (bEPPflags.bits.control_state != USB_TRANSMIT) return;//非发送状态,返回
	if( i >= EP0_PACKET_SIZE)
	{
		//剩下数据大于16字节,发送16字节
		D12_WriteEndpoint(1, EP0_PACKET_SIZE, ControlData.pData + ControlData.wCount);
		ControlData.wCount += EP0_PACKET_SIZE;
		bEPPflags.bits.control_state = USB_TRANSMIT;
	}
	else if( i != 0)
	{
		//发送剩下数据
			D12_WriteEndpoint(1, i, ControlData.pData + ControlData.wCount);
			ControlData.wCount += i;
			bEPPflags.bits.control_state = USB_IDLE;

	}
	else if (i == 0)
	{
		D12_WriteEndpoint(1, 0, 0); //发送完毕,发送0字节
		bEPPflags.bits.control_state = USB_IDLE;
	}
}

//DMA结束处理
void dma_eot(void)
{
}

//端点1OUT处理
void ep1_txdone(void)
{
	D12_ReadLastTransactionStatus(3); //清中断标志位
}

//端点1IN处理
void ep1_rxdone(void)
{
	unsigned char len;

	D12_ReadLastTransactionStatus(2); //清中断标志位
	len = D12_ReadEndpoint(2, sizeof(GenEpBuf), GenEpBuf);//读取数据
	if(len != 0) bEPPflags.bits.ep1_rxdone = 1;//标志接收到数据
	rcv_data_len = len ;
}

//主端点OUT控制
void main_txdone(void)
{
	D12_ReadLastTransactionStatus(5); //清中断标志位
}

//主端点IN控制
void main_rxdone(void)
{
	unsigned char len,epstatus;

	D12_ReadLastTransactionStatus(4); 			//清中断标志位
	len = D12_ReadEndpoint(4, 64, EpBuf);		//接收数据
	epstatus=D12_ReadEndpointStatus(4);
	epstatus &= 0x60;
	if (epstatus == 0x60) len = D12_ReadEndpoint(4, 64, EpBuf);//读取双缓冲区数据
	rcv_data_len = len ;
	bEPPflags.bits.ep2_rxdone = 1 ;
}
void reserved(void)
{
	stall_ep0();
}


//获取设备状态
void get_status(void)
{
	unsigned char endp, txdat[2];
	unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;
	unsigned char c;
	if (bRecipient == USB_RECIPIENT_DEVICE)
	{
		if(bEPPflags.bits.remote_wakeup == 1)		//获取远程唤醒状态
			txdat[0] = 3;
		else
			txdat[0] = 1;
		txdat[1]=0;
		single_transmit(txdat, 2);
	}
	else if (bRecipient == USB_RECIPIENT_INTERFACE)
	{												//获取接口状态
		txdat[0]=0;
		txdat[1]=0;
		single_transmit(txdat, 2);
	}
	else if (bRecipient == USB_RECIPIENT_ENDPOINT)
	{												//获取端点状态
		endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
		if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
			c = D12_SelectEndpoint(endp*2 + 1);	/* Control-in */
		else
			c = D12_SelectEndpoint(endp*2);	/* Control-out */
		if(c & D12_STALL)
			txdat[0] = 1;
		else
			txdat[0] = 0;
		txdat[1] = 0;
		single_transmit(txdat, 2);
	}
	else
		stall_ep0();
}

//特性清除
void clear_feature(void)
{
	unsigned char endp;
	unsigned char bRecipient = ControlData.DeviceRequest.bmRequestType & USB_RECIPIENT;

	if (bRecipient == USB_RECIPIENT_DEVICE && ControlData.DeviceRequest.wValue == USB_FEATURE_REMOTE_WAKEUP)
	{											//清除远程唤醒功能
		DISABLE;
		bEPPflags.bits.remote_wakeup = 0;
		ENABLE;
		single_transmit(0, 0);
	}
	else if (bRecipient == USB_RECIPIENT_ENDPOINT && ControlData.DeviceRequest.wValue == USB_FEATURE_ENDPOINT_STALL)
	{											//清除端点stall
		endp = (unsigned char)(ControlData.DeviceRequest.wIndex & MAX_ENDPOINTS);
		if (ControlData.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -