1. usbClassGetInterfaceSetting中接口数量改为1,因为这里有2个接口
RESULT usbClassGetInterfaceSetting(uint8_t Interface, uint8_t AlternateSetting)
{
if (AlternateSetting > 0)
{
return USB_UNSUPPORT;
}
else if (Interface > 1)
{
return USB_UNSUPPORT;
}
return USB_SUCCESS;
}
2. CDC类的请求说明
#define SEND_ENCAPSULATED_COMMAND 0x00
#define GET_ENCAPSULATED_RESPONSE 0x01
#define SET_COMM_FEATURE 0x02
#define GET_COMM_FEATURE 0x03
#define CLEAR_COMM_FEATURE 0x04
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
#define SEND_BREAK 0x23
a) SEND_ENCAPSULATED_COMMAND
此请求用于发出通信类接口支持的控制协议格式的命令。不用支持。
b) GET_ENCAPSULATED_RESPONSE
此请求用于以通信类接口支持的控制协议的格式请求响应。不用支持。
c) SET_COMM_FEATURE
此请求设置特定目标的特定通信功能的特性
具体解释与GET_COMM_FEATURE一样。
d) GET_COMM_FEATURE
此请求返回所选通信功能的当前设置
wValue表示特征值,有2个有效值,分别为
0x01: ABSTRACT_STATE,wLength = 2, Data描述这个抽象模型通信设备的多路复用状态和空闲状态,即仅对抽象模型通信设备有效。这2个字节数据的含义如下:
bit | 描述 |
D15:D2 | 保留位 |
D1 | 数据复用状态: 1:在数据类上启用呼叫管理命令的多路复用。 0:禁止复用 |
D0 | 空闲设定 1:这个接口上的所有端点将不再接受或发送数据 0:关闭空闲模式 |
0x02: COUNTRY_SETTING,wLength = 2, 2字节数据是ISO 3166中定义的十六进制国家代码。
e) CLEAR_COMM_FEATURE
此请求将选定功能设置为其默认状态。参考GET_COMM_FEATURE
d) SET_LINE_CODING
此请求允许主机指定一些应用程序可能需要的异步行字符格式属性。对于虚拟串口就是设置波特率之类的参数。具体参考GET_LINE_CODING。
e) GET_LINE_CODING
此请求允许主机找出当前配置的行编码。
行编码的结构如下:
Offset | Filed | Size | Value | Description |
0 | dwDTERate | 4 | Number | 数据终端速率,单位为位/秒。这里是波特率 |
4 | bCharFormat | 1 | Number | 停止位: 0 - 1个停止位 1 - 1.5个停止位 2 - 2个停止位 |
5 | bParityType | 1 | Number | 校验位: 0 - None 1 - Odd 2 - Even 3 - Mark 4 - Space |
6 | bDataBits | 1 | Number | 数据位 5, 6, 7, 8或16 |
f) SET_CONTROL_LINE_STATE
此请求生成RS-232的RTS和DTR。
wValue是控制信号位图。
Bit position | Description |
D15..D2 | 预留 |
D1 | 半双工调制解调器的载波控制。该信号对应RTS。 0:停用载波 1:激活载波 在全双工模式下操作时,设备忽略此位的值。 |
D0 | 向DCE指示DTE是否存在。该信号对应DTR。 0:不存在 1:存在 |
g) SEND_BREAK
此请求发送特殊的载波调制,生成RS-232型中断。
wValue字段是中断信号的时间长度(以毫秒为单位)。如果wValue等于FFFFh,设备将发送中断,直到收到另一个wValue为0000h的send break请求。
3. DataSetup中添加GET_LINE_CODING和SET_LINE_CODING的处理
RESULT usbClassDataSetup(uint8_t RequestNo)
{
uint8_t *(*CopyRoutine)(uint16_t);
CopyRoutine = NULL;
if (RequestNo == GET_LINE_CODING)
{
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
CopyRoutine = usbVComGetLineCoding;
}
}
else if (RequestNo == SET_LINE_CODING)
{
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
CopyRoutine = usbVComSetLineCoding;
}
Request = SET_LINE_CODING;
}
if (CopyRoutine == NULL)
{
return USB_UNSUPPORT;
}
pInformation->Ctrl_Info.CopyData = CopyRoutine;
pInformation->Ctrl_Info.Usb_wOffset = 0;
(*CopyRoutine)(0);
return USB_SUCCESS;
}
获取LINE_CODING就是返回串口的设定
uint8_t* usbVComGetLineCoding(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = sizeof(stUartConfig);
return NULL;
}
return(uint8_t *)&stUartConfig;
}
其中结构体变量stUartConfig是全局变量,记录串口的波特率等参数。
lineCoding_st stUartConfig =
{
115200, /* baud rate*/
0x00, /* stop bits-1*/
0x00, /* parity - none*/
0x08 /* no. of bits 8*/
};
设定串口的参数,这里只是更新了变量里面的值。
uint8_t* usbVComSetLineCoding(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = sizeof(stUartConfig);
return NULL;
}
return(uint8_t *)&stUartConfig;
}
在statusin里面设定uart参数
void usbClassStatusIn(void)
{
if (Request == SET_LINE_CODING)
{
uartConfig(UART_VCOM, &stUartConfig);
Request = 0;
}
}
4. 修改NoData_Setup
RESULT usbClassNoDataSetup(uint8_t RequestNo)
{
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
{
if (RequestNo == SET_COMM_FEATURE)
{
return USB_SUCCESS;
}
else if (RequestNo == SET_CONTROL_LINE_STATE)
{
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}
基本功能OK,可以短接RxD和TxD,然后用一个串口工具验证功能。
碰到一个问题,记录一下:
PC端的串口工具有时候打开会提示串口被占用,原因是USB中断中加了一部分打印,去掉所有打印后恢复正常。