东莞市朋电数控 发表于 2025-5-7 10:57:57

RMB0.95, 8H2K12U做USB转串口,如何兼容CH340的通信协议 | 已成功

RMB0.95, 8H2K12U-SOP8/SOP16/TSSOP20/QFN20, USB型MCU单片机
使用STC通用USB型MCU做USB转串口,如何兼容CH340的通信协议:
这几天没事干,就用 8H2K12U / 8H8K64U 单片机里面的USB做USB-CDC转串口,
改了一个来兼容CH340通信协议的USB转串口:
现在的问题是有些电脑能识别并安装CH340驱动,并正常使用。
有些电脑设备管理器显示CH340串口感叹号,有的电脑读不到VID PID……郁闷中,
不知道哪里出来问题,把程序发上来,大家帮忙看看

char code DEVICEDESC =
{
    0x12,                           /* bLength */
    0x01,                                                                                                      /* bDescriptorType */
    0x10,0x01,                        /* bcdUSB = 1.10 */
    0xff,                           /* bDeviceClass: CDC */
    0x00,                           /* bDeviceSubClass */
    0x00,                           /* bDeviceProtocol */
    0x40,                           /* bMaxPacketSize0 */
    0x86,0x1a,                        /* idVendor = 0x1A86 */
    0x23,0x75,                        /* idProduct = 0x7523 */
    0x64,0x02,                        /* bcdDevice = 2.00 */
    0x01,                           /* 制造商描述符的索引 */
    0x02,                           /* 产品描述符的索引 */
    0x03,                           /* 设备序列号的描述符的索引 */
    0x01                              /* 配置描述符的数量 */

};


char code CONFIGDESC =
{


    /* 配置描述符 */
    0x09,                           /* bLength: 配置描述符的长度 */
    0X02,                                                                                                               /* bDescriptorType: Configuration */
    0x27,                                                                                                                  /* wTotalLength: 所有返回的字节数 */
    0x00,
    0x01,                           /* bNumInterfaces: 接口的数量 */
    0x01,                           /* bConfigurationValue: 配置值 */
    0x00,                           /* iConfiguration: 描述该配置的字符串描述符的索引 */
    0x80,                           /* bmAttributes: 自供电 */
    0x30,                           /* MaxPower: 0 mA */

    /* 接口描述符 */
    0x09,                           /* bLength: 接口描述符的长度 */
    0x04,                                                                                                         /* bDescriptorType: Interface */
    /* 接口描述符类型 */
    0x00,                           /* bInterfaceNumber: 接口的编号 */
    0x00,                           /* bAlternateSetting: 替代设置 */
    0x03,                           /* bNumEndpoints: 使用的端点数 */
    0xff,                           /* bInterfaceClass: 通信接口类 */
    0x01,                           /* bInterfaceSubClass: 抽象控制模型 */
    0x02,                           /* bInterfaceProtocol: 通用 AT 命令 */
    0x00,                           /* iInterface: 描述该接口的字符串描述符的索引 */

    /* 端点2输入描述符 */
    0x07,                           /* bLength: 端点描述符的长度 */
    0X05,                                                                                                   /* bDescriptorType: Endpoint */
    0x82,                           /* bEndpointAddress: (IN2) */
    0x02,                           /* bmAttributes: 传输类型为批量传输 */
    0x40,                           /* wMaxPacketSize: 最大数据包大小 */
    0x00,
    0x00,                           /* bInterval: 传输间隔 */

    /* 端点2输出描述符 */
    0x07,                           /* bLength: 端点描述符的长度 */
    0X05,                                                                                                   /* bDescriptorType: Endpoint */
    0x02,                           /* bEndpointAddress: (OUT2) */
    0x02,                           /* bmAttributes: 传输类型为批量传输 */
    0x40,                           /* wMaxPacketSize: 最大数据包大小 */
    0x00,
    0x00,                           /* bInterval: 传输间隔 */
               
               
         /* 端点1输入描述符 */
    0x07,                           /* bLength: 端点描述符的长度 */
    0X05,                                                                                                   /* bDescriptorType: Endpoint */
    0x81,                           /* bEndpointAddress: (IN1) */
    0x03,                           /* bmAttributes: 传输类型为中断传输 */
    0x08,                           /* wMaxPacketSize: 最大数据包大小 */
    0x00,
    0x01,                              /* bInterval: 传输间隔 */      
               
};

