当前位置: 首页 > news >正文

GD32 I2C外设详介绍

好的 👍
你贴的这些 enum 定义其实就是 GD32(或 STM32 类似外设)的 I2C 外设状态标志位、事件中断标志位、以及中断使能位

我给你拆开讲,每类标志什么意思,在哪些场景会用到。


一、I2C 标志位(i2c_flag_enum

这些是 I2C 外设硬件寄存器里的状态位,用来 反映当前 I2C 总线或控制器的状态

STAT0(状态寄存器 0)

  • I2C_FLAG_SBSEND:主机模式下,Start 信号已发出
  • I2C_FLAG_ADDSEND:地址已发送(主机模式),或作为从机接收到自己的地址并匹配成功。
  • I2C_FLAG_BTC字节传输完成。表示 8bit 数据和 ACK/NACK 已经完成。
  • I2C_FLAG_ADD10SEND:10bit 地址模式下,高位地址已发出
  • I2C_FLAG_STPDET:从机模式下,检测到 STOP 条件
  • I2C_FLAG_RBNE:接收缓冲区非空,有数据可读
  • I2C_FLAG_TBE:发送缓冲区空,可以写入数据
  • I2C_FLAG_BERR:总线错误(出现了非预期的 START/STOP)。
  • I2C_FLAG_LOSTARB:主模式下,仲裁丢失(总线上别的主机更强)。
  • I2C_FLAG_AERR:应答错误(对方没有回应 ACK)。
  • I2C_FLAG_OUERR:从机模式下,溢出/欠载错误
  • I2C_FLAG_PECERR:接收时的 PEC 校验错误(主要用于 SMBus)。
  • I2C_FLAG_SMBTO:SMBus 超时。
  • I2C_FLAG_SMBALT:SMBus Alert 事件。

STAT1(状态寄存器 1)

  • I2C_FLAG_MASTER:当前是否在 主机模式
  • I2C_FLAG_I2CBSY:I2C 总线忙标志。
  • I2C_FLAG_TR:传输方向(1=发送器,0=接收器)。
  • I2C_FLAG_RXGC:收到 通用呼叫地址 0x00
  • I2C_FLAG_DEFSMB:收到 SMBus 默认地址。
  • I2C_FLAG_HSTSMB:从机模式下检测到 SMBus 主机头。
  • I2C_FLAG_DUMOD:双地址模式下,指示匹配到哪个地址。

SAMCS(扩展寄存器)

主要是帧同步控制:

  • I2C_FLAG_TFF:发送帧下降沿标志。
  • I2C_FLAG_TFR:发送帧上升沿标志。
  • I2C_FLAG_RFF:接收帧下降沿标志。
  • I2C_FLAG_RFR:接收帧上升沿标志。

(这几个一般用得少,主要是同步应用或 SMBus)


二、I2C 中断标志位(i2c_interrupt_flag_enum

这些是在 中断服务程序里用来判断触发源的标志位
区别在于:

  • 它们不仅仅检查状态寄存器,还要求对应的中断使能位有效。
  • 举例:I2C_INT_FLAG_RBNE = RBNE(数据可读) && 中断使能打开。

所以,中断函数里通常写:

if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE)) {// 有数据可读
}

