7. 内部集成电路总线接口I²C

7. 内部集成电路总线接口I²C

  7.1 I²C结构及寄存器说明

  7.2 I²C设计实例

      7.2.1   24C32A简介

      7.2.2   24C32A程序设计

      7.2.3     24C32A程序应用

7.1 I²C结构及寄存器说明

  • 内部集成电路总线接口I²C是通信控制领域广泛采用的一种总线标准,用于连接微控制器和外围设备,连接在总线上的每个设备都有唯一的7/10位地址
  • I²C使用一根双向串行数据线SDA和一根双向串行时钟线SCL实现主/从设备间的多主串行通信
  • SDA和SCL的时序关系

  • 起始条件是在SCL高电平时SDA从高电平变为低电平,停止条件是在SCL高电平时SDA从低电平变为高电平
  • SDA上的数据必须在SCL高电平时保持稳定,低电平时可以改变。发送器发送数据后释放SDA(高电平),接收器接收数据后必须在SCL低电平时将SDA变为低电平,并在SCL高电平时保持稳定,作为对发送器的应答
  • I²C由数据和时钟两部分组成
  • 数据部分包括数据寄存器、数据移位寄存器和数据控制等
  • 时钟部分包括控制状态寄存器、时钟控制寄存器、控制逻辑电路和时钟控制等,控制状态寄存器通过控制逻辑电路等控制时钟的行为

  • I²C使用的GPIO引脚

  • I²C通过9个寄存器进行操作

7.2 I²C设计实例

    7.2.1 24C32A简介

  • 24C32A是32Kbit串行EEPROM,内部组织为4KByte*8bit支持32Byte页写,写周期内部定时(小于5ms),2线串行接口,可实现8个器件共用1个接口,工作电压1.7~5.5V
  • 8引脚封装

  • 24C32A的字节读写格式

 

    7.2.2 24C32A程序设计

  • I²C初始化子程序
//I²C初始化子程序

void I2c1_Init(void)
{

    RCC->APB2ENR |= 1<<3;                 //开启GPIOB时钟

    RCC->APB1ENR |= 1<<21;                //开启I²C1时钟

    GPIOB->CRL |= 0xff000000;             //PB.06(SCL)和PB.07(SDA)复用开漏输出

    I2C1->CR2 = 8 ;                     //时钟频率:8MHz

    I2C1->CCR |= 1<<15;                 //快速模式

    I2C1->CCR |= 1<<14;                 //占空比9/25
    
    I2C1->CCR |= 1 ;                    //分频系数:8MHz/(25*320KHz)=1

    I2C1->TRISE = 3 ;                   //上升时间:int(300ns*8MHz+1)

    I2C1->CR1 |= 1 ;                    //允许I²C1
}
  • I²C写子程序
//I²C写子程序(器件地址:000)
//入口参数:addr-数据地址,data-数据

void I2c1_Write(short addr,char data)
{
    short temp = addr>>8;

    //产生起始条件

    I2C1->CR1 |= 1<<8;                 //START=1

    while(!(I2C1->SR1&1));             //等待SB=1

    //发送控制字节

    I2C1->DR = 0xa0;                   //7位地址,写操作

    while(!(I2C1->SR1&2));             //等待ADDR=1

    I2C1->SR2;                         //清除事件

    //发送数据地址高4位

    while(!(I2C1->SR1&1<<7));          //等待TXE=1

    I2C1->DR = temp;                   //发送数据地址高4位

    //发送数据地址高8位

    while(!(I2C1->SR1&1<<7));         //等待TXE=1

    I2C1->DR = addr;                  //发送数据地址低8位

    //发送数据字节

    while(!(I2C1->SR1&1<<7));         //等待TXE=1

    I2C1->DR = data;                  //发送数据字节

    while(!(I2C1->SR1&1<<2));         //等待BTF=1

    //产生停止条件

    I2C1->CR1 |= 1<<9;                 //STOP=1

    for(temp=0;temp<<5000;temp++);     //延时约5ms
}
  • I²C读子程序
//I²C读子程序(器件地址:000)
//入口参数:addr-数据地址

void I2c1_Read(short addr)
{
    char temp = addr>>8;

    //产生起始条件

    I2C1->CR1 |= 1<<8;             //START=1

    while(!(I2C1->SR1&1));         //等待SB=1

    //发送控制字节

    I2C1->DR = 0xa0;               //7位地址,写操作

    while(!(I2C1->SR1&2));         //等待ADDR=1

    I2C1->SR2;                     //清除事件

    //发送数据地址高4位

    while(!(I2C1->SR1&1<<7));      //等待TXE=1

    I2C1->DR = temp;               //发送数据地址高4位

    for(temp=0;temp<50;temp++);    //延时

    //发送数据地址高8位

    while(!(I2C1->SR1&1<<7));      //等待TXE=1

    I2C1->DR = addr;               //发送数据地址高8位



    //重新产生起始条件

    I2C1->CR1 |= 1<<0;             //START=1

    while(!(I2C1->SR1 & 1));       //等待SB=1

    //发送控制字节

    I2C1->DR = 0xa1;               //7位地址,读操作

    while(!(I2C1->SR1 & 2 ));      //等待ADDR=1

    I2C1->SR2;                     //清除事件

    //接收数据字节

    while(!(I2C1->SR1 & 1<<6));     //等待RxNE=1

    temp = I2C1->DR;                 //接收数据字节

    //产生停止条件

    I2C1->CR1 |= 1<<9;             //STOP=1

    return temp;                 //返回数据
}

猜你喜欢

转载自blog.csdn.net/SherlockHolmess/article/details/87929370