char code LANGIDDESC =
{
    0x04,0x03,
    0x09,0x04,
};

char code MANUFACTDESC =
{
          0x0B,0x03,
    'w',0,
    'c',0,
    'h',0,
    '.',0,
    'c',0,
    'n',0,
      
};

char code PRODUCTDESC =
{

   0x18,0x03,
    'U',0,
    'S',0,
    'B',0,
    ' ',0,
    'S',0,
    'e',0,
    'r',0,
    'i',0,
    'a',0,
    'l',0,
      
};

char code PACKET0 =
{
    0, 0,
};

char code PACKET1 =
{
    1, 0,
};





case VENDOR_REQUEST://处理来自厂商的请求
                   usb_req_vendor();
                                                       //***********************************************************************
                                                                         // 这部分是厂商信息
                                                                         //***********************************************************************
               
                                                                              switch(Setup.bRequest)
                                                                              {
                                                                                        case   0x5F:
                                                                                                      Ep0State.pData = buf1;
                                                                                                      Ep0State.wSize = sizeof(buf1);
                                                                                                      break;
                                                                                        case0x95:
                                                                                                      if((Setup.wValueH==0x25)&&(Setup.wValueL==0x18))    // wValue == 0x2518)
                                                                                                      {
                                                                                                                Ep0State.pData = buf2;
                                                                                                                Ep0State.wSize = sizeof(buf2);
                                                                                                
                                                                                                      }
                                                                                                      else if((Setup.wValueH==0x07)&&(Setup.wValueL==0x06)) ///wValue == 0x0706
                                                                                                      {
                                                                                                               Ep0State.pData = buf0;
                                                                                                               Ep0State.wSize = sizeof(buf0);
                                                                                                      }
                                                                                                      break;
                                                                                        case0xA4:
                                                                                                      {
                                                                                                                Ep0State.pData = buf0;
                                                                                                                Ep0State.wSize = sizeof(buf0);
                                                                                                      }
                                                                                                      break;
                                                                                        default:
                                                                                                      Ep0State.pData = zero;
                                                                                                      Ep0State.wSize = sizeof(zero);
                                                                                                      break;
                                                                              }

                                                                              
                //***********************************************************************

                break;



有爱心的大神,有空帮忙看看,下面是程序附件




ercircle 发表于 2025-5-9 08:47:02

根据楼上网友的开源USB转串口程序,
使用STC通用USB型MCU做USB转串口,
兼容CH340的通信协议,已测试成功,
支持DTR\RTS控制,支持常用波特率及校验位设置:
RMB0.95, 8H2K12U,
8H8K64U / 32G12K128 / Ai8051U 通用USB型MCU,
USB转串口,兼容CH340的驱动协议,已测试 成功,有一定的参考价值 :
楼上网友的开源程序问题是 vendor的setup_out 请求处理不对,
基本都用setup_status回应,使用setup_out会阻塞。




可通过P16/P17与外部串口通讯, 可自己修改成其他I/O:


一箭双雕下载器兼容CH340源码及固件:

如有自制下载器需求可用上面源码,此固件与源码对应:
旧系统CDC驱动安装失败的情况建议使用此固件,注意频率一定要选24M:



win10以上免驱动,建议使用CDC,可直接使用ISP软件更新下载器固件。


驱动:





注意事项:
1.基于最新的3.9驱动版本+win10测试,WIN7下旧版驱动测试正常,新驱动数字签名不识别需要安装特定系统补丁。
2.CDC版本,下载完成后,P15(DTR1)为高电平,P13(RTS1)为低电平
兼容CH340版本,下载完成后,P15(DTR1)&P13(RTS1)都为高电平。
是关闭串口动作,驱动控制策略不同导致。
3.兼容CH340版本,只能用串口1。
4.一箭双雕开发板可用P13(RTS1),开天斧,屠龙刀P13连的测温电阻,建议改P14

更新记录:
20250510:
1.兼容一箭双雕下载器代码
2.兼容波特率(抽测常用波特率9600,115200,460800正常)、校验方式、DTR\RTS控制协议。















vb2002 发表于 2025-5-7 11:36:48

还是用官方的一箭双雕或者置顶那个下载器好点
RMB0.95, 8H2K12U;
8H8K64U / 32G12K128 / Ai8051U 通用USB型MCU

AI-32位8051 发表于 2025-5-7 14:41:31






【USB转双串口】量产PCB/SCH开源, 芯片出厂自带USB程序
Ai8H2K12U-45MHz-SOP8,USB 转 单串口,RMB 0.95,【免费+包邮 送】
Ai8H2K12U-45MHz-SOP16,USB 转 双串口,RMB 1.1,省1个USB口
USB插头支持:USB-TypeA,USB-TypeC
支持任意波特率,最高到 10Mbps,程序早已稳定,免驱动安装
全自动停电/上电,ISP下载编程烧录器
有手动电源开/关按键,可做电源供电模块
立创开源 SCH / PCB,可以自己去立创免费打样,V1.2-20241023:
https://www.stcaimcu.com/data/attachment/forum/202410/23/102736nv42d3qkqv2yzqy9.png


【新提醒】USB转双串口,RMB1.1, 量产PCB/SCH开源,芯片出厂自带USB程序@Ai8H2K12U-45MHz-SOP16 - USB:USB-CDC虚拟串口/就是串口,一箭双雕之USB转双串口,[鼠标+键盘]的HID复合设备 国芯技术交流网站 - AI32位8051交流社区https://www.stcaimcu.com/forum.php?mod=viewthread&tid=11288&highlight=%E5%87%BA%E5%8E%82%E8%87%AA%E5%B8%A6USB&page=1&extra=#pid113523

soma 发表于 2025-5-7 16:51:04

vb2002 发表于 2025-5-7 11:36
还是用官方的一箭双雕或者置顶那个下载器好点

说的是用STC模拟CH340,也就是芯片是STC的显示出来是CH340,和下载器无关吧

东莞市朋电数控 发表于 2025-5-7 17:53:57

soma 发表于 2025-5-7 16:51
说的是用STC模拟CH340,也就是芯片是STC的显示出来是CH340,和下载器无关吧
是的,和下载器无关,单片机的CDC串口只能用CDC的驱动。
做成CH340的串口,用的是CH340的驱动,
很多电脑并不支持或者没有良好的支持CDC驱动

vb2002 发表于 2025-5-7 19:40:52

soma 发表于 2025-5-7 16:51
说的是用STC模拟CH340,也就是芯片是STC的显示出来是CH340,和下载器无关吧

意思是把stc的单片机当ch340用?还能给stm下载那种m

晓飛飛 发表于 2025-5-7 23:30:40

模拟CH340并非把设备描述和PID VID改成CH340一致的那么简单,
CH340官方驱动里面有关于一些特殊寄存器级的操作,这个也需要做相应的模拟。

qq603599910 发表于 2025-5-8 08:09:30

现在大家有用过CDC在Linux或者Ubuntu系统通讯吗?CH340是识别为TTYUSB.

xxkj2010 发表于 2025-5-8 08:32:11

好像在网上曾看到大佬用CH552模拟CH340的,毕竟人家是同一厂家的,用STC单片机来模拟CH340,估计很难完美模拟

神农鼎 发表于 2025-5-8 09:29:29

只是兼容部分电脑端的驱动通信协议,
难度就是个比较简单的本科课程设计

只是 UART通信协议 变成了 USB通信协议
页: [1] 2 3
查看完整版本: RMB0.95, 8H2K12U做USB转串口,如何兼容CH340的通信协议 | 已成功