协议理解之I2C协议

原创 2016年06月01日 12:14:59

I2C总线的特征

协议我们参考|EEPROM 24C64的DataSheet

  • 硬件特征:
    SDA:串行数据线
    SCL:串行时钟线
    每个连接到总线上的设备都有唯一的地址

  • 速度
    标准模式下可以达到100kbit/s
    快速模式下可以达到400kbit/s
    高速模式下可以达到3.4Mbit/s

  • I2C总线术语
    发送器: 发送数据到总线的器件
    接收器: 从总线接收数据的器件
    主机: 初始化发送 产生时钟信号和终止发送的器件
    从机: 被主机寻址的器件
    多主机: 同时有多于一个主机尝试控制总线 但不破坏报文
    仲裁: 是一个在有多个主机同时尝试控制总线 但只允许其中一个控制总线并使报文不被破坏
    的过程
    同步: 两个或多个器件同步时钟信号的过程

协议格式

  • 开始位
    在 SCL 线是高电平时 SDA 线从高电平向低电平切换
    这里写图片描述

  • 停止位
    当 SCL 是高电平时 SDA 线由低电平向高电平切换
    这里写图片描述

  • 数据位
    发送到 SDA 线上的每个字节必须为 8 位,数据的高位在前(先发数据高位);
    这里写图片描述

代码范例

void i2c_delay(void)
{
    unsigned char i;
    for(i=0;i<10;i++);
}

void i2c_start(void)
{
    I2C_SDA = 1;
    I2C_CLK = 1;
    i2c_delay();
    I2C_SDA = 0;
    i2c_delay();
    I2C_CLK = 0;
}

void i2c_stop(void)
{
    I2C_SDA = 0;
    I2C_CLK = 0;
    i2c_delay();
    I2C_CLK = 1;
    i2c_delay();
    I2C_SDA = 1;
}

unsigned char read_i2c_onebyte(bit ack_or_nak)
{
    unsigned char read_data, i;
    SET_SDA_INPUTMODE;
    read_data = 0x00;
    for(i=0;i<7;i++)
    {
        I2C_CLK = 1;
        if(I2C_SDA)
            read_data |= 0x01;
        i2c_delay();
        I2C_CLK = 0;
        read_data <<= 1;
        i2c_delay();
    }
    I2C_CLK = 1;
    if(I2C_SDA)
        read_data |= 0x01;
    i2c_delay();
    I2C_CLK = 0;

    SET_SDA_OUTPUTMODE;     //SDA output

    i2c_delay();
    if(ack_or_nak)
        I2C_SDA = 1;
    else
        I2C_SDA = 0;
    I2C_CLK = 1;
    i2c_delay();
    I2C_CLK = 0;

    i2c_delay();
    I2C_SDA = 0;
    return read_data;
}

bit write_i2c_onebyte(char w_buf)
{
    unsigned char i;
    bit ack_or_nak;
    for(i=0;i<8;i++)
    {
        if(w_buf&0x80)
            I2C_SDA = 1;
        else
            I2C_SDA = 0;
        i2c_delay();
        I2C_CLK = 1;
        i2c_delay();
        I2C_CLK = 0;
        w_buf <<= 1;
    }
    SET_SDA_INPUTMODE;
    i2c_delay();
    I2C_CLK = 1;
    i2c_delay();
    ack_or_nak = 0;
    if(I2C_SDA)
        ack_or_nak = 1;
    I2C_CLK = 0;
    I2C_SDA = 0;
    SET_SDA_OUTPUTMODE;     //SDA output

    return ack_or_nak;
}

写操作

  • 设备地址
    这里写图片描述

  • 字节写操作
    这里写图片描述

时序分析:
1、开始信号;
2、写从设备地址,地址最低位R/W=0,表示为写操作,从设备收到数据后会自动返回ACK,判断设备存不存在可以根据ACK信号;
3、写存储地址高八位(写完地址后从设备会返回ACK),(有的设备是10bit的地址,24C64是8bit地址)
4、写存储地址低八位(写完地址后从设备会返回ACK)
5、写8bit数据(1Byte)
6、写停止位

void 24cxx_write(unsigned short addr, unsigned char dat)
{
    i2c_start();
    write_i2c_onebyte((EEPROM_ADDR<<1)+WRITE_CMD);
    write_i2c_onebyte(addr>>8);
    write_i2c_onebyte(addr);    
    write_i2c_onebyte(dat);
    i2c_stop();
    delay_ms(12);
}
  • 页写操作
    这里写图片描述
    时序分析:
    1、开始信号;
    2、写从设备地址,地址最低位R/W=0,表示为写操作,从设备收到数据后会自动返回ACK,判断设备存不存在可以根据ACK信号;
    3、写存储地址高八位(写完地址后从设备会返回ACK),(有的设备是10bit的地址,24C64是8bit地址)
    4、写存储地址低八位(写完地址后从设备会返回ACK)
    5、写停止位
    7、写开始位
    8、写从设备地址
    6、写停止位
int 24cxx_write_page(unsigned short addr, unsigned short len, unsigned char* idata buf)
{
    i2c_start();
    write_i2c_onebyte((EEPROM_ADDR<<1)+WRITE_CMD);
    write_i2c_onebyte(addr>>8);
    write_i2c_onebyte(addr);

    while(len--) {
        write_i2c_onebyte(*buf++);
    }
    i2c_stop();
    delay_ms(12);
    return 0;
}

//用于拷贝芯片的数据
int 24cxx_write_buf(unsigned short addr, unsigned short num, unsigned char* idata buf)
{
    int stat;
    unsigned char NumOfPage = 0, NumOfSingle = 0;

    if (addr % _24CXX_PageSize) //位一页空间的大小
        NumOfSingle = _24CXX_PageSize - addr%_24CXX_PageSize;
    else 
        NumOfSingle = 0;
    if (num <= NumOfSingle)     
        NumOfSingle = num;  
    else 
        NumOfPage =  (num - NumOfSingle + (_24CXX_PageSize - 1)) / _24CXX_PageSize;

    if (NumOfSingle) {
        if (0!=(stat=_24cxx_write_page(addr, NumOfSingle, buf)))
            return stat;
        addr += NumOfSingle;
        buf += NumOfSingle;
        num  -= NumOfSingle;
    }
    while (NumOfPage--) {
        if (0!=(stat=_24cxx_write_page(addr, (num>=_24CXX_PageSize)?_24CXX_PageSize:num, buf)))
            return stat;
        addr += _24CXX_PageSize;
        buf += _24CXX_PageSize;
        num  -= _24CXX_PageSize;    
    }
    return 0;
}

读操作

这里写图片描述
- 随机读操作
时序分析:
1、开始信号;
2、写从设备地址,地址最低位R/W=1,表示为读操作,从设备收到数据后会自动返回ACK,判断设备存不存在可以根据ACK信号;
3、读存储地址高八位(写完地址后从设备会返回ACK),(有的设备是10bit的地址,24C64是8bit地址)
4、读存储地址低八位(写完地址后从设备会返回ACK)
5、写停止位
6、写开始信号
7、写从设备地址
8、读取数据,并告诉从设备这次不用回ACK
9、写停止位

unsigned char 24cxx_read(unsigned short addr)
{
    unsigned char tmp;
    i2c_start2();
    write_i2c_onebyte((EEPROM_ADDR<<1)+WRITE_CMD);
    write_i2c_onebyte(addr>>8);
    write_i2c_onebyte(addr);
    i2c_stop();

    i2c_start();
    write_i2c_onebyte((EEPROM_ADDR<<1)+READ_CMD);
    i2c_delay();
    tmp = read_i2c_onebyte(NAK_FLAG);
    i2c_stop();
    return tmp;
}   
  • 顺序读
    这里写图片描述
    时序分析:
    1、开始信号;
    2、写从设备地址,地址最低位R/W=1,表示为读操作,从设备收到数据后会自动返回ACK,判断设备存不存在可以根据ACK信号;
    3、读存储地址高八位(写完地址后从设备会返回ACK),(有的设备是10bit的地址,24C64是8bit地址)
    4、读存储地址低八位(写完地址后从设备会返回ACK)
    5、写停止位
    6、写开始信号
    7、写从设备地址
    8、读取数据,并告诉从设备这次不用回ACK
    9、写停止位
