差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
i2c [2017/03/26 21:05]
gongyu
i2c [2023/05/30 11:13] (当前版本)
gongyu
行 1: 行 1:
 +#### I2C - 集成电路之间的同步、半双工数据传输
 +
 +---
 +
 I2C是一种简单地连接多个芯片的总线方式,尤其是在[[FPGA]]s/​[[CPLD]]s中. I2C是一种简单地连接多个芯片的总线方式,尤其是在[[FPGA]]s/​[[CPLD]]s中.
 {{ ::​i2cslave.gif |}} {{ ::​i2cslave.gif |}}
  
 +### I2C总线特性
  
-====== 概述 ====== +  ​除了“电源”和“地”之外,只用了"​SDA"​"​SCL"​两根信号线 
-===== I2C总线特性 ===== +  * 在同一个总线上最多可以支持到100个器件,每个挂在总线的器件都有一个地址用于寻址 
- +  * 多个“主”设备(例如,两个[[CPU]]可以简单地共用同一个I2C器件
-  ​Uses only 2 wires (named ​"​SDA" ​and "​SCL"​) in addition to power and ground +  * 为业界标准,由Philips开发被很多其它厂商采用 
-  * Can support over 100 devices on the same bus (each device on the bus has an address to be individually accessible) +  * 用途非常广泛,比如电视机、PCs
-  * Multi-master ​(for exampletwo CPUs can easily share the same I2C devices+
-  * Industry standard (developed by Philips, ​adopted by many other manufacturers) +
-  * Used everywhere (TVs, PCs...)+
  
 但是: 但是:
-  * Relatively slow (100Kbps ​base speedwith extensions up to 3.4Mbps) +  * 速度相对比较慢(100Kbps基础速率,可以扩展到3.4Mbps) 
-  * Not plug-and-play+  * 不支持“即插即用” 
  
-===== 工作原理 ===== +一个I2C总线需要至少一个I2C主和I2C
-An I2C bus needs at a minimum an I2C master and an I2C slave+I2C“主”即可以向“从”写也可以从“从”设备中读取
-The I2C master is a transaction (a master can write-to or read-from a slave). +
-The I2C slave is a transaction recipient (a slave can be written-to or read-from a master).+
  
-===== I2C波型 ===== +#### I2C波形  
-Here's how it looks on the bus+{{ :i2c_timing.png |}} 
-This a write to an EEPROM at address ​0x51, with data bytes 0x50 and 0x0F.+这个图示为向地址为0x51的EEPROM进行写2个字节的数据0x500x0F.
  
  {{ ::​i2c_writetoeeprom.gif |initiator}}  {{ ::​i2c_writetoeeprom.gif |initiator}}
  
-An I2C transaction begins with a "start" ​conditionfollowed by the address of the device we wish to speak to, a bit to indicate if we want to read or write, the data written or read, and finally a "​stop"​. +一个I2C过程由"起始"开始接着是我们要通信的设备的地址,有一位标记此操作是“读”还是“写”;要读取或写入的“数据”,最后是个“终止”位。
-There are other details, like the need to have an "​acknowledge"​ bit after each byte transmitted... see the waveform above, and the project'​s links.+
  
 +还有其它的一些细节,比如在每个字节传输以后需要一个”应答“位,参看波形图。
  
-====== I2C从模式示例1 ====== +在FPGA或CPLD中有两种方式创建一个I2C从功能:
-在FPGA或CPLD中有两种方式创建一个I2C ​slave+
   * 直接使用你FPGA/CPLD中的SCL信号线作为时钟信号   * 直接使用你FPGA/CPLD中的SCL信号线作为时钟信号
   * 使用更快的时钟信号过取样你的SDA和SCL信号   * 使用更快的时钟信号过取样你的SDA和SCL信号
  
-第一种方法设计比较紧凑,但不如第二种方法可靠。+第一种方法设计比较紧凑,但不如第二种方法可靠,在这里我们简单讲一下第一种方法的实现过程
  
-I2C slave示例1:​ 采用方法1进行IO扩展 ​SCL在FPGA/CPLD中作为时钟信号+目标:通过I2C进行IO端口扩展SCL在FPGA/CPLD中作为时钟信号
  
-Here's a view of our IO extender. 
  
 {{ ::​i2cslave.gif |}} {{ ::​i2cslave.gif |}}
  
-The I2C slave module is connected to a small 8-bits memory that can be read and written from the I2C bus. The 8-bits are also exported outside the FPGA/CPLD. That creates an I2C IO extender.+I2C从模块连接到一个小的8位存储器,这个存储器可以通过I2C总线进行读写,这8位为FPGACPLD的外部连线,这样就实现了一个I2CIO端口扩展
  
-First the module declaration.+第一步,先定义模块 
 +<code verilog>
 module I2CslaveWith8bitsIO(SDA,​ SCL, IOout); module I2CslaveWith8bitsIO(SDA,​ SCL, IOout);
 inout SDA; inout SDA;
 input SCL; input SCL;
 output [7:0] IOout; output [7:0] IOout;
-Then the 7-bits address that we want for our I2C slave.+</​code>​ 
 + 
 +接着是我们需要的I2C“从”设备的7位地址 
 + 
 +<code verilog>
 parameter I2C_ADR = 7'h27; parameter I2C_ADR = 7'h27;
-Then the start and stop conditions detection logic. +</​code>​ 
-That's the "black magic" part of this design...+ 
 +接着是“起始”和“终止”检测逻辑,这也是本设计中最神秘的部分。 
 + 
 +<code verilog>
 // We use two wires with a combinatorial loop to detect the start and stop conditions // We use two wires with a combinatorial loop to detect the start and stop conditions
 //  ... making sure these two wires don't get optimized away //  ... making sure these two wires don't get optimized away
行 65: 行 72:
 always @(negedge SCL or posedge start_or_stop) always @(negedge SCL or posedge start_or_stop)
 if(start_or_stop) incycle <= 1'b0; else if(~SDA) incycle <= 1'b1; if(start_or_stop) incycle <= 1'b0; else if(~SDA) incycle <= 1'b1;
-Now we are ready to count the I2C bits coming in+</​code>​ 
 + 
 +现在我们可以计数进来的I2C的位数。 
 + 
 +<code verilog>
 reg [3:0] bitcnt; ​ // counts the I2C bits from 7 downto 0, plus an ACK bit reg [3:0] bitcnt; ​ // counts the I2C bits from 7 downto 0, plus an ACK bit
 wire bit_DATA = ~bitcnt[3]; ​ // the DATA bits are the first 8 bits sent wire bit_DATA = ~bitcnt[3]; ​ // the DATA bits are the first 8 bits sent
行 87: 行 98:
     bitcnt <= bitcnt - 4'h1;     bitcnt <= bitcnt - 4'h1;
 end end
-and detect if the I2C address matches our own+</​code>​ 
 + 
 +并且检测I2C的地址是否匹配 
 + 
 +<code verilog>
 wire adr_phase = ~data_phase;​ wire adr_phase = ~data_phase;​
 reg adr_match, op_read, got_ACK; reg adr_match, op_read, got_ACK;
行 117: 行 132:
     if(adr_match & bit_DATA & data_phase & op_write) mem[bitcnt] <= SDAr;  // memory write     if(adr_match & bit_DATA & data_phase & op_write) mem[bitcnt] <= SDAr;  // memory write
 end end
-and drive the SDA line when necessary.+</​code>​ 
 + 
 +如有需要驱动=SDA信号线 
 + 
 +<code verilog>​ 
 wire mem_bit_low = ~mem[bitcnt[2:​0]];​ wire mem_bit_low = ~mem[bitcnt[2:​0]];​
 wire SDA_assert_low = adr_match & bit_DATA & data_phase & op_read & mem_bit_low & got_ACK; wire SDA_assert_low = adr_match & bit_DATA & data_phase & op_read & mem_bit_low & got_ACK;
行 126: 行 146:
 assign IOout = mem; assign IOout = mem;
 endmodule endmodule
-What's the result? +</code>
- +
-The code has been tested in multiple devices (Xilinx FPGA, Altera FPGA/CPLD), with an hard-macro I2C master (Dragon board). +
-The complete ​code is available here.+
  
-This code has two drawbacks:​ +结果如何?​
-The SCL signal is used as a clock in the FPGA/CPLD. The use of a Schmitt trigger on the SCL input pin is strongly recommended to avoid erratic behavior (without Schmitt trigger, any noise or ringing on the SCL line may introduce extra clock cycles, which would break the functionality). +
-The start and stop conditions detection logic uses a combinatorial feedback loop, which is not a recommended practice. Same thing on the "​incycle"​ signal that is used as asynchronous reset by the rest of the logic. These are the price to pay to avoid using an oversampling clock. +
-If you can live with these drawbacks, you get a very compact I2C slave design. +
-Otherwise, use an external clock to oversample SDA and SCL (method 2). This way, glitches can be filtered out using digital filters, and the start and stop condition detected easily (at the price of a more complex design). +
-External contributions+
  
-Contributed by an fpga4fun ​readers..+此代码已经在Xilinx和Altera的多个器件上进行过测试,​能够同硬化的I2C主进行通信,在这里可以下载[[http://​www.fpga4fun.com/​files/​I2Cslave1.zip|完整的代码]]
-I2C simulation in Verilog +
-I2C slave in VHDL+
  
-  +不过此代码有两个缺点::​ 
-====== I2C从模示例2 ======+  * 在FPGA/CPLD中SCL被用做了时钟信号,强烈建议在SCL输入端加入施密特触发器以避免错误的行为发生,如果不加施密特触发器,在SCL线上的任何噪声或振铃都会导致多余的时钟周期,导致功能失效 
 +  * “起始”和“终止”的条件检查逻辑采用的是组合反馈环路,这种方是不建议的。同样其它电路的异步复位也不建议采用“周期内信号”
  
-====== An example of I2C master ======+如果你能够容忍这些缺点,这应该是I2C从模式非常简洁的设计,否则你只能用外部时钟对SDA和SCL进行过取样,通过数字滤波器将毛刺给滤除掉,“起始”和“终止”的检测也变得比较容易,当然代价就是设计变得更复杂。
  
-====== A logic analyzer, to capture live I2C transaction and spy on the bus ====== 
-  
  
-...not ready yet+### 相关设计资源参考
  
-====== 资源链接 ====== +  ​* [I2C规范](http://​www.nxp.com/​documents/​user_manual/​UM10204.pdf)
-  ​* [[http://​www.nxp.com/​documents/​user_manual/​UM10204.pdf|I2C规范]]+  * Philips多方面深度讨论I2C的[应用指南](http://​www.nxp.com/​documents/​application_note/​AN10216.pdf) 
-  * Philips多方面深度讨论I2C的[[http://​www.nxp.com/​documents/​application_note/​AN10216.pdf|应用指南]] +  * [I2C常见问题](http://​www.esacademy.com/​faq/​i2c/​) 
-  * [[http://​www.esacademy.com/​faq/​i2c/​|I2C常见问题]] +  * [关于I2C和SMBus区别的文章](http://​www.totalphase.com/​support/​kb/​10040/​)(SMBus是由Intel公司开发的,基本跟I2C兼容) 
-  * [[http://​www.totalphase.com/​support/​kb/​10040/​|关于I2C和SMBus区别的文章]](SMBus是由Intel公司开发的,基本跟I2C兼容)+  * 苏老师公众号文章 - [几种最常用的串行数据传输总线(2)-I2C](https://​mp.weixin.qq.com/​s/​UVlecH-zBVG5Ug4Bx6TVeQ) 
 +  * Lattice Semi的[I2C Master](http://​www.latticesemi.com/​en/​Products/​DesignSoftwareAndIP/​IntellectualProperty/​ReferenceDesigns/​ReferenceDesigns02/​I2CBusMaster)使用说明,及IP参考代码下载 
 +  * Lattice Semi的[支持Wisbone总线的I2C Master](http://​www.latticesemi.com/​en/​Products/​DesignSoftwareAndIP/​IntellectualProperty/​ReferenceDesigns/​ReferenceDesigns02/​I2CMasterWISHBONECompatible)使用说明,及IP参考代码下载 
 +  * Lattice Semi的[I2C总线控制器](http://​www.latticesemi.com/​en/​Products/​DesignSoftwareAndIP/​IntellectualProperty/​ReferenceDesigns/​ReferenceDesigns02/​I2CBusControllerforSerialEEPROM)使用说明,及IP参考代码下载 
 +  * Lattice Semi的[I2C主控制器](http://​www.latticesemi.com/​en/​Products/​DesignSoftwareAndIP/​IntellectualProperty/​ReferenceDesigns/​ReferenceDesigns02/​I2CMasterController)使用说明,及IP参考代码下载 
 +  * Lattice Semi的[用于嵌入式功能块中的I2C从设备](http://​www.latticesemi.com/​en/​Products/​DesignSoftwareAndIP/​IntellectualProperty/​ReferenceDesigns/​ReferenceDesigns02/​I2CSlavePeripheralusingEmbeddedFunctionBlock)使用说明,及IP参考代码下载 
 +  * Lattice Semi的[I2C从到SPI主的桥接](http://​www.latticesemi.com/​en/​Products/​DesignSoftwareAndIP/​IntellectualProperty/​ReferenceDesigns/​ReferenceDesigns02/​I2CSlavetoSPIMasterBridge)使用说明,及IP参考代码下载 
 +  * FPGA4FUN上的[关于I2C的介绍及相应的Verilog代码资源](https://​www.fpga4fun.com/​I2C.html) 
 +  * FPGA4FUN上的I2C从设备的[[http://​www.fpga4fun.com/​files/​I2Cslave1.zip|完整的代码]]