ercircle 发表于 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发送

猫虎的 发表于 2025-6-19 08:34:03

厉害,愿此贴能多保留一段时间,过段时间开始做HID键鼠

苏紫方璇 发表于 2025-7-6 11:48:00

老师,您的键盘鼠标+cdc的例子,cdc收发测试是短接rxtx,我看USB_SendData是在端点1的hid里面的,能不能加的那个cdc也可以使用USB_SendData,直接在usb_out_ep5中写in的fifo可以吗

ercircle 发表于 2025-7-6 12:24:07

苏紫方璇 发表于 2025-7-6 11:48
老师,您的键盘鼠标+cdc的例子,cdc收发测试是短接rxtx,我看USB_SendData是在端点1的hid里面的,能不能加 ...

可以的,Usb sendData也是调用fifo写函数。

苏紫方璇 发表于 2025-7-6 13:46:41

我试着修改了一下,有点问题
1,不停电下载字符串可以正确响应,但是无法重启到usb_Writer那里
2,接收重发那里,单个包在120以内比较稳定,120-127有时会接收不到,超过端点5最大IN的长度,分包发送时,接收不到任何信息。而且使用wireshark抓包会一直刷IN的信息
附上代码,main那里在1ms的定时器里加了个msTick++,注释了uart中动态调节主频的,其他修改均在下面代码中明显标注了
#include "ai8051u.h"
#include "ai_usb_ex.h"
#include "string.h"
#include "uart.h"
#include "CDC_ex_desc.h"

LINECODING LineCoding1;
LINECODING LineCoding2;
BYTE Interface;
BOOL Ep4InBusy;
BOOL Ep5InBusy;
BOOL Ep4OutBusy;
BOOL Ep5OutBusy;

BYTE xdata UsbBuffer;
void uart_settings(BYTE index)
{
                Interface = index;
    if (Interface == CDC1_FIRST_INTERFACE)
    {
      LineCoding1.bCharFormat = 0;
      LineCoding1.bDataBits = 8;
    }
                else if (Interface == CDC2_FIRST_INTERFACE)
    {
      LineCoding2.bCharFormat = 0;
      LineCoding2.bDataBits = 8;
    }

    uart_set_parity();
    uart_set_baud();
}



void usb_in_ep4()
{
    BYTE csr;

    usb_write_reg(INDEX, 4);
    csr = usb_read_reg(INCSR1);
    if (csr & INSTSTL)
    {
      usb_write_reg(INCSR1, INCLRDT);
    }
    if (csr & INUNDRUN)
    {
      usb_write_reg(INCSR1, 0);
    }
}
void usb_in_ep5()
{
    BYTE csr;

    usb_write_reg(INDEX, 5);
    csr = usb_read_reg(INCSR1);
    if (csr & INSTSTL)
    {
      usb_write_reg(INCSR1, INCLRDT);
    }
    if (csr & INUNDRUN)
    {
      usb_write_reg(INCSR1, 0);
    }

    Ep5InBusy = 0;
}
////////////////////////////////////////////////////////////////////////
//补两个函数
void usb_write_fifo(BYTE fifo, BYTE *pdat, BYTE cnt)
{
        while (cnt--)
        {
      usb_write_reg(fifo, *pdat++);
    }
}

void _usb_bulk_intr_in(BYTE *pData, BYTE bSize, BYTE ep)
{
    usb_write_fifo((BYTE)(FIFO0 + ep), pData, bSize);
    usb_write_reg(INCSR1, INIPRDY);
}
////////////////////////////////////////////////////////////////////////

void usb_out_ep5()
{
    BYTE csr;
    BYTE cnt,addr,i=0;

    usb_write_reg(INDEX, 5);
    csr = usb_read_reg(OUTCSR1);
    if (csr & OUTSTSTL)
    {
      usb_write_reg(OUTCSR1, OUTCLRDT);
    }
    if (csr & OUTOPRDY)
    {
      cnt = usb_read_reg(OUTCOUNT1);
      while (cnt--)
      {
                        UsbBuffer = usb_read_reg(FIFO5);
            Uart2RxBuffer = UsbBuffer;
                        i++;
      }
                /////////////////////////////////////////////////////////
                //判断命令@STCISP#
                if(i==8)
                {
                        UsbBuffer=0;
                        if(strcmp(UsbBuffer,"@STCISP#")==0)
                        {
                                EUSB = 0;
                                USBCON = 0x00;
                USBCLK = 0x00;
                IRC48MCR = 0x00;
                msTick=0;//main中1ms定时器计数
                                while(msTick<20);
                  
                                IAP_CONTR = 0x60;
                                while(1);
                        }
                }
                //回发数据
                EUSB=0;
                usb_write_reg(INDEX, 5);
                addr=0;
                do
                {
                        cnt=(i > EP5IN_SIZE) ? EP5IN_SIZE : i;
                        while (usb_read_reg(INCSR1) & INIPRDY);
                        _usb_bulk_intr_in(&UsbBuffer, cnt, 5);
                        addr += cnt;
                        i -= cnt;
                }while(cnt>=EP5IN_SIZE);
                EUSB=1;
                /////////////////////////////////////////////////////////               
               
               
               
               
      if ((BYTE)(Uart2RxWptr - Uart2RxRptr) >= (BYTE)(256 - EP5OUT_SIZE))
      {
            Ep5OutBusy = 1;
      }
      else
      {
            usb_write_reg(OUTCSR1, 0);
      }

    }
}


