找回密码
 立即注册
楼主: ercircle

USB拓展库及使用示例 | 本贴 咨询 USB,基本帮您把USB程序开发完成

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:254
  • 最近打卡:2025-08-01 08:52:46
已绑定手机

78

主题

2779

回帖

5722

积分

荣誉版主

无情的代码机器

积分
5722
发表于 2025-6-13 13:45:25 | 显示全部楼层
神*** 发表于 2025-6-13 13:34
调用USB库函数与上位机之间传数据的时候,一次传输的长度最多多少?
===HID协议一包64字节,
       CDC协 ...

CDC和HID使用USB_SendData是自动分包发送,使用库单包大小一般是64,自定义代码视wMaxPacketSize而定。

但是,使用printf_usb,程序内部是用UsbInBuffer作缓冲区,一般是64字节大小,不够支持1k格式化字符串。
自建一个足够大缓冲区,使用sprintf格式化字符串后,调用USB_SendData发送

三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2025-08-01 08:49:59

5

主题

68

回帖

205

积分

中级会员

积分
205
发表于 2025-6-19 08:34:03 | 显示全部楼层
厉害,愿此贴能多保留一段时间,过段时间开始做HID键鼠
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:511
  • 最近打卡:2025-08-01 00:02:36

4

主题

33

回帖

1607

积分

金牌会员

积分
1607
发表于 2025-7-6 11:48:00 | 显示全部楼层
老师,您的键盘鼠标+cdc的例子,cdc收发测试是短接rxtx,我看USB_SendData是在端点1的hid里面的,能不能加的那个cdc也可以使用USB_SendData,直接在usb_out_ep5中写in的fifo可以吗

点评

可以的,Usb sendData也是调用fifo写函数。  详情 回复 发表于 2025-7-6 12:24
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:254
  • 最近打卡:2025-08-01 08:52:46
已绑定手机

78

主题

2779

回帖

5722

积分

荣誉版主

无情的代码机器

积分
5722
发表于 2025-7-6 12:24:07 来自手机 | 显示全部楼层
苏紫方璇 发表于 2025-7-6 11:48
老师,您的键盘鼠标+cdc的例子,cdc收发测试是短接rxtx,我看USB_SendData是在端点1的hid里面的,能不能加 ...

可以的,Usb sendData也是调用fifo写函数。
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:511
  • 最近打卡:2025-08-01 00:02:36

4

主题

33

回帖

1607

积分

金牌会员

积分
1607
发表于 2025-7-6 13:46:41 | 显示全部楼层
我试着修改了一下,有点问题
1,不停电下载字符串可以正确响应,但是无法重启到usb_Writer那里
2,接收重发那里,单个包在120以内比较稳定,120-127有时会接收不到,超过端点5最大IN的长度,分包发送时,接收不到任何信息。而且使用wireshark抓包会一直刷IN的信息
附上代码,main那里在1ms的定时器里加了个msTick++,注释了uart中动态调节主频的,其他修改均在下面代码中明显标注了
  1. #include "ai8051u.h"
  2. #include "ai_usb_ex.h"
  3. #include "string.h"
  4. #include "uart.h"
  5. #include "CDC_ex_desc.h"
  6. LINECODING LineCoding1;
  7. LINECODING LineCoding2;
  8. BYTE Interface;
  9. BOOL Ep4InBusy;
  10. BOOL Ep5InBusy;
  11. BOOL Ep4OutBusy;
  12. BOOL Ep5OutBusy;
  13. BYTE xdata UsbBuffer[256];
  14. void uart_settings(BYTE index)
  15. {
  16.                 Interface = index;
  17.     if (Interface == CDC1_FIRST_INTERFACE)
  18.     {
  19.         LineCoding1.bCharFormat = 0;
  20.         LineCoding1.bDataBits = 8;
  21.     }
  22.                 else if (Interface == CDC2_FIRST_INTERFACE)
  23.     {
  24.         LineCoding2.bCharFormat = 0;
  25.         LineCoding2.bDataBits = 8;
  26.     }
  27.     uart_set_parity();
  28.     uart_set_baud();
  29. }
  30. void usb_in_ep4()
  31. {
  32.     BYTE csr;
  33.     usb_write_reg(INDEX, 4);
  34.     csr = usb_read_reg(INCSR1);
  35.     if (csr & INSTSTL)
  36.     {
  37.         usb_write_reg(INCSR1, INCLRDT);
  38.     }
  39.     if (csr & INUNDRUN)
  40.     {
  41.         usb_write_reg(INCSR1, 0);
  42.     }
  43. }
  44. void usb_in_ep5()
  45. {
  46.     BYTE csr;
  47.     usb_write_reg(INDEX, 5);
  48.     csr = usb_read_reg(INCSR1);
  49.     if (csr & INSTSTL)
  50.     {
  51.         usb_write_reg(INCSR1, INCLRDT);
  52.     }
  53.     if (csr & INUNDRUN)
  54.     {
  55.         usb_write_reg(INCSR1, 0);
  56.     }
  57.     Ep5InBusy = 0;
  58. }
  59. ////////////////////////////////////////////////////////////////////////
  60. //补两个函数
  61. void usb_write_fifo(BYTE fifo, BYTE *pdat, BYTE cnt)
  62. {
  63.         while (cnt--)
  64.         {
  65.         usb_write_reg(fifo, *pdat++);
  66.     }
  67. }
  68. void _usb_bulk_intr_in(BYTE *pData, BYTE bSize, BYTE ep)
  69. {
  70.     usb_write_fifo((BYTE)(FIFO0 + ep), pData, bSize);
  71.     usb_write_reg(INCSR1, INIPRDY);
  72. }
  73. ////////////////////////////////////////////////////////////////////////
  74. void usb_out_ep5()
  75. {
  76.     BYTE csr;
  77.     BYTE cnt,addr,i=0;
  78.     usb_write_reg(INDEX, 5);
  79.     csr = usb_read_reg(OUTCSR1);
  80.     if (csr & OUTSTSTL)
  81.     {
  82.         usb_write_reg(OUTCSR1, OUTCLRDT);
  83.     }
  84.     if (csr & OUTOPRDY)
  85.     {
  86.         cnt = usb_read_reg(OUTCOUNT1);
  87.         while (cnt--)
  88.         {
  89.                         UsbBuffer[i] = usb_read_reg(FIFO5);
  90.             Uart2RxBuffer[Uart2RxWptr++] = UsbBuffer[i];
  91.                         i++;
  92.         }
  93.                 /////////////////////////////////////////////////////////
  94.                 //判断命令  @STCISP#
  95.                 if(i==8)
  96.                 {
  97.                         UsbBuffer[i]=0;
  98.                         if(strcmp(UsbBuffer,"@STCISP#")==0)
  99.                         {
  100.                                 EUSB = 0;
  101.                                 USBCON = 0x00;
  102.                 USBCLK = 0x00;
  103.                 IRC48MCR = 0x00;
  104.                 msTick=0;//main中1ms定时器计数
  105.                                 while(msTick<20);
  106.                     
  107.                                 IAP_CONTR = 0x60;
  108.                                 while(1);
  109.                         }
  110.                 }
  111.                 //回发数据
  112.                 EUSB=0;
  113.                 usb_write_reg(INDEX, 5);
  114.                 addr=0;
  115.                 do
  116.                 {
  117.                         cnt=(i > EP5IN_SIZE) ? EP5IN_SIZE : i;
  118.                         while (usb_read_reg(INCSR1) & INIPRDY);
  119.                         _usb_bulk_intr_in(&UsbBuffer[addr], cnt, 5);
  120.                         addr += cnt;
  121.                         i -= cnt;
  122.                 }while(cnt>=EP5IN_SIZE);
  123.                 EUSB=1;
  124.                 /////////////////////////////////////////////////////////               
  125.                
  126.                
  127.                
  128.                
  129.         if ((BYTE)(Uart2RxWptr - Uart2RxRptr) >= (BYTE)(256 - EP5OUT_SIZE))
  130.         {
  131.             Ep5OutBusy = 1;
  132.         }
  133.         else
  134.         {
  135.             usb_write_reg(OUTCSR1, 0);
  136.         }
  137.     }
  138. }
  139. void initCDCEx(){
  140.                 //修改PID
  141.                 DEVICEDESC[10] = 0x0a;
  142.                 DEVICEDESC[11] = 0xFF;
  143.                 set_usb_uart_settings_callback(uart_settings);
  144.                
  145.                 //添加CDC,使用EP4 EP5
  146.                 usb_add_interface(CDC2_FIRST_INTERFACE,CONFIGDESC_CDC2_HEAD,sizeof(CONFIGDESC_CDC2_HEAD),&LineCoding2);
  147.                 usb_add_interface(CDC2_FIRST_INTERFACE+1,CONFIGDESC_CDC2_BODY,sizeof(CONFIGDESC_CDC2_BODY),NULL);
  148.                 set_usb_ep_callback(4,64,usb_in_ep4,0,0);
  149.                 set_usb_ep_callback(5,128,usb_in_ep5,248,usb_out_ep5);
  150. }
