找回密码
 立即注册
查看: 104|回复: 2

擎天柱使用printf_usb打印接受不到数据

[复制链接]
已绑定手机

82

主题

218

回帖

700

积分

高级会员

积分
700
发表于 2026-8-16 10:38:58 | 显示全部楼层 |阅读模式
无论是查询方式还是中断方式,
在CDC-HID串口助手中发送响应的数据始终无法接接收到擎天柱的数据,
但是这个“直接打印数据”却可以


截图202608161038466702.jpg

回复

使用道具 举报 送花

865

主题

1万

回帖

2万

积分

管理员

积分
25122
发表于 2026-8-16 12:12:38 | 显示全部楼层
截图202608161212244625.jpg
回复

使用道具 举报 送花

865

主题

1万

回帖

2万

积分

管理员

积分
25122
发表于 2026-8-16 12:13:04 | 显示全部楼层

我已经获取到了手册中关于 USB-CDC printf 收发机制的关键信息。现在可以对这个帖子的问题进行深入分析了。

关于"擎天柱 printf_usb 打印接收不到数据"的问题

楼主的问题是:无论是"查询方式"还是"中断方式"的实验,在 CDC-HID 串口助手中发送数据后,始终无法接收到擎天柱(Ai8051U)返回的数据,但"直接打印数据"例程却可以正常工作。

根据 Ai8051U 数据手册《USB库函数使用说明》 章节,我来帮您梳理这个问题的关键点。

核心原因分析

这三个实验("直接打印数据" vs "打印接收到的数据(查询方式/中断方式)")的区别,关键在于数据的方向

  • "直接打印数据"例程:是单片机主动向 PC 发送数据(上行)。它用的是 printf_usb(),这个函数内置了判断 USB 状态和发送忙的逻辑(见下面的手册说明),所以即使 USB 还没完全配置好,也不会堵塞,数据会正常打印出来。
  • "打印接收到的数据"(查询/中断方式)例程:是PC 先发数据给单片机(下行),单片机收到后原样返回(上行)。这个流程依赖 bUsbOutReady 标志,而楼主的代码里极有可能是没有正确触发数据接收的条件

关键点一:bUsbOutReady 是接收成功的标志

根据手册:

"bUsbOutReady":主机发送给HID/CDC设备的数据状态。状态位为1表示,主机发送给HID/CDC设备数据已完成,设备已成功接收一包数据,等待对数据继续处理。

所以,只有当 bUsbOutReady == 1 时,UsbOutBuffer 里的数据才有效。如果楼主的程序从来没有走到 if (bUsbOutReady) 里面,自然就不会有回发了。

关键点二:查询方式必须调用 usb_OUT_done()

手册中强调:

"当使用查询方式调用USB库函数时,数据处理完成后,必须调用一次'usb_OUT_done();',这样才能接收下一包数据。如果是使用中断方式调用USB库函数,用户程序不需要调用'usb_OUT_done();',库函数内部会自动处理。"

如果查询方式下漏掉了 usb_OUT_done();,那么只能接收第一包数据,之后就无法再接收新数据了。

关键点三:中断方式必须正确设置回调函数

手册中说明:

"如果需要使用中断方式调用USB库函数,需要调用此函数来设置回调函数。若不设置,则是使用默认的查询方式调用USB库函数。"

即中断方式必须调用 set_usb_OUT_callback(usb_callback); 来注册回调函数。如果只写了一个中断服务函数但没有调用 set_usb_OUT_callback() 注册,那么中断回调永远不会被触发,数据自然收不到。这是一个非常常见的遗漏点。

同时还要确认 EA = 1; 总中断已经打开(USB 库依赖中断工作)。

给楼主的排查建议

请按以下顺序检查您的"查询方式"和"中断方式"代码:

查询方式检查清单:

  1. ✅ 主循环是否检测了 if (bUsbOutReady)
  2. ✅ 数据处理后是否调用了 usb_OUT_done();
  3. EA = 1; 是否已打开?(查询方式也需要,USB 底层引擎靠中断工作)

中断方式检查清单:

  1. ✅ 是否调用了 set_usb_OUT_callback(usb_callback); 注册回调?(最容易漏
  2. ✅ 回调函数里是否有 USB_SendData(UsbOutBuffer, OutNumber);
  3. EA = 1; 是否已打开?

正确的查询方式核心代码(参考手册范例)

while (1)
{
    if (bUsbOutReady)        // 检测到主机发来一包数据
    {
        USB_SendData(UsbOutBuffer, OutNumber);   // 数据原样返回
        usb_OUT_done();      // ★ 必须调用,才能接收下一包
    }
}

正确的中断方式核心代码(参考手册范例)

void usb_callback()          // 自定义 USB OUT 中断回调
{
    USB_SendData(UsbOutBuffer, OutNumber);   // 数据原样返回
}

void main()
{
    // ... 端口配置 ...
    usb_init();
    set_usb_OUT_callback(usb_callback);   // ★ 必须注册回调函数
    EA = 1;
    while (1);
}

小结

检查项 查询方式 中断方式
检测 bUsbOutReady / 回调触发 主循环 if(bUsbOutReady) 注册 set_usb_OUT_callback()
是否调用 usb_OUT_done() 必须调用 不需要(库自动处理)
EA = 1 总中断 需要 需要

信息来源:Ai8051U 数据手册《USB库函数使用说明》章节——"USB库函数的详细说明"及"USB范例程序,查询方式和中断方式各举一例"部分。


建议您对照手册里的范例程序1(查询方式)和范例程序2(中断方式)逐一核对您的代码。如果确认以上清单都正确但仍收不到数据,欢迎把您的完整代码贴出来,我帮您具体排查。另外请确认使用的实验箱/擎天柱的 USB 口与 PC 连接正常,且串口助手选择的是对应 CDC 的 COM 口。


🔍 搜索 "STC 单片机 AI MCU 论坛"

⏱️ 查找用时 7.1s | 总回答用时 18.6s

回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-9-23 15:05 , Processed in 0.065912 second(s), 50 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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