请教:stm32 usb如何配置成usb printer类(打印机类)(从模式)

2019-12-20 21:35发布

我是做热敏打印机的,用stm32的usb与电脑通信,需将usb配置成打印机类协议,我从st的官方例程虚拟串口修改了一份,在window下可以枚举(生成usb端口如:usb001),可以正常通信,但是在有些linux下却不行。
另外就是我现在做的只能单向通信,也就是能接收电脑端的数据,不能向电脑端发送数据。
哪位兄弟有做过类似相关的项目帮我一下啊
下面是修改的配置描述符:
const uint8_t Virtual_Com_Port_ConfigDescriptor[] =
  {
    /*Configuration Descriptor*/
    0x09,   /* bLength: Configuration Descriptor size */
    USB_CONFIGURATION_DESCRIPTOR_TYPE,      /* bDescriptorType: Configuration */
    VIRTUAL_COM_PORT_SIZ_CONFIG_DESC,       /* wTotalLength:no of returned bytes */
    0x00,
    0x01,//0x02,   /* bNumInterfaces: 2 interface */
    0x01,   /* bConfigurationValue: Configuration value */
    0x05,   /* iConfiguration: Index of string descriptor describing the configuration */
    0xC0,   /* bmAttributes: self powered */
    0x32,   /* MaxPower 0 mA */
    /*Interface Descriptor*/
    0x09,   /* bLength: Interface Descriptor size */
    USB_INTERFACE_DESCRIPTOR_TYPE,  /* bDescriptorType: Interface */
    /* Interface descriptor type */
    0x00,   /* bInterfaceNumber: Number of Interface */
    0x00,   /* bAlternateSetting: Alternate setting */
    0x02,//0x01,   /* bNumEndpoints: One endpoints used */
    0x07,   /* bInterfaceClass: Communication Interface Class */
    0x01,   /* bInterfaceSubClass: Abstract Control Model */
    0x02,   /* bInterfaceProtocol: Common AT commands */
    0x04,   /* iInterface: */

    /*Endpoint 3 Descriptor*/
    0x07,   /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
    0x81,   /* bEndpointAddress: (OUT3) */
    0x02,   /* bmAttributes: Bulk */
    VIRTUAL_COM_PORT_DATA_SIZE,             /* wMaxPacketSize: */
    0x00,
    0x00,   /* bInterval: ignore for Bulk transfer */
    /*Endpoint 1 Descriptor*/
    0x07,   /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */
    0x03,   /* bEndpointAddress: (IN1) */
    0x02,   /* bmAttributes: Bulk */
    VIRTUAL_COM_PORT_DATA_SIZE,             /* wMaxPacketSize: */
    0x00,
    0x00    /* bInterval */
  };
usb初始化:
void USB_Init(void)
{
  pInformation = &Device_Info;
  pInformation->ControlState = 2;
  pProperty = &Device_Property;
  pUser_Standard_Requests = &User_Standard_Requests;
  /* Initialize devices one by one */
  pProperty->Init();
}
void Virtual_Com_Port_Reset(void)
{
   /* Set Virtual_Com_Port DEVICE as not configured */
  pInformation->Current_Configuration = 0;

  /* Current Feature initialization */
  pInformation->Current_Feature = Virtual_Com_Port_ConfigDescriptor[7];

  /* Set Virtual_Com_Port DEVICE with the default Interface*/
  pInformation->Current_Interface = 0;

  SetBTABLE(BTABLE_ADDRESS);

  /* Initialize Endpoint 0 */
  SetEPType(ENDP0, EP_CONTROL);
  SetEPTxStatus(ENDP0, EP_TX_STALL);
  SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  Clear_Status_Out(ENDP0);
  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPRxValid(ENDP0);

  /* Initialize Endpoint 1 */
  SetEPType(ENDP1, EP_BULK);
  SetEPTxAddr(ENDP1, ENDP1_TXADDR);
  SetEPTxStatus(ENDP1, EP_TX_NAK);
  SetEPRxStatus(ENDP1, EP_RX_DIS);

  /* Initialize Endpoint 3 */
  SetEPType(ENDP3, EP_BULK);
  SetEPRxAddr(ENDP3, ENDP3_RXADDR);
  SetEPRxCount(ENDP3, VIRTUAL_COM_PORT_DATA_SIZE);
  //SetEPDoubleBuff(ENDP3);
  //SetEPDblBuffAddr(ENDP3,ENDP3_BUF0Addr,ENDP3_BUF1Addr);
  //SetEPDblBuffCount(ENDP3, VIRTUAL_COM_PORT_DATA_SIZE);
  SetEPRxStatus(ENDP3, EP_RX_VALID);
  SetEPTxStatus(ENDP3, EP_TX_DIS);

  /* Set this device to response on default address */
  SetDeviceAddress(0);

  bDeviceState = ATTACHED;
}
发送函数:
void USB_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes)
{

   UserToPMABufferCopy(data_buffer, ENDP1_TXADDR, Nb_bytes);
    SetEPTxCount(ENDP1, Nb_bytes);
    SetEPTxValid(ENDP1);

}
接收是中断接收的这里和虚拟串口的一模一样。

