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

📄 usbd12.c

📁 1.实现单片机驱动USBD12的固件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*******************************************
  文件:USBD12.C
  环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10 
  硬件:ATMEGA16芯片
  日期:2006年12月10日 
  功能:驱动开发板上的USBD12
  备注:参考《PDIUSBD12USB固件编程与驱动开发》(北航出版社)
/******************************************/
#include <iom16v.h>			//包含型号头文件
#include <macros.h>			//包含"位"操作头文件
#include <stdio.h>			//标准输入输出头文件
#include <AVR_PQ1A.h>		//包含自定义常量头文件
#include "LED.C"
#include "SKEY.C"

#pragma interrupt_handler USB_INT1:3//外部中断1中断服务函数声明
struct flags
{
	uchar bus_reset           	;	//总线复位标志
	uchar suspend             	;	//挂起改变标志
	uchar setup_packet  	  	;	//收到SETUP包
	uchar remote_wakeup			;
	uchar in_isr		      	;	//USB中断服务标志
	uchar control_state			;	//控制端点处理标志
													//0: IDLE	   空闲状态
													//1: TRANSMIT  数据发送状态
													//2: RECEIVE   数据接收状态
 	uchar configuration			;	//配置标志(0: 未配置; 1: 已经配置)		
	uchar ep1_rxdone			;	//端点 1 收到数据标志
	uchar ep2_rxdone			;	//端点 2 收到数据标志
	uchar ep2buf_full			;	//端点 2 接收双缓冲区满标志
}USB_FLAG={0,0,0,0,0,0,0,0,0,0};
typedef struct request
{
	uchar bmRequestType;
	uchar bRequest;
	uint wValue;
	uint wIndex;
	uint wLength;
}DEVICE_REQUEST;
typedef struct xfer
{
	DEVICE_REQUEST DeviceRequest;
	uint wLength;
	uint wCount;
	uchar * pData;
	uchar dataBuffer[MAX_CTLDAT_SIZE];
}CONTROL_XFER;
typedef struct _USB_DEVICE_DESCRIPTOR 
{
    uchar bLength;
    uchar bDescriptorType;
    uchar bcdUSB0;
    uchar bcdUSB1;
    uchar bDeviceClass;
    uchar bDeviceSubClass;
    uchar bDeviceProtocol;
    uchar bMaxPacketSize0;
    uchar idVendor0;
    uchar idVendor1;
    uchar idProduct0;
    uchar idProduct1;
    uchar bcdDevice0;
    uchar bcdDevice1;
    uchar iManufacturer;
    uchar iProduct;
    uchar iSerialNumber;
    uchar bNumConfigurations;
} USB_DEVICE_DESCRIPTOR;
/***********  USB  接口描述符结构体  ****************/
typedef struct _USB_INTERFACE_DESCRIPTOR 
{
    uchar bLength;
    uchar bDescriptorType;
    uchar bInterfaceNumber;
    uchar bAlternateSetting;
    uchar bNumEndpoints;
    uchar bInterfaceClass;
    uchar bInterfaceSubClass;
    uchar bInterfaceProtocol;
    uchar iInterface;
} USB_INTERFACE_DESCRIPTOR;
/***********  USB  配置描述符结构体  ****************/
typedef struct _USB_CONFIGURATION_DESCRIPTOR 
{
    uchar bLength;
    uchar bDescriptorType;
    uchar wTotalLength0;
    uchar wTotalLength1;
    uchar bNumInterfaces;
    uchar bConfigurationValue;
    uchar iConfiguration;
    uchar bmAttributes;
    uchar MaxPower;
} USB_CONFIGURATION_DESCRIPTOR;
/***********  USB  端点描述符结构体  ****************/
typedef struct _USB_ENDPOINT_DESCRIPTOR 
{
    uchar bLength;
    uchar bDescriptorType;
    uchar bEndpointAddress;
    uchar bmAttributes;
    uchar wMaxPacketSize0;
    uchar wMaxPacketSize1;
    uchar bInterval;
} USB_ENDPOINT_DESCRIPTOR;
/***********  D12 USB 各种描述符结构体 *********************/
typedef struct _USB_DESCRIPTOR 
{
	USB_CONFIGURATION_DESCRIPTOR ConfigDescr;		//配置描述符
	USB_INTERFACE_DESCRIPTOR InterfaceDescr;		//接口描述符
	USB_ENDPOINT_DESCRIPTOR EP1_TXDescr;			//端点1输入描述符
	USB_ENDPOINT_DESCRIPTOR EP1_RXDescr;			//端点1输出描述符
	USB_ENDPOINT_DESCRIPTOR EP2_TXDescr;			//端点2输入描述符
	USB_ENDPOINT_DESCRIPTOR EP2_RXDescr;			//端点2输出描述符
} USB_DESCRIPTOR;
CONTROL_XFER ControlData;
uchar GenEpBuf[EP1_PACKET_SIZE];			//端点1接收缓冲区
uchar EpBuf[EP2_PACKET_SIZE];				//端点2接收缓冲区
//#pragma data:code
//设备描述符
USB_DEVICE_DESCRIPTOR DeviceDescr =
{
	sizeof(USB_DEVICE_DESCRIPTOR),				//设备描述符长度,= 12H
	USB_DEVICE_DESCRIPTOR_TYPE,					//设备描述符类型,= 01H
	0x00,0x10,										//协议版本,= 1.10
	USB_CLASS_CODE_TEST_CLASS_DEVICE,			//测试设备类型, = 0DCH	
	0, 0,										//设备子类,设备协议
	EP0_PACKET_SIZE,							//端点0最大数据包大小,= 10H	
	0x71,0x04,									//PHILIPS公司的设备ID	
	0x66,0x06,									//设备制造商定的产品ID
	0x00,0x01,									//设备系列号
	0, 0, 0,									//索引
	1											//可能的配置数
};
USB_DESCRIPTOR usb_descr =
{
//配置描述符
{
	sizeof(USB_CONFIGURATION_DESCRIPTOR),		//配置描述符长度,= 09H
	USB_CONFIGURATION_DESCRIPTOR_TYPE,			//配置描述符类型,= 02H
	CONFIG_DESCRIPTOR_LENGTH,0x00,				//描述符总长度, = 002EH
	1,											//只支持1个接口
	1,											//配置值
	0,											//字符串描述符指针(无)
	0xa0,										//自供电,支持远程唤醒
	0x32										//最大功耗(100mA)
},
//接口描述符
{
	sizeof(USB_INTERFACE_DESCRIPTOR),			//接口描述符长度,= 09H
	USB_INTERFACE_DESCRIPTOR_TYPE,				//接口描述符类型,= 04H
	0,											//接口数,只有1个
	0,											//可选配置,只有1个
	NUM_ENDPOINTS,								//除端点0的端点索引数目,= 04H
	USB_CLASS_CODE_TEST_CLASS_DEVICE,			//测试设备类型,= 0DCH
	USB_SUBCLASS_CODE_TEST_CLASS_D12,			//子类代码,= 0A0H	
	USB_PROTOCOL_CODE_TEST_CLASS_D12,			//协议代码,= 0B0H
	0											//字符串描述符索引
},
//端点描述符,端点1输入
{
	sizeof(USB_ENDPOINT_DESCRIPTOR),			//端点描述符长度,= 07H
	USB_ENDPOINT_DESCRIPTOR_TYPE,				//端点描述符类型,= 05H
	0x81,										//端点1 IN
	USB_ENDPOINT_TYPE_INTERRUPT,				//中断传输, = 03H
	EP1_PACKET_SIZE,0x00,						//端点最大包的大小,= 0010H
	10											//传输间隔时间,= 10ms
},
//端点描述符,端点1输出
{
	sizeof(USB_ENDPOINT_DESCRIPTOR),			//端点描述符长度,= 07H
	USB_ENDPOINT_DESCRIPTOR_TYPE,				//端点描述符类型,= 05H
	0x1,										//端点1 OUT
	USB_ENDPOINT_TYPE_INTERRUPT,				//中断传输,= 03H
	EP1_PACKET_SIZE,0x00,						//端点最大包的大小,= 0010H
	10											//传输间隔时间,= 10ms
},
//端点2输入
{
	sizeof(USB_ENDPOINT_DESCRIPTOR),			//端点描述符长度,= 07H
	USB_ENDPOINT_DESCRIPTOR_TYPE,				//端点描述符类型,= 05H
	0x82,										//端点2 OUT
	USB_ENDPOINT_TYPE_BULK,						//批量传输,= 02H
	EP2_PACKET_SIZE,0x00,						//端点最大包的大小,= 0040H
	10											//批量传输时该设备无效
},
//端点2输出
{
	sizeof(USB_ENDPOINT_DESCRIPTOR),			//端点描述符长度,= 07H
	USB_ENDPOINT_DESCRIPTOR_TYPE,				//端点描述符类型,= 05H
	0x2,										//端点2 IN	
	USB_ENDPOINT_TYPE_BULK,						//批量传输,= 02H
	EP2_PACKET_SIZE,0x00,						//端点最大包的大小,= 0040H
	10											//批量传输时该设备无效
} 
};
//#pragma data:data
//#pragma data:code
void (*StandardDeviceRequest[])(void)=
{
	Get_status,
	Clr_feature,
	Reserved,
	Set_feature,
	Reserved,
	Set_addr,
	Get_descriptor,
	Reserved,
	Get_config,
	Set_config,
	Get_interface,
	Set_interface,
	Reserved,
	Reserved,
	Reserved,
	Reserved
};
//#pragma data:data
/*******************************************
函数名称: D12_init
功    能: 初始化D12接口(包括数据接口和控制接口)
参    数: 无
返回值  : 无
/********************************************/
void D12_init(void)
{
 DDRA|=BIT(CSUSB); 				//USB的573锁存端设置为输出			  
 PORTA&=~BIT(CSUSB);			//573锁存端关闭
 USBDAT_DDR|=0xFF;				//数据端口设置为输出
 USBCTL_DDR|=BIT(WR_N)|BIT(RD_N)|BIT(C_D)|BIT(D12_CS);//控制引脚设置为输出
 USBCTL_DDR&=~BIT(D12_INT);							  //中断引脚设置为输入				  
 USBCTL_PORT|=BIT(D12_INT);							  //上拉使能
 USBCTL_PORT|=BIT(WR_N)|BIT(RD_N)|BIT(D12_CS);		  //控制引脚无效
 PORTA|=BIT(CSUSB);									  //送出控制信号
 
 SREG|=BIT(GLOBAL);					//使能全局中断
 MCUCR&=0xF3;						//外部中断1采用低电平触发
 GICR|=BIT(EXTINT1);	//使能外部中断0和1  
 
 USBCTL_PORT&=~BIT(D12_CS);
}
/*******************************************
函数名称: OutB
功    能: 向D12写入一个字节数据或者命令
参    数: cmd--命令标识(为CMD是命令,为DAT是数据)
	  	  dat--要写入的字节数据
返回值  : 无
/********************************************/
void OutB(uchar cmd,uchar dat)
{
 if(cmd==CMD)
 {
  USBCTL_PORT|=BIT(C_D); 
  Delayus(5);
  USBCTL_PORT&=~BIT(WR_N);
  Delayus(5);
  USBDAT_PORT=dat;  
  Delayus(5);
  USBCTL_PORT|=BIT(WR_N);
 }
 else
 {
  USBCTL_PORT&=~BIT(C_D);
  Delayus(1);
  USBCTL_PORT&=~BIT(WR_N);
  Delayus(1);
  USBDAT_PORT=dat;  
  Delayus(1);
  USBCTL_PORT|=BIT(WR_N);
 }
}
/*******************************************
函数名称: InB
功    能: 从D12读出一个字节数据
参    数: 无
返回值  : dat--读出的字节数据
/********************************************/
uchar InB(void)
{ 
  uchar dat;
  USBDAT_DDR=0x00;
  USBDAT_PORT=0xFF;
  USBCTL_PORT&=~BIT(C_D);
  Delayus(1);
  USBCTL_PORT&=~BIT(RD_N);
  Delayus(1);
  dat=USBDAT_PIN;
  Delayus(1);
  USBCTL_PORT|=BIT(RD_N);
  USBDAT_DDR=0xFF;
  return dat;
}
/*******************************************
函数名称: Set_addren
功    能: 设置地址/使能----------------------------
参    数: addr--设置的地址
	  	  enable--使能标志(为1使能,为0禁止)
返回值  : 无
/********************************************/
void Set_addren(uchar addr, uchar enable)
{
	if(USB_FLAG.in_isr == 0)
		UEN_GINT();

	OutB(CMD, 0xD0);	//输出设置地址/使能指令
	Delayus(1);
	if(enable)
	{
		addr|=0x80;		//bit7置1,使能
	}
	Delayus(1);
	OutB(DAT,addr);		//输出设置值

	if(USB_FLAG.in_isr == 0)
		EN_GINT();
}
/*******************************************
函数名称: Set_EPen
功    能: 设置端点使能
参    数: enable--使能标志(为1使能,为0禁止)
返回值  : 无
/********************************************/
void Set_EPen(uchar enable)
{
	if(USB_FLAG.in_isr == 0)
		UEN_GINT();

	OutB(CMD,0xD8);	//输出设置端点使能指令
	Delayus(1);
	if(enable)
		OutB(DAT,1);		//设置端点允许
	else
		OutB(DAT,0);		//设置端点禁止

	if(USB_FLAG.in_isr == 0)
		EN_GINT();
}
/*******************************************
函数名称: Set_mode
功    能: 设置模式
参    数: config--配置字节信息
	  	  clkdiv--分频因子
返回值  : 无
/********************************************/
void Set_mode(uchar config,uchar clkdiv)
{
	if(USB_FLAG.in_isr == 0)
		UEN_GINT();

	OutB(CMD,0xF3);		//输出设置模式指令
	Delayus(1);
	OutB(DAT,config);		//输出配置字节信息
	OutB(DAT,clkdiv);		//输出时钟分频因数字节

	if(USB_FLAG.in_isr == 0)
		EN_GINT();	
}
/*******************************************
函数名称: Set_DMA
功    能: 设置DMA工作方式设置
参    数: bMode--设置值
返回值  : 无
/********************************************/
void Set_DMA(uchar bMode)
{
	if(USB_FLAG.in_isr == 0)
		UEN_GINT();

	OutB(CMD, 0xFB);	//设置DMA工作方命令
	Delayus(1);
	OutB(DAT, bMode);		//输出设置值

	if(USB_FLAG.in_isr == 0)
		EN_GINT();			
}

