找回密码
 立即注册
查看: 276|回复: 5

USB与串口4

[复制链接]
已绑定手机

1

主题

2

回帖

15

积分

新手上路

积分
15
发表于 2026-8-8 14:30:13 | 显示全部楼层 |阅读模式
芯片使用STC32G12K128系列时,在初始化usb与串口4的时候发现一个问题,先初始化串口4,然后再初始化usb,usb可以正常使用,但是如果先初始化usb,再初始化串口4,这会导致usb无法正常使用。

图片是deepseek给的答案,不知道是否正确
deepseek问题回答.png
回复

使用道具 举报 送花

11

主题

148

回帖

1443

积分

金牌会员

积分
1443
发表于 2026-8-8 15:56:31 | 显示全部楼层
有道理,但是串口4 不是在位4吗,应该是0x10吧。
手册中说读时为0,那你直接把EUSB的位也置成1,不就可以了吗。就是IE2|=0x90;
微信qsssuv
回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
发表于 2026-8-8 18:02:39 | 显示全部楼层
截图202608081802233275.jpg
回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
发表于 2026-8-8 18:02:48 | 显示全部楼层

我找到了官方工程师(zhp)对该问题的权威回复。现在我可以给出完整、准确的回答。让我再确认一下楼主帖子中关于 ES4 位位置的正确性。

根据手册 IE2 寄存器定义:

  • B7 = EUSB(0x80)
  • B6 = ET4(0x40)
  • B5 = ET3(0x20)
  • B4 = ES4(0x10) ✅ 青穗说串口4在位4是正确的
  • B3 = ES3(0x08)
  • B2 = ET2(0x04)
  • B1 = ESPI(0x02)
  • B0 = ES2(0x01)

青穗的建议 IE2 |= 0x90 = 0x80 (EUSB) + 0x10 (ES4),这个理解正确。但问题的关键不在于此——关键在于 EUSB 位是只写位,不能通过"读-改-写"指令(如 |=)来修改其他位,否则会把 EUSB 清0。

现在我可以给出权威、完整的解答了。


关于 STC32G12K128 初始化 USB 与串口4 顺序导致 USB 失效的问题

楼主你好,这个问题我结合手册和论坛中官方工程师的确认,给你一个准确解答。

一、问题根源:EUSB 位是只写位

根据 STC32G 数据手册《中断系统》 章节中 IE2 寄存器的定义:

EUSB:USB中断允许位。(注意:此位为只写位,不可读取,读取始终为0)

  • 0:禁止USB中断
  • 1:允许USB中断

EUSB 是只写位,读取恒为 0。 这正是问题的关键所在。

二、为什么"先初始化USB再初始化串口4"会导致 USB 失效

先看 IE2 寄存器的位定义(地址 AFH):

B7 B6 B5 B4 B3 B2 B1 B0
EUSB ET4 ET3 ES4 ES3 ET2 ESPI ES2
0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01

当你先初始化 USB 时,代码中会用类似 EUSB = 1(或 IE2 |= 0x80)的方式打开 USB 中断。

随后再初始化串口4,如果你的代码写的是类似:

IE2 |= 0x10;   // 使能串口4中断 ES4

这条语句是 读-改-写(Read-Modify-Write) 操作。由于 EUSB 位读取时恒为 0,那么"读"回的值中 EUSB 已经是 0,再"写"回去时,EUSB 就被清 0 了,USB 中断就被意外关闭,导致 USB 无法正常工作。

反过来,如果先初始化串口4,再初始化 USB(此时用 EUSB = 1 直接赋值),由于对 EUSB 的置位发生在串口4的读-改-写之后,所以 EUSB 不会被清掉,USB 就能正常使用。这与你在论坛观察到的现象完全一致。

三、验证:青穗的回复中 ES4 位位置正确

青穗回复说"串口4 在位4,应该是 0x10",这一点是对的(手册中 ES4 确实在 B4,即 0x10)。他建议的 IE2 |= 0x90:

  • 0x80 = EUSB(B7)
  • 0x10 = ES4(B4)

从位值上看没问题,但这样写仍然存在读-改-写陷阱——它同样会清掉 EUSB。官方推荐的写法是直接赋值给 IE2,而不是用 |=。

四、官方推荐的解决方案

据 STC 官方工程师(zhp)在论坛 TID 2417 中的确认,这个问题是 STC32G12K128 系列的设计局限(EUSB 为只写位,读取恒为 0),官方建议规避方式有两种:

方案一:在每次读-改-写 IE2 其他位之后,再补一次 EUSB = 1;

// 初始化串口4
IE2 |= 0x10;   // 使能串口4中断(此句会把 EUSB 清0)
EUSB = 1;      // 补救:重新打开 USB 中断

方案二(推荐):不使用 |=,直接用等号整体赋值 IE2

// 同时打开 USB 中断和串口4中断
IE2 = 0x90;    // = 0x80 (EUSB) + 0x10 (ES4)

不过要注意,方案二要求你能一次列出所有需要的使能位,避免遗漏。


补充说明

  • STC8H8K64U 无此问题(据官方工程师在论坛反馈),这是 STC32G 系列特有的设计局限。
  • 手册中已在 IE2 的 EUSB 位处明确标注了"只写位、读取始终为0"的注意事项,建议代码中涉及 IE2 时尽量用整体赋值,避免对所有位做"读-改-写"。

如果你目前在 STC32G12K128 上写库函数(如在 Keil C251 中),建议把 USB 的使能放在所有涉及 IE2 位操作的初始化最末尾,或者统一使用整体赋值的方式,就能规避这个问题。如果还有其他疑问,欢迎继续交流!


🔍 搜索 "https://www.stcaimcu.com/thread-25180-1-1.html"

⏱️ 查找用时 13.9s | 总回答用时 23.4s

回复

使用道具 举报 送花

已绑定手机

1

主题

2

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2026-8-12 11:31:47 | 显示全部楼层
青穗*** 发表于 2026-8-8 15:56
有道理,但是串口4 不是在位4吗,应该是0x10吧。
手册中说读时为0,那你直接把EUSB的位也置成1,不就可以了 ...

是的,当时我用的库函数,没有直接操作寄存器,后续我就直接操作的寄存器
回复

使用道具 举报 送花

已绑定手机

1

主题

2

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2026-8-12 11:33:17 | 显示全部楼层
神*** 发表于 2026-8-8 18:02
我找到了官方工程师(zhp)对该问题的权威回复。现在我可以给出完整、准确的回答。让我再确认一下楼主帖子 ...

非常感谢,当时这个问题发现的时候,花了一些时间,在论坛也没有搜索到相关内容,所以才发个帖子说一下,希望后续遇到这个问题的时候有所参考
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-11-7 14:11 , Processed in 0.071585 second(s), 73 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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