STM32——关于I2C的讲解与应用

1、什么是I2C?

        I2C(Inter-Integrated Circuit)是一种通用的总线协议。它是由Philips(飞利浦)公司,现NXP(恩智浦)半导体开发的一种简单的双向两线制总线协议标准。是一种半双工的同步通信协议。

2、I2C协议标准  

      I2C协议使用两根总线线路,即时钟线(SCL)和数据线(SDA),用于在主设备和从设备之间传输数据。主设备负责生成时钟信号,并控制通信的起始和停止,从设备则负责响应主设备的指令和传输数据。

 对于I2C总线来说,支持总线挂载多设备(一主多从、多主多从),类似上面的就是一主多从。

        I2C协议支持多主设备和多从设备的连接,每个设备都有一个唯一的地址。主设备通过发送地址和数据来选择要与之通信的从设备,并可以进行读取和写入操作。I2C总线保持向下兼容性。

        I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。各设备连接到总线的输出端时必须是漏极开路(OD)输出或者集电极开路(OC)输出。

        在I2C的实际应用中,我们实际一般将软件模拟的I2C引脚定义为开漏输出(GPIO_Mode_Out_OD),将硬件模拟的I2C引脚定义为复用开漏输出( GPIO_Mode_AF_OD)

3、I2C的通信速率

  • 标准模式:100Kbps,采用7位寻址。
  • 快速模式:400Kbps,采用10位寻址。
  • 高速模式:3.4Mbps。
  • 4、I2C总线的工作原理

            MCU与I2C芯片之间的通信,可以形象的比喻成两个人对话,因此必须遵循基本的规范;一是你说的话别人能够听懂,即双方要有约定的信号协议(通信协议);二是你的语速要能够被别人所接受,即双方满足时序要求。

    5、I2C总线的信号要求

            I2C总线上可以挂多个设备,每个I2C设备都有固定的地址,只有当I2C两条线上传输的地址值等于某个I2C设备的地址时,该I2C设备才做出响应。数据传输后,必须要有应答信号(响应信号)。数据传输前必须有开始信号,传输结束后必须有结束信号。

  •  开始信号:I2C协议规定,SCL处于高电平时,SDA由高到低变化,这种信号是起始信号。当I2C总线上的设别检测到这个开始信号后,就知道该发送数据了。
  • 停止信号:I2C协议规定,SCL处于高电平,SDA由低到高变化,这种信号是停止信号。
  • 数据传输:I2C协议对数据的采样发生在SCL高电平期间,除了起始和停止信号,在数据传输期间,SCL为高电平时,SDA必须保持稳定,不允许改变,在SCL低电平时才可以进行变化。
  • 应答信号:处理器把数据发给从设备,如何知道从设备已经接收到数据呢?这就需要从设备回应一个信号给主机,因为当主机发送玩数据会后就不再驱动总线(SDA引脚由输出变为输入),而SDA和SCL硬件在设计时都有上拉电阻,所以这时SDA变为高电平。当一个字节的数据传输完成后,即在第九个SCL时钟周期内,此时主机需要释放SDA总线,把总线控制权交给从机,由于上拉电阻的作用,此时总线为高电平,如果从机正确的收到了主机发来的数据,会把SDA拉低,表示应答响应。当在第九个SCL时钟周期内,若SDA是高电平,则为无效应答,表示从机位接收到主机发送来的数据。
  • 6、软件模拟I2C通信

    首先我们设置软件I2C的引脚,将其定义为开漏输出
    void Soft_I2C_Init(void)
    {
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    /*这里为什么两个引脚都设置为高电平,是由于I2C总线的要求,
    在使用I2C协议时,当SCL和SDA处于高电平时,此时I2C总线为空闲状态。*/
        GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
    }
    在这里我们定义SCL和SDA
    void Soft_I2C_W_SCL(uint8_t BitValue)
    {
    	GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
    	Delay_us(10);
    }
    
    void Soft_I2C_W_SDA(uint8_t BitValue)
    {
    	GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction)BitValue);
    	Delay_us(10);
    }
    I2C协议规定,SCL处于高电平时,SDA由高到低变化,这种信号是起始信号。
    当I2C总线上的设别检测到这个开始信号后,就知道该发送数据了。
    void Soft_I2C_Start(void)
    {
    	Soft_I2C_W_SDA(1);
    	Soft_I2C_W_SCL(1);
    	Soft_I2C_W_SDA(0);
    	Soft_I2C_W_SCL(0);
    }
    
    当I2C准备发送一个字节时,SCL在低电平期间,主机会依次将数据位放到SDA线上(高位先行)
    所以在这里我们将SCL拉到低电平,更便于我们理解。
    
    void Soft_I2C_Stop(void)
    {
    	Soft_I2C_W_SDA(0);
    	Soft_I2C_W_SDA(1);
    	Soft_I2C_W_SCL(1);
    }
    
    当SCL低电平,变换数据,高电平,保持数据稳定
    void Soft_I2C_SendByte(uint8_t Byte)
    {
    	uint8_t i;
    	for(i = 0 ;i<8;i++)
    	{
    		当SCL低电平时,把Byte的最高位放在SDA线上(高位先行)
    		Soft_I2C_W_SDA(Byte & (0x80 >> i));
    		Soft_I2C_W_SCL(1);从机将在SCL高电平期间读取数据位
    		Soft_I2C_W_SCL(0);当SCL低电平时,SDA会继续取下一位的数据
    	}
    }
    

    作者:Xa_L

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32——关于I2C的讲解与应用

    发表回复