IIC协议

I2C(inter-integrated Circuit):集成电路总线,由飞利浦公司在上个世纪80年代所设计的,是一种两线式串行通信总线,使用多主从架构,用作为不同器件之间的通讯。
主机:发送命令的设备成为主机。
从机:接受命令并响应命令的设备成为从机。

设计模式
I2C只使用两条双向漏级开路(数据线SDA和时钟线SCL),iic设备通过这两条总线连接到处理器的IIC总线控制器上。连接到总线的接口数量只由总线电容是 400pF 的限制决定。
PS:漏级开路(Open Drain),是一个NPN型三极管,并不输出某一特定电压值或电流值。根据三极管基极所接的集成电路来决定(三极管发射极接地),通过三极管集电极,使其开路而输出。(后续再补充这方面内容)

IIC特点

  1. IIC支持不同的模式:快速模式(400 kbit/s)、快速+模式(1 Mbit/s)高速模式(3.4 Mbit/s)
    2.每一个设备都可以通过唯一的设备地址进行单独访问,并且I2C 总线协议不需要地址译码器。
  2. 它是一个多主机系统,在一条总线上可以同时有多个主机存在。同一时间只能有一个主机占用总线(仲裁,通过冲突检测和延时等待,可以保证数据不被破坏。
  3. 只要求两条总线线路:SDA和SCL。
  4. 片上的滤波器可以滤去总线数据线上的毛刺波 保证数据完整

IIC总线的信号类型
开始信号S:SCL为高点平时,SDA由高电平向低电平跳变。
结束信号P:SCL为高点平时,SDA由低电平向高电平跳变。
响应信号ACK:从机接收到8位数据后,在第9个时钟周期拉低SDA电平,表示以及收到数据。

从图中可知:空闲时间时,两条线都是高电平数据的变化都是在SCL为低电平时SDA进行改变,并且在SCL为高电平时被读取到数据(此时SDA需要保持电平)。当SCL为高电平时,SDA改变会产生控制信号。
维基:

  1. Data transfer is initiated with a start condition (S) signaled by SDA being pulled low while SCL stays high
  2. SCL is pulled low, and SDA sets the first data bit level while keeping SCL low (during blue bar time).
  3. The data are sampled (received) when SCL rises for the first bit (B1). For a bit to be valid, SDA must not change between a rising edge of SCL and the subsequent falling edge (the entire green bar time).
  4. This process repeats, SDA transitioning while SCL is low, and the data being read while SCL is high (B2, ...Bn)
  5. The final bit is followed by a clock pulse, during which SDA is pulled low in preparation for the stop bit.
  6. A stop condition (P) is signaled when SCL rises, followed by SDA rising.

IIC发送数据过程
数据传输的格式:
发送的数据必须是一个字节,但是字节的数量是不受限制的,每个字节后必须跟一个响应位 ,首先传输的是数据的最高位 MSB。
如果从机要完成一些其他功能后 ,例如一个内部中断服务程序才能接收或发送下一个完整的数据字节 ,可以使时钟线 SCL 保持低电平迫使主机进入等待状态, 当从机准备好接收下一个数据字节并释放时钟线 SCL 后 数据传输继续。
响应:
当从机不能响应从机地址时 例如它正在执行一些实时函数不能接收或发送 从机必须使数据线保持
高电平 主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输
相关的响应时钟脉冲由主机产生 在响应的时钟脉冲期间 发送器释放 SDA 线
数据传输过程:
主机通过SDA向从机发送数据,总线空闲时SDA和SCL都处于高电平。

  1. 当主机检测到总线空闲时,主机发出开始信号S
  2. 主机发送8位数据,前7位表示从机地址,第8位表示数据的传输方向。(0表示向从机发送数据)。
  3. 被选中的从机发出响应信号ACK
  4. 从机传输一系列的字节和响应位
  5. 主机接受数据并发送停止符。

地址:一个固定和可编程的部分组成,如有3位可编程的地址位,则总线上一共可以连接8个相同的器件。

仲裁:
所有主机在 SCL 线上产生它们自己的时钟来传输 I2C 总线上的报文,数据只在时钟的高电平周期有效。如果两个或多个主机都向总线上发送启动信号并开始传送数据,这样就形成了冲突。 需要仲裁。
I2C总线上仲裁分为两部分:SCL线的同步和SDA线的仲裁。I2C总线的仲裁机制

  1. SCL线同步
    SCL同步是由于总线具有线“与”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平。


    时钟同步
  2. SDA仲裁
    SDA线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。
  3. 仲裁过程
  • 主节点1、2同时发送起始信号时,两个主节点都发送了高电平信号。这时总线上呈现的信号为高电平,两个主节点都检测到总线上的信号与自己发送的信号相同,继续发送数据。
  • 第2个时钟周期,2个主节点都发送低电平信号,在总线上呈现的信号为低电平,仍继续发送数据。
  • 在第3个时钟周期,主节点1发送高电平信号,而主节点2发送低电平信号。根据总线的线“与”的逻辑功能,总线上的信号为低电平,这时主节点1检测到总线上的数据和自己所发送的数据不一样,就断开数据的输出级,转为从机接收状态。
  • 这样主节点2就赢得了总线,而且数据没有丢失,即总线的数据与主节点2所发送的数据一样,而主节点1在转为从节点后继续接收数据,同样也没有丢掉SDA线上的数据。因此在仲裁过程中数据没有丢失。


仲裁特殊情况:

  • 重复起始条件和数据位。
    数据传输一般由主机产生的停止位 P 终止, 但是如果主机仍希望在总线上通讯,它可以产生重复起始条件和寻址另一个从机,而不是首先产生一个停止条件。
  • 停止条件和数据位。
  • 重复起始条件和停止条件。

从机不被卷入仲裁过程。

维基:example of IIC code

// Hardware-specific support functions that MUST be customized:
//It illustrates all of the I2C features described before (clock stretching, arbitration, start/stop bit, ack/nack)
//ACK:Acknowledgement,它是一种正向反馈,接收方收到数据后回复消息告知发送方。 NACK:Negative //Acknowledgement,则是一种负向反馈,接收方只有在没有收到数据的时候才通知发送方。

#define I2CSPEED 100
void I2C_delay(void);
bool read_SCL(void);  // Return current level of SCL line, 0 or 1
bool read_SDA(void);  // Return current level of SDA line, 0 or 1
void set_SCL(void);   // Do not drive SCL (set pin high-impedance)
void clear_SCL(void); // Actively drive SCL signal low
void set_SDA(void);   // Do not drive SDA (set pin high-impedance阻抗)
void clear_SDA(void); // Actively drive SDA signal low
void arbitration_lost(void);

bool started = false; // global data

  //开始信号S:SCL为高点平时,SDA由高电平向低电平跳变。
void i2c_start_cond(void) {
  if (started) { 
    // if started, do a restart condition
    set_SDA();// set SDA to 1
    I2C_delay();
    set_SCL();// Do not drive SCL (set pin high-impedance)
    // read_SCL() ,Return current level of SCL line, 0 or 1
    while (read_SCL() == 0) { // Clock stretching
    //PS:clock stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行
      // You should add timeout to this loop  
    }

    // Repeated start setup time, minimum 4.7us
    I2C_delay();
  }

  if (read_SDA() == 0) {
    arbitration_lost();
  }
  // SCL is high, set SDA from 1 to 0.
  // SCL为高,SDA高到低时为开始启动
  //SCL为低时,SDA变化为传输数据。
  clear_SDA();
  I2C_delay();
  clear_SCL();
  started = true;
}

 //结束信号P:SCL为高点平时,SDA由低电平向高电平跳变。
void i2c_stop_cond(void) {
  // set SDA to 0
  clear_SDA();
  I2C_delay();

  set_SCL();
  // Clock stretching
  while (read_SCL() == 0) {
    // add timeout to this loop.
  }

  // Stop bit setup time, minimum 4us
  I2C_delay();

  // SCL is high, set SDA from 0 to 1
  set_SDA();
  I2C_delay();

  if (read_SDA() == 0) {
    arbitration_lost();
  }

  started = false;
}

//数据的变化都是在SCL为低电平时SDA进行改变,并且在SCL为高电平时被读取到数据
// Write a bit to I2C bus
void i2c_write_bit(bool bit) {
  if (bit) {
    set_SDA();
  } else {
    clear_SDA();
  }

  // SDA change propagation delay
  I2C_delay();

  // Set SCL high to indicate a new valid SDA value is available
  set_SCL();

  // Wait for SDA value to be read by slave, minimum of 4us for standard mode
  I2C_delay();

  while (read_SCL() == 0) { // Clock stretching
    // You should add timeout to this loop
  }

  // SCL is high, now data is valid
  // If SDA is high, check that nobody else is driving SDA
  if (bit && (read_SDA() == 0)) {
    arbitration_lost();
  }

  // Clear the SCL to low in preparation for next change
  clear_SCL();
}

// Read a bit from I2C bus
bool i2c_read_bit(void) {
  bool bit;

  // Let the slave drive data
  set_SDA();

  // Wait for SDA value to be written by slave, minimum of 4us for standard mode
  I2C_delay();

  // Set SCL high to indicate a new valid SDA value is available
  set_SCL();

  while (read_SCL() == 0) { // Clock stretching
    // You should add timeout to this loop
  }

  // Wait for SDA value to be written by slave, minimum of 4us for standard mode
  I2C_delay();

  // SCL is high, read out bit
  bit = read_SDA();

  // Set SCL low in preparation for next operation
  clear_SCL();

  return bit;
}

// Write a byte to I2C bus. Return 0 if ack by the slave.
bool i2c_write_byte(bool send_start,
                    bool send_stop,
                    unsigned char byte) {
  unsigned bit;
  bool     nack;

  if (send_start) {
    i2c_start_cond();
  }

  for (bit = 0; bit < 8; ++bit) {
    i2c_write_bit((byte & 0x80) != 0);
    byte <<= 1;
  }

  nack = i2c_read_bit();

  if (send_stop) {
    i2c_stop_cond();
  }

  return nack;
}

// Read a byte from I2C bus
unsigned char i2c_read_byte(bool nack, bool send_stop) {
  unsigned char byte = 0;
  unsigned char bit;

  for (bit = 0; bit < 8; ++bit) {
    byte = (byte << 1) | i2c_read_bit();
  }

  i2c_write_bit(nack);

  if (send_stop) {
    i2c_stop_cond();
  }

  return byte;
}

void I2C_delay(void) { 
  volatile int v;
  int i;

  for (i = 0; i < I2CSPEED / 2; ++i) {
    v;
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360

推荐阅读更多精彩内容