📄 usb2uart.c
字号:
/******************************************************************
本程序只供学习使用,未经作者许可,不得用于其它任何用途
欢迎访问我的USB专区:http://group.ednchina.com/93/
欢迎访问我的blog: http://www.ednchina.com/blog/computer00
http://computer00.21ic.org
感谢wang1jin为本PCB的检查以及元件的采购,欢迎大家访问wang1jin的博客:
http://www.ednchina.com/blog/wang1jin/
USB2UART.C file
作者:Computer-lov
建立日期: 2007.03.20
修改日期: 2007.03.23
版本:V1.1
版权所有,盗版必究。
Copyright(C) Computer-lov 2007-2017
All rights reserved
*******************************************************************/
#include "AT89x52.H"
#include "USB.H"
#include "PDIUSBD12.H"
#include "My_type.h"
#include "UART.H"
#include "led.h"
#define DispLineInf() \
{ \
Prints(" in file \""); \
Prints(__FILE__); \
Prints(", @ line "); \
PrintLongInt(__LINE__-1); \
Prints("\r\n"); \
}
//#define debug
#define USB_COMMAND_ADD 1
#define USB_DATA_ADD 0
//USB芯片连接引脚
#define USB_DATA P0
#define USB_A0 P3_5
#define USB_WR P3_6
#define USB_RD P3_7
#define USB_INT P3_2
#define DTR P2_0
#define RTS P2_1
#define TXD P3_1
#define ENDPOINT_NUMBER 2
#define MAX_CONTROL_DATA_SIZE 16
//控制传输时保存数据
CONTROL_DATA_BUFF Control_Data;
//缓冲
uint8 idata OutBuffer[64],InBuffer[64];
//数据计数器
uint8 idata InCount;
//数据位置
uint8 idata pIn;
//溢出标志
uint8 idata Overflow;
//交换数据时用的指针
uint8 *pData;
uint8 idle; //空闲状态
uint8 protocol; //当前协议
//当前串口设置
LINE_CODING LineCoding;
//高低字节交换
#define SWAP16(x) ((((uint16)(x))<<8)|(((uint16)(x))>>8))
#define SWAP32(x) ((((uint32)SWAP16(x))<<16)|SWAP16((x)>>16))
//取一个整数的低字节
#define LSB(x) ((uint8)(x))
//取一个整数的高字节
#define MSB(x) ((uint8)(((uint16)(x))>>8))
//字符串描述符所用的语言种类
code uint8 LANGUAGE_ID[4]={0x04,0x03,0x09,0x04};
//设备序列号
code uint8 device_serial_number[]=
{22,STRING_DESCRIPTOR,'2',0,'0',0,'0',0,'7',0,'-',0,'1',0,'1',0,'-',0,'2',0,'9',0};
//厂商字符串 电脑圈圈的USB专区 http://group.ednchina.com/93
//汉字Unicode编码,使用http://computer00.21ic.org/user1/2198/archives/2007/42769.html转换
code uint8 ManufacturerString[80]=
{80,STRING_DESCRIPTOR,0x35,0x75,0x11,0x81,0x08,0x57,0x08,0x57,0x84,0x76,'U',0x00,
'S',0x00,'B',0x00,0x13,0x4E,0x3A,0x53,0x20,0x00,'H',0,'t',0,'t',0,
'p',0,':',0,'/',0,'/',0,'g',0,'r',0,'o',0,'u',0,'p',0,'.',0,'e',0,'d',0,'n',0,
'c',0,'h',0,'i',0,'n',0,'a',0,'.',0,'c',0,'o',0,'m',0,'/',0,'9',0,'3',0};
//产品字符串 电脑圈圈的USB专区活动之USB转串口 http://group.ednchina.com/93
//汉字Unicode编码,使用http://computer00.21ic.org/user1/2198/archives/2007/42769.html转换
code uint8 ProducterString[98]=
{98,STRING_DESCRIPTOR,0x35,0x75,0x11,0x81,0x08,0x57,0x08,0x57,0x84,0x76,'U',0x00,
'S',0x00,'B',0x00,0x13,0x4E,0x3A,0x53,0x3B,0x6D,0xA8,0x52,0x4B,0x4E,'U',0x00,
'S',0x00,'B',0x00,0x6C,0x8F,0x32,0x4E,0xE3,0x53,0x20,0x00,'H',0,'t',0,'t',0,
'p',0,':',0,'/',0,'/',0,'g',0,'r',0,'o',0,'u',0,'p',0,'.',0,'e',0,'d',0,'n',0,
'c',0,'h',0,'i',0,'n',0,'a',0,'.',0,'c',0,'o',0,'m',0,'/',0,'9',0,'3',0};
code DEVICE_DESCRIPTOR_STRUCT device_descriptor= //设备描述符
{
sizeof(DEVICE_DESCRIPTOR_STRUCT), //设备描述符的字节数大小
DEVICE_DESCRIPTOR, //设备描述符类型编号
SWAP16(0x0110), //USB版本号,USB1.1
0x02, //USB分配的设备类代码,通信设备类(CDC)
0x00, //USB分配的子类代码
0x00, //USB分配的设备协议代码
0x10, //端点0的最大包大小
SWAP16(0x8888), //厂商编号VID,这里只是作为测试用,请使用自己的VID
SWAP16(0x0006), //产品编号PID,这里只是作为测试用,请使用自己的PID
SWAP16(0x0001), //设备出厂编号
0x01, //设备厂商字符串的索引
0x02, //描述产品字符串的索引
0x03, //描述设备序列号字符串的索引
0x01 //可能的配置数量
};
//定义配置,接口,端点等描述符结构体,因为它们是随配置描述符一起返回的
typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
{
CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;
INTERFACE_DESCRIPTOR_STRUCT interface0_descriptor;
HEADER_FUNCTIONAL_DESCRIPTOR header_functional_descriptor;
CALL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR call_management_functional_descriptor;
ABSTRACT_CONTROL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR abstract_ontrol_anagement_unctional_escriptor;
UNION_FUNCTIONAL_DESCRIPTOR union_functional_descriptor;
ENDPOINT_DESCRIPTOR_STRUCT endpoint1in_descriptor;
INTERFACE_DESCRIPTOR_STRUCT interface1_descriptor;
ENDPOINT_DESCRIPTOR_STRUCT endpoint2in_descriptor;
ENDPOINT_DESCRIPTOR_STRUCT endpoint2out_descriptor;
}CON_INT_ENDP_DESCRIPTOR_STRUCT;
code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor=
{
//configuration_descriptor //配置描述符
{
sizeof(CONFIGURATION_DESCRIPTOR_STRUCT), //配置描述符的字节数大小
CONFIGURATION_DESCRIPTOR, //配置描述符类型编号
SWAP16(sizeof(CON_INT_ENDP_DESCRIPTOR_STRUCT)),
0x02, //只包含一个接口
0x01, //该配置的编号
0x00, //iConfiguration字段
0xA0, //采用总线供电,支持远程唤醒
0xC8 //从总线获取最大电流400mA
},
//CDC interface_descritor //CDC类接口描述符
{
sizeof(INTERFACE_DESCRIPTOR_STRUCT), //接口描述符的字节数大小
INTERFACE_DESCRIPTOR, //接口描述符类型编号
0x00, //接口编号为0
0x00, //该接口描述符的备用编号
0x01, //非0端点数量为1,端点1中断
0x02, //所使用的类,Communication Interface Class
0x02, //使用的子类,Abstract Control Model
0x01, //使用的协议,Common AT commands
0x00 //接口描述符字符串索引
},
//header_functional_descriptor
{
sizeof(HEADER_FUNCTIONAL_DESCRIPTOR), //Size of this descriptor in bytes
CS_INTERFACE_DESCRIPTOR, //CS_INTERFACE descriptor type
0x00, //Header functional descriptor subtype
SWAP16(0x0110) //CDC版本号
},
//call_management_functional_descriptor
{
sizeof(CALL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR), //Size of this descriptor in bytes
CS_INTERFACE_DESCRIPTOR, //CS_INTERFACE descriptor type
0x01, //Call Management functional descriptor subtype
0x00, //D1=0: Device sends receives call management
//information only over the Communication Class interface.
//D0=0: Device does not handle call management itself
0x00 //Interface number of Data Class interface optionally used for call management(here not use).
},
//abstract_ontrol_anagement_unctional_escriptor
{
sizeof(ABSTRACT_CONTROL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR), //Size of this descriptor in bytes
CS_INTERFACE_DESCRIPTOR, //CS_INTERFACE descriptor type
0x02, //Abstract Control Management functional descriptor subtype
0x02, //D3=0: Device DO NOT supports the notification Network_Connection.
//D2=0: Device DO NOT supports the request Send_Break
//D1=0: Device supports the request combination of
// Set_Line_Coding,Set_Control_Line_State,
// Get_Line_Coding, and the notification Serial_State.
},
//union_functional_descriptor
{
sizeof(UNION_FUNCTIONAL_DESCRIPTOR), //Size of this descriptor in bytes
CS_INTERFACE_DESCRIPTOR, //CS_INTERFACE descriptor type
0x06, //Union functional descriptor SubType
0x00, //MasterInterface,CDC接口
0x01 //SlaveInterface,数据接口
},
//endpoint1in_descriptor
{ //中断输入端点描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //端点描述符类型编号
POINT_1_IN, //端点号,输入端点1
ENDPOINT_TYPE_INTERRUPT, //使用的传输类型:中断传输
SWAP16(0x0010), //该端点支持的最大包尺寸,16字节
0x01 //中断扫描时间:设置为1ms
},
//interface_descritor //数据接口描述符
{
sizeof(INTERFACE_DESCRIPTOR_STRUCT), //接口描述符的字节数大小
INTERFACE_DESCRIPTOR, //接口描述符类型编号
0x01, //接口编号为1
0x00, //该接口描述符的备用编号
0x02, //端点数量为2,使用主端点输入和输出
0x0A, //所使用的类,Data Interface Class
0x00, //使用的子类
0x00, //使用的协议,Common AT commands
0x00 //接口描述符字符串索引
},
//endpoint2in_descriptor
{ //主端点输入描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //端点描述符类型编号
MAIN_POINT_IN, //端点号,主输入端点
ENDPOINT_TYPE_BULK, //使用的传输类型:批量传输
SWAP16(0x0040), //该端点支持的最大包尺寸,64字节
0x0A //中断扫描时间:批量端点无效
},
{ //主端点输出描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //端点描述符类型编号
MAIN_POINT_OUT, //端点号,主输出端点
ENDPOINT_TYPE_BULK, //使用的传输类型:批量传输
SWAP16(0x0040), //该端点支持的最大包尺寸,64字节
0x0A //中断扫描时间:批量端点无效
}
};
union //程序标志位
{
uint16 Register;
struct
{
uint8 bus_reset :1;
uint8 suspend :1;
uint8 remote_wakeup :1;
uint8 int_isr :1;
uint8 not_end :1;
uint8 usb_idle :1;
uint8 usb_busy :1;
uint8 setup_packet_in :1;
uint8 setup_packet_out :1;
uint8 set_addr :1;
uint8 usb_endp0_in :1;
uint8 usb_endp2_in :1;
uint8 usb_endp2_out :1;
}flags;
}usb_flags;
union //中断寄存器
{
uint8 Register[2];
struct
{
uint8 control_out_port :1;
uint8 control_in_port :1;
uint8 port_out_1 :1;
uint8 port_in_1 :1;
uint8 main_out_port :1;
uint8 main_in_port :1;
uint8 bus_reset :1;
uint8 suspend_change :1;
uint8 DMA_EOT :1;
uint8 not_use :7;
}Interrupt;
}Interrupt_Register;
union //端点最后处理状态
{
uint8 Register;
struct
{
uint8 successful :1;
uint8 error_code :4;
uint8 setup_packet :1;
uint8 data_1 :1;
uint8 prestatus_not_read :1;
}Status;
}Last_Status;
/***************** 延时x毫秒函数 ***********/
void delay(uint16 x)
{
uint16 i;
uint16 j;
for(i=0;i<x;i++)
for(j=0;j<230;j++);
}
/********************************************/
/*******************************写USB命令******************************************/
void write_usb_command(uint8 usb_command)
{
USB_A0=USB_COMMAND_ADD;
USB_DATA=usb_command;
USB_WR=0;
USB_WR=1;
USB_DATA=0xFF;
}
/******************************************************************************/
/*********************写一字节USB数据*******************************************/
void write_a_usb_data(uint8 usb_data)
{
USB_A0=USB_DATA_ADD;
USB_DATA=usb_data;
USB_WR=0;
USB_WR=1;
USB_DATA=0XFF;
}
/******************************************************************************/
/****************************读一字节USB数据************************************/
uint8 read_a_usb_data(void)
{
uint8 temp;
USB_A0=USB_DATA_ADD;
USB_RD=0;
temp=USB_DATA;
USB_RD=1;
return temp;
}
/******************************************************************************/
/************************读USB中断寄存器**************************************/
void read_interrupt_register(void)
{
write_usb_command(Read_Interrupt_Register);
Interrupt_Register.Register[0]=read_a_usb_data();
Interrupt_Register.Register[1]=read_a_usb_data();
}
/******************************************************************************/
/************************设置USB地址*******************************************/
void set_usb_addr(uint8 addr)
{
write_usb_command(Set_Address);
write_a_usb_data(0x80|addr);
#ifdef debug
Prints(" 设置地址.\r\n");
Prints(" 地址为: ");
PrintLongInt(addr);
Prints("\r\n");
#endif
}
/******************************************************************************/
/*************************端点使能******************************************/
void set_endpoint_enable(void)
{
write_usb_command(Set_Endpoint_Enable);
write_a_usb_data(0x01);
}
/******************************************************************************/
/****************************选择终端点*************************************/
uint8 select_endpoint(uint8 endp)
{
write_usb_command(Select_EndPoint+endp);
return read_a_usb_data();
}
/******************************************************************************/
/****************************读端点最后状态**********************************/
uint8 read_last_status(uint8 endp)
{
write_usb_command(Read_Last_Status+endp);
return read_a_usb_data();
}
/******************************************************************************/
/****************************设置端点状态**************************************/
void set_endpoint_status(uint8 endp,uint8 status)
{
write_usb_command(0x40+endp);
write_a_usb_data(!status);
}
/******************************************************************************/
/*****************************读端点状态**************************************/
uint8 read_endpoint_status(uint8 endp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -