驱动学习-I2C协议

**

I2c协议(Inter-Integrated Circuit)

**

1、I2C简介

I2C 是一种串行通信总线,用于连接微控制器及其外围设备,实现主控制器和从器件间的主从双向通信,是一种同步半双工通信(两端时钟频率一致,双向通信,但不能同时进行数据收发)。
I2C是 NXP 公司设计的, I2C 使用两条线在主控制器和从机之间进行数据通信。一条是 SCL(串行时钟线),另外一条是 SDA(串行数据线),这两条数据线需要接上拉电阻,一般为4.7k,总线空闲的时候 SCL 和 SDA 处于高电平。

2.I2C协议

I2C 是支持多从机的,也就是一个 I2C 控制器下可以挂多个 I2C 从设备,为确保传输过程的指向准确性,每个接到I2C总线上的器件都有唯一的地址(7位从器件专用地址码),可实现制定从机的定向传输与群发传输。
在这里插入图片描述

3.I2C协议标准代码

3.1 起止信号

起始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。

void I2C_Start(void)
{
    I2C_SCL_High();     //SCL=1
    I2C_SDA_High();     //SDA=1
    I2C_Delay();
    I2C_SDA_Low();
    I2C_Delay();
    
}

在这里插入图片描述

停止信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。

void I2C_Stop(void)
{
    I2C_SCL_High(); //SCL=1
    I2C_SDA_Low();//SDA=0;
    I2C_Delay();
    I2C_SDA_High();
    I2C_Delay();
}

在这里插入图片描述

3.2 数据传输

I2C 总线在数据传输的时候要保证在 SCL 高电平期间, SDA 上的数据稳定,因此 SDA 上的数据变化只能在 SCL 低电平期间发生,如下图所示:
在这里插入图片描述

CPU向I2C总线设备发送一个字节(8bit)数据:

cu8 I2C_SendByte(uint8_t Byte)
{
    uint8_t i;
 
    /* 先发送高位字节 */
    for(i = 0 ; i < 8 ; i++)
    {
        if(Byte & 0x80)
        {
            I2C_SDA_High();
        }
        else
        {
            I2C_SDA_Low();
        }
        I2C_Delay();
        I2C_SCL_High();
        I2C_Delay();
        I2C_SCL_Low();
        I2C_Delay();
        if(i == 7)
        {
            I2C_SDA_High();                     /* 释放SDA总线 */
        }
        Byte <<= 1;                             /* 左移一位  */
 
        I2C_Delay();
    }
} 

CPU从I2C总线设备上读取一个字节(8bit数据):

u8 I2C_ReadByte(void)
{
    uint8_t i;
    uint8_t value;
 
    /* 先读取最高位即bit7 */
    value = 0;
    for(i = 0 ; i < 8 ; i++)
    {
        value <<= 1;
        I2C_SCL_High();
        I2C_Delay();
        if(I2C_SDA_READ())
        {
            value++;
        }
        I2C_SCL_Low();
        I2C_Delay();
    }
 
    return value;
}

3.3应答信号

IIC 总线协议规定,每传送一个字节数据后(8bit),都要有一个应答信号以确定数据传送是否被对方收到。即一个字节传输的8个时钟过后的第9个时钟期间,接收器必须回一个ACK应答信号给发送器,这样才能进行数据传输。
应答信号由接受设备产生,在SCL为高电平期间,接受设备将SDA拉低为低电平,表示数据传输正确,产生应答(ACK),SDA拉高则表示数据传输失败,产生非应答位(NACK)

(1)CPU产生一个ACK信号

void I2C_Ack(void)
{
    I2C_SDA_Low();
    I2C_Delay();
    I2C_SCL_High();
    I2C_Delay();
    I2C_SCL_Low();
    I2C_Delay();
 
    I2C_SDA_High();
}

(2)CPU产生一个非ACK信号

void I2C_NoAck(void)
{
    I2C_SDA_High();
    I2C_Delay();
    I2C_SCL_High();
    I2C_Delay();
    I2C_SCL_Low();
    I2C_Delay();
}

(3)CPU产生一个时钟,并读取器件的ACK应答信号

uint8_t I2C_WaitToAck(void)
{
    uint8_t redata;
 
    I2C_SDA_High();
    I2C_Delay();
    I2C_SCL_High();
    I2C_Delay();
 
    if(I2C_SDA_READ())
    {
        redata = 1;
    }
    else
    {
        redata = 0;
    }
    I2C_SCL_Low();
    I2C_Delay();
 
    return redata;
}   

4.I2C通信时序图解析

