打印

I2C协议的科学化学习方法

[复制链接]
167|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaoyang9992006|  楼主 | 2023-5-25 22:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在集成电路(IC)之间进行短距离数据传输。它是由Philips(现在的NXP半导体)在上世纪80年代开发的,并成为一种广泛应用的通信协议。

I2C协议主要用于连接微控制器、传感器、存储器和其他外围设备,以实现简单而可靠的通信。它使用两根信号线:串行数据线(SDA)和串行时钟线(SCL)。通过这两根线,多个设备可以同时连接到同一条总线上。
以下是I2C协议的一些关键特点:
  • 简单和双向:I2C使用主从结构,其中一个设备充当主设备,负责控制通信的时序和协调数据传输,其他设备则充当从设备,按照主设备的指示进行操作。双向通信意味着数据可以在主设备和从设备之间双向传输。
  • 地址寻址:每个从设备在总线上都有一个唯一的7位或10位地址,用于主设备选择要与之通信的从设备。7位地址模式支持最多128个从设备,10位地址模式支持最多1024个从设备。
  • 速度可变:I2C协议支持多种传输速率,通常有标准模式(100 kbit/s)、快速模式(400 kbit/s)和高速模式(3.4 Mbit/s)。速率的选择由主设备决定,所有从设备都必须支持所选择的速率。
  • 起始和停止条件:通信的开始由主设备发出起始条件(Start),而结束由主设备发出停止条件(Stop)。起始条件和停止条件的产生使得每个通信传输都有明确的开始和结束,确保数据的完整性。
  • 硬件传输:I2C协议通过改变SDA和SCL线上的电压来传输数据。SDA线上的数据传输是基于时钟信号的变化,而SCL线上的时钟信号由主设备生成。

I2C协议在许多应用中得到广泛应用,特别是在连接微控制器和外围设备的场景中。它提供了一种简单可靠的通信方式,具有较低的成本和较少的引脚需求。由于其流行和广泛支持,许多芯片和模块都集成了I2C接口,使得设备之间的互联变得更加简单和灵活。
接下来用实例说明实现方式
/**********************************************
//IIC Start
时钟信号在高电平状态时候在数据线产生一个下降沿
**********************************************/
void IIC_Start()
{
        OLED_SCLK_Set() ;
        OLED_SDIN_Set();
        OLED_SDIN_Clr();
}

/**********************************************
//IIC Stop
时钟信号在高电平状态时候在数据线产生一个上升沿
**********************************************/
void IIC_Stop()
{
        OLED_SCLK_Set();
        OLED_SDIN_Clr();
        OLED_SDIN_Set();       
}
//这里就是跳过这个时钟周期,没有去读数据位有没有回来应答信号。
void IIC_Wait_Ack()
{
        OLED_SCLK_Set();
        OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
在时钟线为低电平的时候在数据线发送数据位,高位在前
在完成数据发送后要保持数据线为低电平
**********************************************/

void Write_IIC_Byte(unsigned char IIC_Byte)
{
        unsigned char i;
        unsigned char m,da;
        da=IIC_Byte;

        for(i=0;i<8;i++)               
        {
                m=da;
                OLED_SCLK_Clr();
                m=m&0x80;
               
                if(m==0x80)
                        OLED_SDIN_Set();
                else
                        OLED_SDIN_Clr();

                da=da<<1;

                OLED_SCLK_Set();
                }
        OLED_SCLK_Clr();
}
/**********************************************
// IIC Write Command
开始信号
前8位为:写7位地址,高位在前,并跟随1个读写位0,表示写入:0111 100 0
第9位应答,这里就是跳过一个时钟信号(拉高时钟,拉低时钟)
接下已一个字节发送0x00表示后面要写命令
接下来应答位,这里就是跳过一个时钟信号(拉高时钟,拉低时钟)
后面开始写入的数据作为命令,即将命令字节装载到这个发送字节的函数里发送出去
然后又是一个应答位,跳过一个时钟信号
之后发送停止指令。
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
        IIC_Start();
        Write_IIC_Byte(0x78);            //Slave address,SA0=0
        IIC_Wait_Ack();       
        Write_IIC_Byte(0x00);                        //write command
        IIC_Wait_Ack();       
        Write_IIC_Byte(IIC_Command);
        IIC_Wait_Ack();       
        IIC_Stop();
}
/**********************************************
// IIC Write Data
开始信号
前八位为:写7位地址,高位在前,并跟随1个读写位0,表示写入:0111 100 0
第9位应答,这里就是跳过一个时钟信号(拉高时钟,拉低时钟)
接下已一个字节发送0x40表示后面要写的是数据
接下来应答位,这里就是跳过一个时钟信号(拉高时钟,拉低时钟)
后面开始写入的数据作为数据,即将数据字节装载到这个发送字节的函数里发送出去
然后又是一个应答位,跳过一个时钟信号
之后发送停止指令。
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
        IIC_Start();
        Write_IIC_Byte(0x78);                        //D/C#=0; R/W#=0
        IIC_Wait_Ack();       
        Write_IIC_Byte(0x40);                        //write data
        IIC_Wait_Ack();       
        Write_IIC_Byte(IIC_Data);
        IIC_Wait_Ack();       
        IIC_Stop();
}




使用特权

评论回复

相关帖子

沙发
gaoyang9992006|  楼主 | 2023-5-26 21:29 | 只看该作者
新写的总结代码,强化了应答响应
/*
I2C Start
起始信号:时钟信号在高电平状态时候,数据线产生一个下降沿表示开始信号
*/
void I2C_Start()
{
        IO_SCL_SET_H();
       
        IO_SDA_SET_H();
        IO_SDA_SET_L();       
}

/*
I2C Stop
停止信号:时钟信号在高电平状态时候,数据线产生一个上升沿表示停止
*/
void I2C_Stop()
{
        IO_SCL_SET_H();
       
        IO_SDA_SET_L();
        IO_SDA_SET_H();       
}

/*
I2C ACK/NACK
应答信号:第九个时钟周期的时钟高电平时候读取SDA数据,如果SDA此时为0,则表示应答,如果为1则表示非应答。
*/
void I2C_ACK()
{
        IO_SDA_SET_H();
       
        IO_SCL_SET_H();
        if(Get_IO_SDA()==0)
        IO_SCL_SET_L();
        else
        while(Get_IO_SDA()==1);
        IO_SCL_SET_L();
}

/*
I2C 上发送一个字节数据
发送字节:发送字节是时钟信号的低电平时候修改数据,。
*/
void Write_I2C_Byte(unsigned char I2C_Byte)
{
        unsigned char i;
       
        for(i=0;i<8;i++)
        {
                IO_SCL_SET_L();
               
                if((I2C_Byte<<i)&0x80)
                        IO_SDA_SET_H();
                else
                        IO_SDA_SET_L();
               
                IO_SCL_SET_H();               
        }
        IO_SCL_SET_L();
}
/*
add:7位地址;
rwbit:读写位,1表示读,0表示写
dat:数据字节
命令或数据:1表示发送的字节是数据,0表示发送的字节是命令
       
*/
void OLED_WR_Byte(unsigned char dat,unsigned char cmd)
{
        I2C_Start();
        Write_I2C_Byte(0x78);
        I2C_ACK();
        if(cmd)
                Write_I2C_Byte(0x40);
        else
                Write_I2C_Byte(0x00);
        I2C_ACK();
        Write_I2C_Byte(dat);
        I2C_ACK();       
        I2C_Stop();
}

使用特权

评论回复
发新帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1893

主题

15622

帖子

197

粉丝