三、I2C 中断使能位(i2c_interrupt_enum

这些是控制 是否允许某些中断触发 NVIC

  • I2C_INT_ERR:错误中断(仲裁丢失、总线错误、ACK 错误等)。
  • I2C_INT_EV:事件中断(Start 发送、地址匹配、停止条件、字节传输完成等)。
  • I2C_INT_BUF:缓冲中断(TXE=发送缓冲空,RXNE=接收缓冲非空)。
  • I2C_INT_TFF / TFR / RFF / RFR:对应 SAMCS 帧同步中断。

总结(适合你作为初学者的理解)

  1. FLAG(状态位) → 只表示硬件状态,可以 polling 查询。
  2. INT_FLAG(中断标志位) → 在中断里用来判断是哪个事件触发的。
  3. INT(中断使能) → 决定是否把事件推送到 NVIC 触发 ISR。

一个常见使用场景:

  • 发送数据:等 TBE(发送缓冲空),写入数据寄存器。
  • 接收数据:等 RBNE(接收缓冲非空),读数据寄存器。
  • 发生错误:判断 BERR / AERR / LOSTARB

要不要我帮你整理一个 最小 I2C 主机发送/接收流程(基于这些标志位的 polling 版),你直接能拿来参考?


在这里插入图片描述
好的 👍 你这张图是 GD32 I2C 控制寄存器 1(I2C_CTL1) 的说明,
我帮你重点解读 bit9 – EVIE (事件中断使能)


📍 bit9: EVIE — 事件中断使能

  • 位名称:EVIE (Event interrupt enable)
  • 位位置:CTL1[9]
  • 功能:控制 I2C 事件中断 是否生效

🔹 取值说明:

  • 0 = 禁用事件中断

    • I2C 的各种事件不会触发中断请求(CPU 需要通过轮询方式检测标志位)。
  • 1 = 使能事件中断

    • 当以下事件标志位被置位时,会触发中断:

      • SBSEND(起始位已发送)
      • ADDSEND(地址已发送 / 匹配)
      • ADD10SEND(10位地址发送完成)
      • STPDET(停止条件检测到)
      • BTC(字节传输完成)
    • 但是注意:这些事件中断 是否真正产生 还取决于其他相关位是否打开,例如:

      • 若同时设置了 BUFIE=1,那么当 TBE=1RBNE=1 时也会触发中断。
      • 如果 BUFIE=0,则 TBE/RBNE 不会触发中断。

🔹 总结

  • EVIE = 0 → CPU 只能靠轮询标志位来判断 I2C 事件。

  • EVIE = 1 → I2C 硬件会在检测到关键事件(起始、地址、停止、传输完成等)时主动触发中断。

  • 典型用途:在 I2C 主机/从机驱动中,事件中断用来 驱动状态机切换,比如:

    • 起始条件产生 → 发送地址
    • 地址匹配 → 进入读/写阶段
    • 传输完成 → 进入下一步

要不要我帮你把 EVIE + BUFIE + ERRIE 三个使能位整理成一个 中断分类表(事件/缓冲区/错误),这样你一眼就能看出 I2C 驱动中是如何区分这三类中断的?




IIC中断接收发送数据处理流程

很好,这段 i2cx_event_irq_handlerI²C 事件中断服务函数(ISR),主要实现 I²C 主机模式下的读写流程,采用状态机(i2c_write_processi2c_read_process)控制。

我给你分成 写流程读流程 两块来解读。


🔹 1. 写流程 (i2c_process_flag == RESET)

写流程主要步骤:

  1. 发送设备地址 I2C_SEND_ADDRESS_FIRST

    • 检测 SBSEND=1(START 发送完成)。
    • 调用 i2c_master_addressing() → 发送设备地址 + 写位(W)。
    • 下一步 → I2C_CLEAR_ADDRESS_FLAG_FIRST
  2. 清除地址应答标志 I2C_CLEAR_ADDRESS_FLAG_FIRST

    • 检测 ADDSEND=1(从机收到了地址并应答)。
    • 清除该标志。
    • 下一步 → I2C_TRANSMIT_WRITE_READ_ADD
  3. 发送寄存器地址 I2C_TRANSMIT_WRITE_READ_ADD

    • 检测 TBE=1(发送缓冲区空)。
    • 把要操作的寄存器地址(i2c_write_dress)写到 I2C_DATA
    • 等待 BTC=1(传输完成)。
    • 下一步 → I2C_TRANSMIT_DATA
  4. 发送数据内容 I2C_TRANSMIT_DATA

    • 检测 TBE=1
    • 写数据到 I2C_DATA,更新指针和剩余字节计数。
    • 如果数据发完 → 下一步 → I2C_STOP
  5. 结束通信 I2C_STOP

    • 发送 STOP 条件。
    • 关闭 I²C 中断(ERR、BUF、EV)。
    • 状态机复位 → I2C_SEND_ADDRESS_FIRST,等待下次写操作。

📍 总结:写流程就是 → START → 设备地址 → 寄存器地址 → 数据 → STOP。


🔹 2. 读流程 (i2c_process_flag == SET)

读流程比写稍复杂,因为一般要先写寄存器地址,再重新启动读。

  1. 发送设备地址(写方向) I2C_SEND_ADDRESS_FIRST

    • SBSEND=1 时,发设备地址(写)。
    • 下一步 → I2C_CLEAR_ADDRESS_FLAG_FIRST
  2. 清除地址应答标志 I2C_CLEAR_ADDRESS_FLAG_FIRST

    • ADDSEND=1 → 从机应答。
    • 清除标志。
    • 下一步 → I2C_TRANSMIT_WRITE_READ_ADD
  3. 发送要读取的寄存器地址 I2C_TRANSMIT_WRITE_READ_ADD

    • TBE=1 时,写寄存器地址(i2c_read_dress)。
    • BTC=1,发送完成。
    • 发送 STOP → 等 STOP 完成。
    • 再次发送 START(重新进入读模式)。
    • 下一步 → I2C_SEND_ADDRESS_SECOND
  4. 发送设备地址(读方向) I2C_SEND_ADDRESS_SECOND

    • SBSEND=1 → 发设备地址(读)。
    • 如果读取字节数小于 3,提前关闭 ACK(避免多读)。
    • 下一步 → I2C_CLEAR_ADDRESS_FLAG_SECOND
  5. 清除地址应答标志(二次) I2C_CLEAR_ADDRESS_FLAG_SECOND

    • ADDSEND=1 → 清除标志。
    • 如果只读 1 或 2 个字节 → 关闭 ACK。
    • 下一步 → I2C_TRANSMIT_DATA
  6. 接收数据 I2C_TRANSMIT_DATA

    • RBNE=1(接收缓冲非空) → 读一个字节到 *i2c_read

    • 字节计数递减。

    • 如果剩 3 个字节时 → 等 BTC=1 再关闭 ACK(保证最后几个字节正确处理)。

    • 当字节读完:

      • 发送 STOP。
      • 关闭中断。
      • 状态机复位,i2c_process_flag=RESET

📍 总结:读流程就是 → START → 写设备地址 + 寄存器地址 → STOP → 再 START → 设备地址(读) → 收数据 → STOP。


🔹 整体理解

这个 中断服务函数 实现了 I²C 读写的完整状态机

  • 写数据
    START → 地址(写) → 寄存器地址 → 数据 → STOP。

  • 读数据
    START → 地址(写) → 寄存器地址 → STOP → 再 START → 地址(读) → 接收数据 → STOP。

通过中断判断 SBSEND/ADDSEND/TBE/RBNE/BTC 等标志位,逐步推进流程,避免阻塞式等待。


要不要我帮你画一个 时序图(SCL/SDA 波形 + 状态机切换),把这段流程更直观地可视化?




I2C读取数据样例

I2C read 一个字节数据(不读了给一个NACK)

在这里插入图片描述

I2C read 多个字节数据(读一个字节给一个ACK,不读了 给个NACK )

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

I2C写入数据样例

在这里插入图片描述
在这里插入图片描述

http://www.dtcms.com/a/431637.html

相关文章:

  • 【C++】C++的多态是个啥,咋用的?
  • 【Linux 系统】进程状态
  • 搜索引擎网站排行榜广州seo优化公司排名
  • 【强化学习】#8 DQN(深度Q学习)
  • 【原创】SpringBoot3+Vue3学生信息管理系统
  • Linux查看日志方法
  • 个人签名设计网站服装网站策划设计
  • 《Span-based Localizing Network for Natural Language Video Localization》
  • VRRP上行逃生:两种核心方案详解
  • 方法的调用:递归
  • 设计师常用的灵感网站做网站怎么盈利
  • 工程承包网站哪个好?临汾工程建设招标投标网站
  • 从新疆油田数据采集器,看Digi ZigBee模块在石油行业上的应用
  • C语言指针与字符串详解
  • 全长抗体表达:从载体策略到产业化,如何实现高活性抗体的高效生产?
  • 0.3 神经网络学习率、激活函数、损失函数
  • 最全的ppt模板网站舆情监测系统永久免费
  • MySQL通过二进制日志恢复数据
  • 建立网站专业公司吗wordpress 换主题问题
  • 高功耗显卡装机实战:电源 / 机箱 / 主板兼容问题全解析与解决方案
  • Java 性能监控与分析工具
  • 写作网站六大神书wordpress改小程序
  • 网站没建设可以访问吗最流行的网站开发
  • 【图像理解进阶】微调Qwen2.5-VL-32B用于遥感图像理解:从硬件到代码实践
  • 比较有名的diy制作网站wordpress category_name
  • 利用视觉对齐的文本洞察进行医学图像分割
  • 定西兰州网站建设做公司简介需要多少钱
  • 网站icp备案查不到兼职做调查哪个网站好
  • 【C++】透视C++多态:从虚函数表到底层内存布局的完全拆解
  • PSG技术分析:战术体系与关键角色