void initCDCEx(){
                //修改PID
                DEVICEDESC = 0x0a;
                DEVICEDESC = 0xFF;
                set_usb_uart_settings_callback(uart_settings);
               
                //添加CDC,使用EP4 EP5
                usb_add_interface(CDC2_FIRST_INTERFACE,CONFIGDESC_CDC2_HEAD,sizeof(CONFIGDESC_CDC2_HEAD),&LineCoding2);
                usb_add_interface(CDC2_FIRST_INTERFACE+1,CONFIGDESC_CDC2_BODY,sizeof(CONFIGDESC_CDC2_BODY),NULL);
                set_usb_ep_callback(4,64,usb_in_ep4,0,0);
                set_usb_ep_callback(5,128,usb_in_ep5,248,usb_out_ep5);
}

ercircle 发表于 2025-7-6 14:56:53

苏紫方璇 发表于 2025-7-6 13:46
我试着修改了一下,有点问题
1,不停电下载字符串可以正确响应,但是无法重启到usb_Writer那里
2,接收重发 ...



参考这个,有几个注意点:
1.复位前用的软延时
2.CDC分包64字节发送,并且Rx数为64字节倍数时要发一包空包
3.CDC Bulk端点,协议里wMaxPacketSize要声明64字节,这里之前写错了。
原因参考这个:https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=16680&pid=166931


苏紫方璇 发表于 2025-7-6 23:08:51

ercircle 发表于 2025-7-6 14:56
参考这个,有几个注意点:
1.复位前用的软延时
2.CDC分包64字节发送,并且Rx数为64字节倍数时要发一包 ...

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

ercircle 发表于 2025-7-6 23:13:54

苏紫方璇 发表于 2025-7-6 23:08
感谢老师,64字节分包可以正常收发了,不停电下载也正常了。另外想问一下,复位前用软延时有什么特殊说法 ...

因为这个代码段很多官方例程里都用到了,就直接CV了。
定时器的我没试,没正常工作可能是因为操作了时钟树相关寄存器~
另外,不是老师哈,同学,同学!{:woshou:}

苏紫方璇 发表于 2025-7-7 01:04:19

ercircle 发表于 2025-7-6 23:13
因为这个代码段很多官方例程里都用到了,就直接CV了。
定时器的我没试,没正常工作可能是因为操作了时钟 ...

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

u32 msTick;
void timer0_isr() interrupt 1
{
    f1ms = 1;
        msTick++;
        P13=~P13;
}

void delay_ms(u32 a)
{
        P12=0;
    msTick = 0;
    while(msTick < a);
        P12=1;
}

extern void cdc_polling();
void main()
{
    sys_init();
                usb_add_HID();//默认使用HID接口,也可替换为CDC接口
                set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
                initKeyboard();
                initMouse();
                uart_init();
                initCDCEx();
    usb_init();
    P12=1;
               
    EA = 1;
                while(DeviceState != DEVSTATE_CONFIGURED);
    while (1){
                        if (f1ms)
                        {
                                        f1ms = 0;
                                        scan_key();
                        }
                        delay_ms(20);
                        keyboardRun();
                        mouseRun();
                        uart_polling();
                        cdc_polling();
                };
}

苏紫方璇 发表于 2025-7-7 01:18:46

苏紫方璇 发表于 2025-7-7 01:04
好像还真有问题,就你发我的那个工程,我在main中添加以下代码,使用示波器测量发现P13正常输出500Hz波形 ...
我有些怀疑是编译器的锅,看反汇编代码,参数是DR4传进去,然后赋值给DR0,然后拿DR0和0作比较,把msTick优化了,自然永远不可能走出while。但是之前这么用过也没出错。

    97: void delay_ms(u32 a)
    98: {
0xFF22C4   7F01      MOV      DR0,DR4
    99:         P12=0;
0xFF22C6   C292      CLR      P12(0x90.2)
   100:   msTick = 0;
0xFF22C8   9F11      SUB      DR4,DR4
0xFF22CA   7A1F0284    MOV      msTick(0x0284),DR4
   101:   while(msTick < a);
0xFF22CE   BE080000    CMP      DR0,#0x0000
0xFF22D2   38FA      JG       C:0x22CE
   102:         P12=1;
0xFF22D4   D292      SETB   P12(0x90.2)
   103: }
   104:
   105: extern void cdc_polling();
0xFF22D6   22          RET      
先这么写吧,骗一下编译器
void delay_ms(u32 a)
{
        P12=0;
        if(msTick!=0)
        {
                msTick = 0;
        }
    while(msTick < a);
        P12=1;
}

页: 1 2 3 [4] 5
查看完整版本: USB拓展库及使用示例 | 本贴 咨询 USB,基本帮您把USB程序开发完成