來源:轉(zhuǎn)載自21ic論壇極海半導(dǎo)體專區(qū)
目前官方SDK的USB設(shè)備例程“APM32E10x_EVAL_SDK_v1.0”只有這幾個(gè),分別是:
CDC類 虛擬串口 “USB_CDC_VirtualCOMPort”
HID類 鼠標(biāo) “USB_HID_Mouse”
MCS類 大容量存儲(chǔ) “USB_MSC_Disk”
上面是沒有Printer類的,如果需要打印機(jī)類,可以在CDC例程的基礎(chǔ)上進(jìn)行修改,只需要幾步就可以實(shí)現(xiàn)一個(gè)USB的打印機(jī)設(shè)備。
1、USB打印機(jī)類的基礎(chǔ)知識(shí)
1.1、USB的設(shè)備類
常見的USB設(shè)備類有以下幾種,這里要實(shí)現(xiàn)就是07h號(hào)打印機(jī)類。
1.2、調(diào)試USB的工具軟件
USB數(shù)據(jù)抓包軟件 “Bus Hound”
枚舉信息查看軟件 “USBlyzer”
1.3、推薦幾個(gè)關(guān)于USB的基礎(chǔ)知識(shí)的網(wǎng)站
https://www.usbzh.com/article/detail-344.html
http://usb.baiheee.com/
1.4、 USB標(biāo)準(zhǔn)組織官網(wǎng)USB-IF上的資料
關(guān)于USB 2.0資料:
https://www.usb.org/document-library/usb-20-specification
關(guān)于 Printer Device Class 的文檔:
https://www.usb.org/document-library/printer-device-class-document-11
2、修改描述符
首先要通過修改描述符,來枚舉出“打印支持”設(shè)備。
在極海官網(wǎng)下載USB的SDK
https://www.geehy.com/support/apm32?id=305
APM32E10x_EVAL_SDK_v1.0.zip
注釋掉不用的代碼,例如LCD、KEY、LED,這些跟USB無關(guān)。
2.1 描述符的基礎(chǔ)知識(shí)
描述符分為:
設(shè)備描述符 Device Descriptor (g_usbDeviceDescriptor)
配置描述符 Configuration Descriptor (g_usbConfigDescriptor)
端點(diǎn)描述符 Endpoint Descriptor (g_usbConfigDescriptor)
詳細(xì)信息可以看這里:
http://usb.baiheee.com/usb_article/usb_spec/usb_cmd_desc.html
2.2 修改設(shè)備描述符
打開源文件 ....Sourceusbd_descriptor.c ,修改數(shù)組 g_usbDeviceDescriptor[] ,
這里只要把設(shè)備類從CDC 0x02 改為Printer 0x07。
/** bDeviceClass */
0x07, //0x02,
2.3 修改配置描述符和端點(diǎn)描述符
配置描述符和端點(diǎn)描述符都在數(shù)組 g_usbConfigDescriptor[] 中,我們只需要1個(gè)配置,該配置下有2個(gè)端點(diǎn),刪除多余的端點(diǎn),修改成下面這樣。
const uint8_t g_usbConfigDescriptor[USB_CONFIG_DESCRIPTOR_SIZE] =
{
/** bLength */
0x09,
/** bDescriptorType */
USBD_DESC_CONFIGURATION,
/** wTotalLength */
USB_CONFIG_DESCRIPTOR_SIZE & 0xFF, USB_CONFIG_DESCRIPTOR_SIZE >> 8,
0x01,//0x02,
/** bConfigurationValue */
0x01,
/** iConfiguration */
0x00,
/** bmAttributes */
0xC0,
/** MaxPower */
0x32,
/** bLength */
0x09,
/** bDescriptorType */
USBD_DESC_INTERFACE,
/** bInterfaceNumber */
0x00, //0x01,
/** bAlternateSetting */
0x00,
/** bNumEndpoints */
0x02, //0x01,
/** bInterfaceClass */
0x07,//0x02,
/** bInterfaceSubClass */
0x01, //0x02,
/** bInterfaceProtocol */
0x01, //0x01,
/** iInterface */
0x00,
0x07, /** bLength: Endpoint Descriptor size */
USBD_DESC_ENDPOINT, /** bDescriptorType: Endpoint */
0x01, /** bEndpointAddress */
0x02, /** bmAttributes: Bulk */
0x40,0x00, /** wMaxPacketSize: */
0x00, /** bInterval: */
0x07, /** bLength: Endpoint Descriptor size */
USBD_DESC_ENDPOINT, /** bDescriptorType: Endpoint */
0x81, /** bEndpointAddress */
0x02, /** bmAttributes: Bulk */
0x40,0x00, /** wMaxPacketSize: */
0x00 /** bInterval: */
};
2.4 測試是否枚舉成功
修改完描述符后,運(yùn)行程序,拔插USB,設(shè)備管理器中會(huì)出現(xiàn)“打印支持”,使用“USBlyzer”可以看到詳細(xì)的枚舉信息。
3 實(shí)現(xiàn)類特殊請(qǐng)求
3.1 添加GET_DEVICE_ID請(qǐng)求
DEVICE ID是打印機(jī)類特有的類請(qǐng)求,關(guān)系到打印機(jī)驅(qū)動(dòng)的安裝, 官方文檔“usbprint11a021811.pdf”中有對(duì)這個(gè)的詳細(xì)描述。
通過修改“usbd_class_cdc.c” 文件中的 “void USBD_ClassHandler()”函數(shù)來實(shí)現(xiàn)。
void USBD_ClassHandler(USBD_DevReqData_T* reqData)
{
uint16_t length = ((uint16_t)reqData->byte.wLength[1] << 8) |
reqData->byte.wLength[0] ;
switch (reqData->byte.bRequest)
{
case 0x00: //GET_DEVICE_ID
USBD_CtrlInData(PRINTER_DEVICE_ID, sizeof(PRINTER_DEVICE_ID));
break;
case 0x01: //GET_PORT_STATUS
USBD_CtrlOutData(&g_port_status, 1);
break;
case 0x02: //SOFT_RESET
USBD_CtrlInData(cmdBuf, length);
break;
}
}
3.2 抓包觀察請(qǐng)求是否成功
拔插USB,通過軟件“Bus Hound”可以看到USB主機(jī)發(fā)送了 GET_DEVICE_ID 請(qǐng)求,然后USB設(shè)備也返回了對(duì)應(yīng)的字符串。
4、實(shí)現(xiàn)數(shù)據(jù)的接收
4.1 在OUT端點(diǎn)中保存接收到的數(shù)據(jù)包
在USB OUT端點(diǎn)處理函數(shù)進(jìn)行數(shù)據(jù)的接收操作,在文件 “usbd_class_cdc.c”中的 “void USBD_VCP_OutEpCallback()” 函數(shù)中添加代碼。
void USBD_VCP_OutEpCallback(uint8_t ep)
{
uint32_t dataCnt;
if (ep == USBD_EP_1)
{
dataCnt = g_usbDev.outBuf[USBD_EP_1].xferCnt;
PrinterReceiveCount = dataCnt;
memcpy(PrinterReceiveData,dataBuf,dataCnt); //保存接收到的這包數(shù)據(jù)
USBD_RxData(USBD_EP_1, dataBuf, g_usbDev.outBuf[USBD_EP_1].maxPackSize); //如果想接收下一包,須加這個(gè)
//USBD_TxData(USBD_EP_1, dataBuf, dataCnt);
}
}
4.2 測試數(shù)據(jù)接收功能
為了方便查看接收到的數(shù)據(jù),在while(1)中把接收到的數(shù)據(jù)通過串口發(fā)送出去。
int main(void)
{
APM_EVAL_Init();
printf("This is an example of USB Printer ");
while(1)
{
if(PrinterReceiveCount>0)
{
for(unsigned char i=0;i
{
USART_TxData(DEBUG_USART,PrinterReceiveData[i]);
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
}
PrinterReceiveCount=0;
}
}
}
通過USB發(fā)送數(shù)據(jù)需要一個(gè)上位機(jī),這里使用“條碼打印機(jī)調(diào)試助手”,插上USB后,通訊端口選擇USB,然后打開端口,在數(shù)據(jù)發(fā)送框輸入想發(fā)的數(shù)據(jù),然后點(diǎn)右下角“發(fā)送數(shù)據(jù)”,這時(shí)可以在串口調(diào)試助手上看到MCU剛接收的數(shù)據(jù)。
如下圖所示,每次USB接收到的數(shù)據(jù)都通過串口發(fā)送出來了。
注:文章作者在原帖中提供了例程文件,有需要請(qǐng)至原文21ic論壇下載
原文地址:https://bbs.21ic.com/icview-3331288-1-1.html
-
usb
+關(guān)注
關(guān)注
60文章
8158瀏覽量
271688 -
打印機(jī)
+關(guān)注
關(guān)注
10文章
797瀏覽量
46949 -
Printer
+關(guān)注
關(guān)注
0文章
5瀏覽量
7517 -
SDK
+關(guān)注
關(guān)注
3文章
1074瀏覽量
47953 -
虛擬串口
+關(guān)注
關(guān)注
3文章
63瀏覽量
14175
原文標(biāo)題:APM32芯得 EP.55 | 基于APM32E103的USB Printer實(shí)現(xiàn)方案
文章出處:【微信號(hào):geehysemi,微信公眾號(hào):Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
基于極海APM32E103 MCU的CoreMark測試方法

stm32f103&gd32的usb虛擬串口,打印類printer組合設(shè)備

極海半導(dǎo)體APM32E103/F072系列MCU順利通過IEC 60730功能安全認(rèn)證
APM32F103VCT6S_USB_MAC電腦無法識(shí)別USB設(shè)備

APM32E103VET6_SMC_SMC驅(qū)動(dòng)8080并口屏?xí)r屏幕無法點(diǎn)亮

評(píng)論