写一段代码实现AT90USB1286的USB设备配置,要求能够在电脑端识别为USB串口设备
时间: 2024-02-05 12:12:41 浏览: 142
以下是一个AT90USB1286的USB设备配置的示例代码,能够在电脑端识别为USB串口设备:
```c
#include <avr/io.h>
#include <stdbool.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
// USB endpoint address for the virtual serial port
#define CDC_TX_EPADDR (ENDPOINT_DIR_IN | 1)
#define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | 2)
#define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | 3)
// Size of the USB endpoint buffers
#define CDC_TXRX_EPSIZE 64
#define CDC_NOTIFICATION_EPSIZE 8
// USB device descriptor
USB_Descriptor_Device_t DeviceDescriptor = {
.Header = {
.Size = sizeof(USB_Descriptor_Device_t),
.Type = DTYPE_Device
},
.USBSpecification = VERSION_BCD(1, 1, 0),
.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_NoSpecificSubclass,
.Protocol = CDC_CSCP_NoSpecificProtocol,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x1234, // Change to your vendor ID
.ProductID = 0xCDC1, // Change to your product ID
.ReleaseNumber = VERSION_BCD(1, 0, 0),
.ManufacturerStrIndex = 0x01,
.ProductStrIndex = 0x02,
.SerialNumStrIndex = NO_DESCRIPTOR,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
// USB configuration descriptor
USB_Descriptor_Configuration_t ConfigurationDescriptor = {
.Config = {
.Header = {
.Size = sizeof(USB_Descriptor_Configuration_Header_t),
.Type = DTYPE_Configuration
},
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
.TotalInterfaces = 2,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.CDC_CCI_Interface = {
.Header = {
.Size = sizeof(USB_Descriptor_Interface_t),
.Type = DTYPE_Interface
},
.InterfaceNumber = 0,
.AlternateSetting = 0,
.TotalEndpoints = 1,
.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_ACMSubclass,
.Protocol = CDC_CSCP_VendorSpecificProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.CDC_Functional_IntHeader = {
.Header = {
.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t),
.Type = DTYPE_CSInterface
},
.Subtype = CDC_DSUBTYPE_CSInterface_Header,
.CDCSpecification = VERSION_BCD(1, 1, 0)
},
.CDC_Functional_AbstractControlManagement = {
.Header = {
.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t),
.Type = DTYPE_CSInterface
},
.Subtype = CDC_DSUBTYPE_CSInterface_ACM,
.Capabilities = 0x02
},
.CDC_Functional_Union = {
.Header = {
.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t),
.Type = DTYPE_CSInterface
},
.Subtype = CDC_DSUBTYPE_CSInterface_Union,
.MasterInterfaceNumber = 0,
.SlaveInterfaceNumber = 1
},
.CDC_NotificationEndpoint = {
.Header = {
.Size = sizeof(USB_Descriptor_Endpoint_t),
.Type = DTYPE_Endpoint
},
.EndpointAddress = CDC_NOTIFICATION_EPADDR,
.Attributes = EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA,
.EndpointSize = CDC_NOTIFICATION_EPSIZE,
.PollingIntervalMS = 0xFF
},
.CDC_DCI_Interface = {
.Header = {
.Size = sizeof(USB_Descriptor_Interface_t),
.Type = DTYPE_Interface
},
.InterfaceNumber = 1,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = CDC_CSCP_CDCDataClass,
.SubClass = CDC_CSCP_NoDataSubclass,
.Protocol = CDC_CSCP_NoDataProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.CDC_DataOutEndpoint = {
.Header = {
.Size = sizeof(USB_Descriptor_Endpoint_t),
.Type = DTYPE_Endpoint
},
.EndpointAddress = CDC_RX_EPADDR,
.Attributes = EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA,
.EndpointSize = CDC_TXRX_EPSIZE,
.PollingIntervalMS = 0x00
},
.CDC_DataInEndpoint = {
.Header = {
.Size = sizeof(USB_Descriptor_Endpoint_t),
.Type = DTYPE_Endpoint
},
.EndpointAddress = CDC_TX_EPADDR,
.Attributes = EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA,
.EndpointSize = CDC_TXRX_EPSIZE,
.PollingIntervalMS = 0x00
}
};
// USB string descriptor
USB_Descriptor_String_t * const StringDescriptors[] = {
[0] = NULL,
[1] = (USB_Descriptor_String_t*) L"Your manufacturer name",
[2] = (USB_Descriptor_String_t*) L"Your product name"
};
// USB configuration callback
bool CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, const void** const DescriptorAddress) {
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
switch (DescriptorType) {
case DTYPE_Device:
*DescriptorAddress = &DeviceDescriptor;
return true;
case DTYPE_Configuration:
*DescriptorAddress = &ConfigurationDescriptor;
return true;
case DTYPE_String:
if (DescriptorNumber < sizeof(StringDescriptors)/sizeof(USB_Descriptor_String_t*)) {
*DescriptorAddress = StringDescriptors[DescriptorNumber];
return true;
}
break;
}
return false;
}
// USB interface class callback
uint16_t CALLBACK_USB_GetDescriptor_Size(const uint16_t wValue, const uint8_t wIndex) {
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
switch (DescriptorType) {
case DTYPE_Device:
return sizeof(USB_Descriptor_Device_t);
case DTYPE_Configuration:
return sizeof(USB_Descriptor_Configuration_t);
case DTYPE_String:
if (DescriptorNumber < sizeof(StringDescriptors)/sizeof(USB_Descriptor_String_t*)) {
return pgm_read_byte(&StringDescriptors[DescriptorNumber]->Header.Size);
}
break;
}
return 0;
}
// USB endpoint configuration
void Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, const uint16_t Size, const uint8_t Banks) {
const uint8_t EndpointIndex = (Address & ENDPOINT_EPNUM_MASK);
// Select the endpoint
Endpoint_SelectEndpoint(EndpointIndex);
// Configure the endpoint
Endpoint_EnableEndpoint();
Endpoint_SetEndpointDirection(Address & ENDPOINT_DIR_MASK);
Endpoint_SetEndpointType(Type);
Endpoint_SetEndpointBufferSize(Size);
// Clear the endpoint banks
while (Banks) {
Endpoint_ClearEndpointBank();
Banks--;
}
// Enable the endpoint interrupt
Endpoint_SetEndpointInterrupts(EP_INT_ENABLE);
}
// USB initialization
void USB_Init(void) {
// Enable USB controller
USB_InitDevice();
// Configure USB endpoints
Endpoint_ConfigureEndpoint(CDC_TX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1);
Endpoint_ConfigureEndpoint(CDC_RX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1);
Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, 1);
}
// USB device task
void USB_Task(void) {
// Process USB events
USB_USBTask();
}
// Main program
int main(void) {
// Initialize USB
USB_Init();
// Enable global interrupts
sei();
while (true) {
// Process USB events
USB_Task();
// Your application code here
}
}
```
在此示例代码中,我们使用了LUFA库来简化USB设备的配置。在初始化函数`USB_Init()`中,我们配置了两个USB端点,一个是用于发送数据的端点,一个是用于接收数据的端点,另外还有一个中断端点,用于发送CDC通知。在主函数中,我们不断地调用`USB_Task()`函数来处理USB事件。
需要注意的是,在设备描述符中,我们使用了自己的厂商ID和产品ID,这些ID需要在申请USB许可证时向USB-IF组织获取。同时,我们还需要在PC端安装对应的驱动程序才能使用该USB设备。
阅读全文