void _24cxx_read_buf(unsigned short addr, unsigned short len, unsigned char* idata buf)
{
    i2c_start();
    write_i2c_onebyte((EEPROM_ADDR<<1)+WRITE_CMD);
    write_i2c_onebyte(addr>>8);
    write_i2c_onebyte(addr);
    i2c_stop2();
    i2c_start2();
    write_i2c_onebyte((EEPROM_ADDR<<1)+READ_CMD);
    while(--len) {
        i2c_delay();
        *buf++ = read_i2c_onebyte(ACK_FLAG);
    }
    i2c_delay();
    *buf = read_i2c_onebyte(NAK_FLAG);
    i2c_stop();
}

附图:

I2C协议图片逻辑分析
临时保存I2C逻辑采样图片,MSB在前

IIC详解

本文的程序是主控室STM32F107,读取的芯片是PCF8563。各种宏定义和文件会在末尾说明。 1、IIC的定义: IIC 即Inter-Integrated Circuit(集成电路总线),这种...
  • Firefly_cjd
  • Firefly_cjd
  • 2016年07月15日 21:25
  • 13166

i2c信号的ACK与NACK

我们平时在调试I2C的时候可能很少去关注NACK信号,只知道如果Master发送数据,MSB先发,LSB后发,连续发送一个字节(8个bit),之后Slave会回复一个ACK信号,但是有时I2C sla...
  • luckywang1103
  • luckywang1103
  • 2013年12月25日 14:11
  • 26766

i2c 相关知识总结(转)

一. 技术性能:     工作速率有100K和400K两种;     支持多机通讯;     支持多主控模块,但同一时刻只允许有一个主控;           由数据线SDA和时钟SCL构成的...
  • hygzxf
  • hygzxf
  • 2013年12月19日 15:41
  • 36749

I2C总线解析

注:本文来源http://blog.csdn.net/zmq5411/article/details/6085740,在此感谢原作者!   IIC总线 一般串行数据通讯都有时钟和数据之分,有异步...
  • dddd0216
  • dddd0216
  • 2016年03月15日 14:18
  • 2897

很清晰的解读i2c协议

很清晰的解读i2c协议。 I2C协议:2条双向串行线,一条数据线SDA,一条时钟线SCL。 SDA传输数据是大端传输,每次传输8bit,即一字节。 支持多主控(multimastering...
  • lingfeng5
  • lingfeng5
  • 2017年06月17日 02:15
  • 2199

EEPROM通过IIC协议进行读写操作

EEPROM通过IIC协议可以进行快速简单的读写操作: 写操作: 1,简单随机写入一个8字节的数据 2,一次写入一页数据,而不需要再次写入从机地址和单元地址,一页数据为32个字节。 每次页操作之间要间...
  • Brian_H
  • Brian_H
  • 2016年11月24日 09:33
  • 1074

I2C从机挂死分析和解决方法

I2C几乎是嵌入系统中最为通用串行总线,MCU周边的各种器件只要对速度要求不高都可以使用。优点是兼容性好(几乎所有MCU都有I2C主机控制器,没有也可以用IO模拟),管脚占用少,芯片实现简单。I2C协...
  • Stephen_yu
  • Stephen_yu
  • 2017年04月07日 15:42
  • 1356

C/C++语言,对MSB、LSB的读/取处理

1. 做硬件的都知道,串口是LSB优先,I2C、1553B是MSB优先,这里的MSB、LSB指的是二进制位的位置,区别于【字节序】(通信中,先发送低字节,还是高字节的问题,那叫大端big-endian...
  • dijkstar
  • dijkstar
  • 2015年09月27日 11:56
  • 2677

个人总结之I2C总线协议

1.what is I2C? 简单讲就是用来传输数据的两根线:一根数据线(SDA)一根时钟线(SCL) 2.I2C怎么传输的? (1)基本过程:      1.主机发出开始信号      2...
  • black_yu
  • black_yu
  • 2016年07月16日 20:03
  • 3336

I2C总线协议

1.I2C协议    2条双向串行线,一条数据线SDA,一条时钟线SCL。    SDA传输数据是大端传输,每次传输8bit,即一字节。    支持多主控(multimastering),任何...
  • subkiller
  • subkiller
  • 2011年10月09日 11:04
  • 87971
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:协议理解之I2C协议
举报原因:
原因补充:

(最多只允许输入30个字)