返回列表 发新帖我要提问本帖赏金: 50.00元(功能说明)

[APM32E1] 基于APM32E103的USB Printer实现

[复制链接]
1516|2
 楼主| shanyuxiang 发表于 2023-10-5 22:12 | 显示全部楼层 |阅读模式
本帖最后由 shanyuxiang 于 2023-10-7 21:34 编辑

#申请原创# @21小跑堂
基于APM32E103的USB Printer实现

目前官方SDK的USB设备例程“APM32E10x_EVAL_SDK_v1.0”只有这几个,分别是:
CDC类 虚拟串口 “USB_CDC_VirtualCOMPort”
HID类  鼠标 “USB_HID_Mouse”
MCS类 大容量存储 “USB_MSC_Disk”
上面是没有Printer类的,如果需要打印机类,可以在CDC例程的基础上进行修改,只需要几步就可以实现一个USB的打印机设备。

1、USB打印机类的基础知识
1.1、USB的设备类
常见的USB设备类有以下几种,这里要实现就是07h号打印机类。
1.png

1.2、调试USB的工具软件
USB数据抓包软件 “Bus Hound”
枚举信息查看软件 “USBlyzer”

1.3、推荐几个关于USB的基础知识的网站
https://www.usbzh.com/article/detail-344.html
http://usb.baiheee.com/

1.4、 USB标准组织官网USB-IF上的资料
关于USB 2.0资料:
https://www.usb.org/document-library/usb-20-specification

关于 Printer Device Class 的文档:
https://www.usb.org/document-library/printer-device-class-document-11

2、修改描述符
首先要通过修改描述符,来枚举出“打印支持”设备。
在极海官网下载USB的SDK
https://www.geehy.com/support/apm32?id=305
APM32E10x_EVAL_SDK_v1.0.zip
注释掉不用的代码,例如LCD、KEY、LED,这些跟USB无关。

2.1 描述符的基础知识
描述符分为:
设备描述符 Device Descriptor           (g_usbDeviceDescriptor)
配置描述符 Configuration Descriptor (g_usbConfigDescriptor)
端点描述符 Endpoint Descriptor       (g_usbConfigDescriptor)

详细信息可以看这里:
http://usb.baiheee.com/usb_article/usb_spec/usb_cmd_desc.html

2.2 修改设备描述符
打开源文件 ..\..\Source\usbd_descriptor.c ,修改数组 g_usbDeviceDescriptor[] ,
这里只要把设备类从CDC 0x02 改为Printer 0x07。
  1. /** bDeviceClass */
  2.     0x07, //0x02,
2.3 修改配置描述符和端点描述符
配置描述符和端点描述符都在数组 g_usbConfigDescriptor[] 中,我们只需要1个配置,该配置下有2个端点,删除多余的端点,修改成下面这样。
  1. const uint8_t g_usbConfigDescriptor[USB_CONFIG_DESCRIPTOR_SIZE] =
  2. {
  3.     /** bLength */
  4.     0x09,
  5.     /** bDescriptorType */
  6.     USBD_DESC_CONFIGURATION,
  7.     /** wTotalLength */
  8.     USB_CONFIG_DESCRIPTOR_SIZE & 0xFF, USB_CONFIG_DESCRIPTOR_SIZE >> 8,

  9.     /** bNumInterfaces */
  10.     0x01,//0x02,
  11.     /** bConfigurationValue */
  12.     0x01,
  13.     /** iConfiguration */
  14.     0x00,
  15.     /** bmAttributes */
  16.     0xC0,
  17.     /** MaxPower */
  18.     0x32,

  19.     /** bLength */
  20.     0x09,
  21.     /** bDescriptorType */
  22.     USBD_DESC_INTERFACE,
  23.     /** bInterfaceNumber */
  24.     0x00, //0x01,
  25.     /** bAlternateSetting */
  26.     0x00,
  27.     /** bNumEndpoints */
  28.     0x02, //0x01,
  29.     /** bInterfaceClass */
  30.     0x07,//0x02,
  31.     /** bInterfaceSubClass */
  32.     0x01, //0x02,
  33.     /** bInterfaceProtocol */
  34.     0x01, //0x01,
  35.     /** iInterface */
  36.     0x00,

  37.     0x07,     /** bLength: Endpoint Descriptor size */
  38.     USBD_DESC_ENDPOINT,  /** bDescriptorType: Endpoint */
  39.     0x01, /** bEndpointAddress */
  40.     0x02, /** bmAttributes: Bulk */   
  41.     0x40,0x00, /** wMaxPacketSize: */
  42.     0x00, /** bInterval: */
  43.                
  44.     0x07,     /** bLength: Endpoint Descriptor size */
  45.     USBD_DESC_ENDPOINT,  /** bDescriptorType: Endpoint */
  46.     0x81, /** bEndpointAddress */
  47.     0x02, /** bmAttributes: Bulk */   
  48.     0x40,0x00, /** wMaxPacketSize: */
  49.     0x00 /** bInterval: */
  50. };
