?? usbd12.txt
字號:
/*******************************************
聯系我:937593195
文件: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 + -