I2C总线进行数据传送时,SCL时钟信号为高电平期间,SDA数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 当一个字节按数据位从高位到低位的顺序传输完后,紧接着从机将拉低SDA线,回传给主设备一个应答位ACK, 此时才认为一个字节真正的被传输完成 ,如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。

4.1 I2C写时序

在这里插入图片描述

结合I2C总线协议的知识,我们可以知道触摸屏驱动的I2C写数据由一下10个步骤组成。
  第一步,发送一个起始信号。
  第二步,发送7bit从机地址,即TP的地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。
  第三步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
  第四步,发送寄存器地址,8bit数据。
  第五步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
  第六步,发送一个数据,8bit数据。
  第七步,产生一个ACK应答信号,此应答信号为从机器件产生的应答信号。
  第八步,发送一个CRC校验码,此CRC校验值为2、4、6步数据产生的校验码。
  第九步,既可以发送一个应答信号,也可以发送一个无应答信号,均有从机器件产生。
  第十步,发送一个停止信号。

接下来,按照以上是个步骤,可以写出TP驱动的i2c写数据的函数。代码如下:

u8 I2C_WriteBytes(void)
{
    I2C_Start();                    //1
 
    I2C_SendByte(Slaver_Addr | 0);  //2
    I2C_WaitToAck();                //3
 
    I2C_SendByte(Reg_Addr);         //4
    I2C_WaitToAck();                //5
 
    I2C_SendByte(data);             //6
    I2C_WaitToAck();                //7
 
    I2C_SendByte(crc);              //8
    I2C_WaitToAck();                //9
 
    I2C_Stop();                     //10
}

4.2 I2C读时序

在这里插入图片描述

通过分解后的时序图,可以看到触摸屏驱动的读数据由以下13个步骤组成。
  第一步,发送一个起始信号。
  第二步,发送7bit从机地址,即驱动的地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。
  第三步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
  第四步,发送寄存器地址。
  第五步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
  第六步,再次发送一个骑士信号。
  第七步,发送7bit从机地址,即驱动的地址。此处需要注意,发送数据时,无法发送7bit数据,此处发送了7bit地址+1bit读写选择位,即发送7bit+r/w。最低位为1表示读,为0表示写。
  第八步,产生一个ACK应答信号,此应答信号为从机器件产生的应答。
  第九步,读取一个字节(8bit)的数据。
  第十步,产生一个ACK应答信号,此应答信号为CPU产生。
  第十一步,读取一个CRC校验码。
  第十二步,产生一个NACK信号。此无应答信号由CPU产生。
  第十三步,产生一个停止信号。

接下来,由以上分析步骤,可以写出驱动的I2C读数据代码。如下所示:

u8 I2C_ReadBytes(void)
{
    u8 data;
    u8 crc;
 
    I2C_Start();                    //1
 
    I2C_SendByte(Slaver_Addr | 0);  //2
    I2C_WaitToAck();                //3
 
    I2C_SendByte(Reg_Addr);         //4
    I2C_WaitToAck();                //5
 
    I2C_Start();                   //6
 
    I2C_SendByte(Slaver_Addr | 1);  //7 1-读
    I2C_WaitToAck();                //8
 
    data=I2C_ReadByte();            //9
 
    I2C_Ack();                      //10
 
    crc=I2C_ReadByte();             //11
 
    I2C_NoAck();                    //12
 
    I2C_Stop();                     //13
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在芯片之间传输数据。它由Philips公司(现在的NXP公司)开发,用于连接微控制器、传感器、存储器等设备。I2C总线由两条线组成:数据线(SDA)和时钟线(SCL)。SDA线传输数据,而SCL线传输时钟信号,控制数据的传输速率和时序。 I2C协议使用地址和数据来传输信息。每个设备都有一个独特的地址,用于在总线上识别该设备。当主设备需要与从设备通信时,它首先发送一个起始信号,并将从设备地址发送到总线上。从设备检测到其地址后,它会回复一个确认信号,然后开始传输数据。主设备通过发送数据来控制从设备,从设备通过回复数据来向主设备提供信息。 学习I2C的关键是理解I2C总线的工作原理和协议规范。可以通过以下步骤来学习I2C: 1.了解I2C总线的基本原理和工作方式,包括总线拓扑结构、传输速率、起始信号和停止信号等。 2.学习I2C协议规范,包括设备地址、读写操作、数据传输格式等。 3.了解I2C总线的硬件支持,包括I2C控制器、I2C接口芯片等。 4.使用I2C总线驱动程序进行编程,掌握I2C读写操作、数据传输、错误处理等。 5.实验和测试I2C设备,包括传感器、存储器、显示器等,以便更好地理解I2C协议和总线工作。 总之,学习I2C需要理解其工作原理和协议规范,并进行实验和测试以掌握相关技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值