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由数据和时钟两部分组成
- 数据部分包括数据寄存器、数据移位寄存器和数据控制等
- 时钟部分包括控制状态寄存器、时钟控制寄存器、控制逻辑电路和时钟控制等,控制状态寄存器通过控制逻辑电路等控制时钟的行为
7.2 I²C设计实例
7.2.1 24C32A简介
- 24C32A是32Kbit串行EEPROM,内部组织为4KByte*8bit支持32Byte页写,写周期内部定时(小于5ms),2线串行接口,可实现8个器件共用1个接口,工作电压1.7~5.5V
- 8引脚封装
7.2.2 24C32A程序设计
//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写子程序(器件地址: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读子程序(器件地址: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; //返回数据
}