2.4 测试是否枚举成功
修改完描述符后,运行程序,拔插USB,设备管理器中会出现“打印支持”,使用“USBlyzer”可以看到详细的枚举信息。 2-2.png
3 实现类特殊请求
3.1 添加GET_DEVICE_ID请求
DEVICE ID是打印机类特有的类请求,关系到打印机驱动的安装, 官方文档“usbprint11a021811.pdf”中有对这个的详细描
4.png



通过修改“usbd_class_cdc.c” 文件中的 “void USBD_ClassHandler()”函数来实现。
  1. void USBD_ClassHandler(USBD_DevReqData_T* reqData)
  2. {
  3.     uint16_t length = ((uint16_t)reqData->byte.wLength[1] << 8) | \
  4.                      reqData->byte.wLength[0] ;

  5.                  switch (reqData->byte.bRequest)
  6.                  {
  7.                                case 0x00:  //GET_DEVICE_ID
  8.                                 USBD_CtrlInData(PRINTER_DEVICE_ID, sizeof(PRINTER_DEVICE_ID));   
  9.                                 break;
  10.                                 
  11.                                 case 0x01:  //GET_PORT_STATUS
  12.                                 USBD_CtrlOutData(&g_port_status, 1);  
  13.                                 break;
  14.                                 
  15.                                 case 0x02:  //SOFT_RESET
  16.                                 USBD_CtrlInData(cmdBuf, length);   
  17.                                 break;
  18.                  
  19.          }
  20. }
3.2 抓包观察请求是否成功

拔插USB,通过软件“Bus Hound”可以看到USB主机发送了 GET_DEVICE_ID 请求,然后USB设备也返回了对应的字符串。
3-2.png
4、实现数据的接收
4.1 在OUT端点中保存接收到的数据包
在USB OUT端点处理函数进行数据的接收操作,在文件 “usbd_class_cdc.c”中的 “void USBD_VCP_OutEpCallback()” 函数中添加代码。
  1. void USBD_VCP_OutEpCallback(uint8_t ep)
  2. {
  3.     uint32_t dataCnt;

  4.     if (ep == USBD_EP_1)
  5.     {
  6.                          dataCnt = g_usbDev.outBuf[USBD_EP_1].xferCnt;

  7.                           PrinterReceiveCount = dataCnt;
  8.                           memcpy(PrinterReceiveData,dataBuf,dataCnt);  //保存接收到的这包数据
  9.                         
  10.                           USBD_RxData(USBD_EP_1, dataBuf, g_usbDev.outBuf[USBD_EP_1].maxPackSize);         //如果想接收下一包,须加这个        
  11.                           //USBD_TxData(USBD_EP_1, dataBuf, dataCnt);
  12.     }
  13. }

4.2 测试数据接收功能
为了方便查看接收到的数据,在while(1)中把接收到的数据通过串口发送出去。
  1. int main(void)
  2. {
  3.     APM_EVAL_Init();
  4.     printf("This is an example of USB Printer \r\n");
  5.         
  6.     while(1)
  7.     {
  8.            if(PrinterReceiveCount>0)
  9.             {  
  10.                 for(unsigned char i=0;i<PrinterReceiveCount;i++)
  11.                {                                
  12.                           USART_TxData(DEBUG_USART,PrinterReceiveData[i]);
  13.                           while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
  14.                }
  15.                PrinterReceiveCount=0;
  16.           }
  17.                         
  18.     }
  19. }
通过USB发送数据需要一个上位机,这里使用“条码打印机调试助手”,插上USB后,通讯端口选择USB,然后打开端口,
在数据发送框输入想发的数据,然后点右下角“发送数据”,这时可以在串口调试助手上看到MCU刚接收的数据。
如下图所示,每次USB接收到的数据都通过串口发送出来了。
5.png

APM32E10x_EVAL_SDK_v1.0 USB Printer.rar

349.29 KB, 阅读权限: 10, 下载次数: 26

USB Printer例程

打赏榜单

21小跑堂 打赏了 50.00 元 2023-10-11
理由:恭喜通过原创审核!期待您更多的原创作品~

评论

基于APM32E103的USB通信实验,整体完成度较好,适用性较强。  发表于 2023-10-11 15:19
hjl2832 发表于 2023-10-8 08:28 | 显示全部楼层
这个不错,学习了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

50

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部