复制代码


点评

参考这个,有几个注意点: 1.复位前用的软延时 2.CDC分包64字节发送,并且Rx数为64字节倍数时要发一包空包 3.CDC Bulk端点,协议里wMaxPacketSize要声明64字节,这里之前写错了。 原因参考这个:https://www.stcai  详情 回复 发表于 2025-7-6 14:56
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:254
  • 最近打卡:2025-08-01 08:52:46
已绑定手机

78

主题

2779

回帖

5722

积分

荣誉版主

无情的代码机器

积分
5722
发表于 2025-7-6 14:56:53 | 显示全部楼层
苏紫*** 发表于 2025-7-6 13:46
我试着修改了一下,有点问题
1,不停电下载字符串可以正确响应,但是无法重启到usb_Writer那里
2,接收重发 ...


3.3.HID键盘鼠标扩展 CDC - 副本.zip (203.49 KB, 下载次数: 6)
参考这个,有几个注意点:
1.复位前用的软延时
2.CDC分包64字节发送,并且Rx数为64字节倍数时要发一包空包
3.CDC Bulk端点,协议里wMaxPacketSize要声明64字节,这里之前写错了。
原因参考这个:https://www.stcaimcu.com/forum.p ... 6680&pid=166931


1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:511
  • 最近打卡:2025-08-01 00:02:36

4

主题

33

回帖

1607

积分

金牌会员

积分
1607
发表于 2025-7-6 23:08:51 | 显示全部楼层
erci*** 发表于 2025-7-6 14:56
参考这个,有几个注意点:
1.复位前用的软延时
2.CDC分包64字节发送,并且Rx数为64字节倍数时要发一包 ...

感谢老师,64字节分包可以正常收发了,不停电下载也正常了。另外想问一下,复位前用软延时有什么特殊说法么

点评

将自定义CDC接口的发送功能和printf绑定功能封装到了库里,可以有空试下新版本。  详情 回复 发表于 2025-7-9 11:37
因为这个代码段很多官方例程里都用到了,就直接CV了。 定时器的我没试,没正常工作可能是因为操作了时钟树相关寄存器~ 另外,不是老师哈,同学,同学!  详情 回复 发表于 2025-7-6 23:13
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:254
  • 最近打卡:2025-08-01 08:52:46
已绑定手机

78

主题

2779

回帖

5722

积分

荣誉版主

无情的代码机器

积分
5722
发表于 2025-7-6 23:13:54 | 显示全部楼层
苏紫*** 发表于 2025-7-6 23:08
感谢老师,64字节分包可以正常收发了,不停电下载也正常了。另外想问一下,复位前用软延时有什么特殊说法 ...

