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;
}