/*******************************************
函数名称: Read_IntR
功    能: 读取中断寄存器值
参    数: 无
返回值  : intreg--16位中断寄存器值
/********************************************/
uint Read_IntR(void)
{
	uchar regl;
	uint  intreg;

	OutB(CMD,0xF4);	//读取中断寄存器命令
	Delayus(5);
	regl=InB( );			//读取低8位字节
	intreg=InB( );			//读取高8位字节

	intreg<<=8;
	intreg+=regl;			//组合为16位

	return intreg;
}
/*******************************************
函数名称: Sel_EP
功    能: 端点选择,将内部指针初始化到选择的缓冲区起始位置
参    数: endp--端点索引号,取值0 ~ 5
返回值  : byte--一个字节的返回数据
/********************************************/
uchar Sel_EP(uchar endp)
{
	uchar byte;
	if(USB_FLAG.in_isr == 0)
		UEN_GINT();

	OutB(CMD,endp);	//端点选择
	Delayus(1);
	byte=InB( );			//读出一个字节

	if(USB_FLAG.in_isr == 0)
		EN_GINT();

	return byte;
}
/*******************************************
函数名称: Sel_EP
功    能: 读取端点状态
参    数: endp--端点索引号,取值0 ~ 5
返回值  : status--端点状态
/********************************************/

⌨️ 快捷键说明

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