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

嵌入式基础 -- I²C 信号与位层规则

I²C 信号与位层规则

  • 两根线SCL(时钟)与 SDA(数据),开漏/开集输出,必须上拉电阻(2.2k–10k 典型,取决于总线电容与速率)。FPGA 只能“拉低或高阻”,绝不主动拉高
  • 空闲SCL=1SDA=1
  • STARTSCL=1 时,SDA 从 1→0。
  • STOPSCL=1 时,SDA 从 0→1。
  • 位有效窗口:数据在 SCL=1 期间有效、SCL=0 期间允许变化(除 START/STOP)。
  • 第 9 个时钟为 ACK 位:每发完 8 bit 字节后,接收方在第 9 个 SCL 周期拉低 SDA 作为 ACK;不拉低即 NACK
  • 时序等级(常用):Standard(100 kHz)、Fast(400 kHz)、Fast+(1 MHz)、High-Speed(3.4 MHz)。速率越高,需要更小的上拉与更紧的布线。
  • 时钟拉伸(Clock Stretching):从设备可在位间隙拉低 SCL 拖延时间,主机必须等待 SCL 真的被释放为高再继续。
  • 多主仲裁SCL=1 期间,主机边发边读回 SDA;若自己想发“1”(释放)却读到“0”,判定丢失仲裁并立刻退让。

常见事务流程(7 位地址为例)

1) 主机写从机寄存器(典型“寄存器指针+写数据”)

  1. START
  2. 发送 ADDR[6:0] + W(0) → 从机 ACK
  3. 发送 REG_ADDR(子地址/寄存器指针)→ 从机 ACK
  4. 发送 DATA0ACK;可继续 DATA1/2/...(每字节均有 ACK)
  5. STOP

2) 主机读取从机寄存器(“写指针 + 重启 + 读数据”)

  1. START

  2. ADDR + WACK

  3. 发送 REG_ADDRACK

  4. Repeated START(不放 STOP

  5. ADDR + R(1)ACK

  6. 主机在每个数据字节后:

    • 若还想继续读 → 回 ACK
    • 读最后一字节 → 回 NACK
  7. STOP

3) 直接顺序读取

  • STARTADDR + R → 字节流(主机对前面字节回 ACK,最后回 NACK)→ STOP

10 位地址、General Call(0x00)、PEC(SMBus) 都是扩展场景,FPGA 侧按需支持。

在 FPGA 里怎么实现(主机/从机通用要点)

IO 级:开漏输出

// 以通用三态举例:当 oe=1 时拉低,oe=0 时高阻(交给上拉)
assign sda = (sda_oe) ? 1'b0 : 1'bz;
wire   sda_i = sda;assign scl = (scl_oe) ? 1'b0 : 1'bz;  // 主机实现时钟用,或从机用于拉伸
wire   scl_i = scl;

Lattice/Intel/Xilinx 可用 IOBUF/OBUFT 原语;不要驱动“1”。开发板“内置上拉(PULLMODE=UP)”强度很弱,只适合极低速+实验,实机务必用外部上拉

位采样/去抖与同步

  • SCL/SDA异步输入,各加两级同步器毛刺过滤(如 3~5 采样取多数票)。
  • 接收侧SCL 上升沿锁存 SDA发送侧SCL 低电平期间改变 SDA

主机 FSM 关键状态

  • IDLE → START → ADDR → ACK_A → (REG/WRITE/REPEAT/READ) … → STOP
  • 波特率发生器:soc_clk 分频产生 SCL 低/高时间;发每一位时遵守“先改 SDA,再拉高 SCL 让对端采样”。

从机 FSM 关键状态

  • 监测 START/STOP;在 SCL 高期间取样 SDA 识别位流。
  • 地址匹配后按读写分流;写路经收子地址更新“寄存器指针”,读路经从该指针出数并自增。
  • buffer 不就绪时可拉伸 SCL(把 scl_oe=1 拉低)争取时间。

CDC/约束

  • SCL/SDAsoc_clk 的路径为异步,用同步器设定 false pathset_clock_groups -asynchronous
  • 若主机用 soc_clk 分频出 SCL,对 SCLgenerated clock;不要门控时钟,用时钟使能

常见边界/异常

  • NACK:地址不匹配、寄存器不可用、数据区空等。
  • 总线挂死(SDA 被某器件一直拉低):主机可输出9 个 SCL 脉冲尝试释放,再发 STOP
  • 上拉过大:上升沿太慢,高速不达标;过小:电流大、功耗高、器件下拉能力吃紧。按总线电容计算 RC 常数选值。
  • 仲裁丢失:必须立刻退总线,等待空闲再发起。
http://www.xdnf.cn/news/1460377.html

相关文章:

  • Swift 解法详解:LeetCode 371《两整数之和》
  • 漏洞绕过方式
  • 从零到一:人工智能应用技术完全学习指南与未来展望
  • ClickHouse 分片、 Distributed 表、副本机制
  • flowable基础入门
  • 【c/c++】深度DFS
  • MATLAB平台实现人口预测和GDP预测
  • 美国教授提出的布鲁姆法,结合AI直击学术科研痛点,写作与创新效率直接翻倍!
  • 漫谈《数字图像处理》之实时美颜技术
  • Java并行计算详解
  • 解决 Rollup failed to resolve import “vue3-json-viewer/dist/index.css“ from xxx
  • 【Docker】P1 前言:容器化技术发展之路
  • JS本地存储
  • Java String vs StringBuilder vs StringBuffer:一个性能优化的探险故事
  • C++学习记录(6)string部分操作的模拟实现
  • push pop 和 present dismiss
  • Leetcode 206. 反转链表 迭代/递归
  • 拦截器和过滤器(理论+实操)
  • Websocket链接如何配置nginx转发规则?
  • NV169NV200美光固态闪存NV182NV184
  • 云数据库服务(参考自腾讯云计算工程师认证课程)更新中......
  • 阿里云 ESA 实时log 发送没有quta的解决
  • 【机器学习】HanLP+Weka+Java=Random Forest算法模型
  • 【CS32L015C8T6】配置单片机时基TimeBase(内附完整代码及注释)
  • Mysql杂志(九)
  • [frontend]WebGL是啥?
  • AI入坑: Trae 通过http调用.net 开发的 mcp server
  • 批量生成角色及动画-统一角色为Mixamo骨骼(一)
  • Qt实现2048小游戏:看看AI如何评估棋盘策略实现“人机合一
  • 对于数据结构:链表的超详细保姆级解析