不知道为什么 不能发送 只能接收
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
31条回答
20062516
1楼-- · 2019-12-23 07:14
caixiuwen 发表于 2014-9-18 14:41
没有什么特别的设置,和虚拟串口一样的。不知道你模拟的是什么打印机。
我抓了一下真的ip3680发的状态数 ...

不是模拟的打印机,是真打印机,热敏打印机,我是做热敏打印机研发的,之前usb这块一直用虚拟串口,现在想改成usb printer类,能在的问题就是打印机能接收电脑发来的数据,但是不能向电脑端发送数据
caixiuwen
2楼-- · 2019-12-23 12:23
20062516 发表于 2014-9-18 14:48
不是模拟的打印机,是真打印机,热敏打印机,我是做热敏打印机研发的,之前usb这块一直用虚拟串口,现在 ...

Get Device ID返回的是什么?电脑上能打印了?
20062516
3楼-- · 2019-12-23 16:08
是啊,可以打印的(打印机可以接收到电脑端发来的数据),但是还有一些打印机的状态(无纸错误,过温错误等)需要发送给电脑端,我用bushound监控,能监控到电脑下发的数据,不能监控到打印机上发的数据。Get Device ID没用这个功能,因为电脑接上打印机,电脑端就会多出一个usb001的端口,我就朝这个端口发数据就行了
caixiuwen
4楼-- · 2019-12-23 18:45
20062516 发表于 2014-9-18 15:39
是啊,可以打印的(打印机可以接收到电脑端发来的数据),但是还有一些打印机的状态(无纸错误,过温错误等 ...

我又改了一下虚拟串口的代码

  1. /**
  2.   * @brief  VCP_Ctrl
  3.   *         Manage the CDC class requests
  4.   * @param  Cmd: Command code            
  5.   * @param  Buf: Buffer containing command data (request parameters)
  6.   * @param  Len: Number of data to be sent (in bytes)
  7.   * @retval Result of the opeartion (USBD_OK in all cases)
  8.   */
  9. static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
  10. {
  11.   switch (Cmd)
  12.   {
  13.   case SEND_ENCAPSULATED_COMMAND:
  14.       memcpy(Buf, printer_device_id, sizeof(printer_device_id));

  15.     /* Not  needed for this driver */
  16.     break;

  17.   case GET_ENCAPSULATED_RESPONSE:
  18.       Buf[0] = 0x30;
  19.     /* Not  needed for this driver */
  20.     break;
复制代码

这里case GET_ENCAPSULATED_RESPONSE其实是Get Port Status,简单测试,懒得改了。。。
0x30 表示出错,缺纸。

OUT 端点都NAK掉,等一会,Windows就来查询状态了,返回0x30,告诉它缺纸。再看打印状态:

getportstatus.png (134.06 KB, 下载次数: 0)

下载附件

2014-9-18 16:42 上传

caixiuwen
5楼-- · 2019-12-23 21:38
 精彩回答 2  元偷偷看……
shen_lan
6楼-- · 2019-12-23 21:44
caixiuwen 发表于 2014-9-18 17:04
不知道你是怎么朝这个端口发送数据的。
有的驱动只要能发数据,就不会查询状态,一直到打印完,都不查询 ...

老哥 可以把你的这个可以识别出打印设备的例程发我一下么~~小白感激不尽~~~

一周热门 更多>