因为这个代码段很多官方例程里都用到了,就直接CV了。
定时器的我没试,没正常工作可能是因为操作了时钟树相关寄存器~
另外,不是老师哈,同学,同学!
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:511
  • 最近打卡:2025-08-01 00:02:36

4

主题

33

回帖

1607

积分

金牌会员

积分
1607
发表于 2025-7-7 01:04:19 | 显示全部楼层
erci*** 发表于 2025-7-6 23:13
因为这个代码段很多官方例程里都用到了,就直接CV了。
定时器的我没试,没正常工作可能是因为操作了时钟 ...

好像还真有问题,就你发我的那个工程,我在main中添加以下代码,使用示波器测量发现P13正常输出500Hz波形,证明定时器一直在运行,但是P12一直输出低电平,程序似乎卡死在while了

  1. u32 msTick;
  2. void timer0_isr() interrupt 1
  3. {
  4.     f1ms = 1;
  5.         msTick++;
  6.         P13=~P13;
  7. }
  8. void delay_ms(u32 a)
  9. {
  10.         P12=0;
  11.     msTick = 0;
  12.     while(msTick < a);
  13.         P12=1;
  14. }
  15. extern void cdc_polling();
  16. void main()
  17. {
  18.     sys_init();
  19.                 usb_add_HID();//默认使用HID接口,也可替换为CDC接口
  20.                 set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
  21.                 initKeyboard();
  22.                 initMouse();
  23.                 uart_init();
  24.                 initCDCEx();
  25.     usb_init();
  26.     P12=1;
  27.                
  28.     EA = 1;
  29.                 while(DeviceState != DEVSTATE_CONFIGURED);
  30.     while (1){
  31.                         if (f1ms)
  32.                         {
  33.                                         f1ms = 0;
  34.                                         scan_key();
  35.                         }
  36.                         delay_ms(20);
  37.                         keyboardRun();
  38.                         mouseRun();
  39.                         uart_polling();
  40.                         cdc_polling();
  41.                 };
  42. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:511
  • 最近打卡:2025-08-01 00:02:36

4

主题

33

回帖

1607

积分

金牌会员

积分
1607
发表于 2025-7-7 01:18:46 | 显示全部楼层
苏紫*** 发表于 2025-7-7 01:04
好像还真有问题,就你发我的那个工程,我在main中添加以下代码,使用示波器测量发现P13正常输出500Hz波形 ...

我有些怀疑是编译器的锅,看反汇编代码,参数是DR4传进去,然后赋值给DR0,然后拿DR0和0作比较,把msTick优化了,自然永远不可能走出while。但是之前这么用过也没出错。

  1.     97: void delay_ms(u32 a)
  2.     98: {
  3. 0xFF22C4   7F01        MOV      DR0,DR4
  4.     99:         P12=0;
  5. 0xFF22C6   C292        CLR      P12(0x90.2)
  6.    100:     msTick = 0;
  7. 0xFF22C8   9F11        SUB      DR4,DR4
  8. 0xFF22CA   7A1F0284    MOV      msTick(0x0284),DR4
  9.    101:     while(msTick < a);
  10. 0xFF22CE   BE080000    CMP      DR0,#0x0000
  11. 0xFF22D2   38FA        JG       C:0x22CE
  12.    102:         P12=1;
  13. 0xFF22D4   D292        SETB     P12(0x90.2)
  14.    103: }
  15.    104:  
  16.    105: extern void cdc_polling();
  17. 0xFF22D6   22          RET      
复制代码

先这么写吧,骗一下编译器
  1. void delay_ms(u32 a)
  2. {
  3.         P12=0;
  4.         if(msTick!=0)
  5.         {
  6.                 msTick = 0;
  7.         }
  8.     while(msTick < a);
  9.         P12=1;
  10. }
复制代码


回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-8-1 14:57 , Processed in 0.132796 second(s), 103 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表