原理图和数据手册
三根线:
- GND地线
- SCL为时钟线
- SDA为数据线
串行、电平式
总线式结构:一对多、一个主设备,总线上可以挂上百个器件,用从地址来区分
主从式:由主设备发起信号,从设备被动响应
通信速率一般(kbps级别),不适合语音、视频等信息类型
at24c02低层时序
START开始信号
SCL高电平期间,SDA要发生下降沿
//起始信号
void I2C_start()
{
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();
I2C_SDA = 0;//下降沿
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
STOP停止信号
SCL高电平期间,SDA要发生上升沿
//结束信号
void I2C_stop()
{
I2C_SDA = 0;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();
I2C_SDA = 1;//上升沿
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
传输“0”或应答位(A)
SCL高电平期间,SDA为“0”
I2C是从高位开始发送、接收的
应答:SDA要提前拉高,当cpu在第9个时钟周期读取的时候,发现at24c02给拉低了,就会判断是应答了
//向从设备发送一个字节 ack=1 开启应答, 0关闭应答
unsigned char I2C_sendbyte(unsigned char dat,unsigned char ack)
{
unsigned char a = 0, b = 0;
I2C_SCL = 0;
for(a = 0; a<8; a ++)
{
I2C_SDA = dat>>7;
dat<<=1;
I2C_Delay10us();
I2C_SCL = 1;
I2C_Delay10us();
I2C_SCL = 0;
I2C_Delay10us();
}
I2C_SDA = 1;
I2C_Delay10us();
I2C_SCL = 1;
while(I2C_SDA && (ack == 1))
{
b++;
if(b > 200)//超过200us没有应答
{
I2C_SCL = 0;
I2C_Delay10us();
}
return 0;//失败
}
I2C_SCL = 0;
I2C_Delay10us();
return 1;//成功
}
传输“1”或非应答位(/A)
SCL高电平期间,SDA为“1”
非应答:SDA要提前置“1”,当cpu在第9个时钟周期读取的时候,发现at24c02还是高电平,就会判断是非应答了
概念:释放总线(SDA = 1)
- 发送数据,接收数据都用SDA。当从设备要给主设备发送数据的时候,必须要释放总线;在其他更高级的单片机(如STM32),这里的处理还有些不一样
- 为什么SDA = 1就释放总线,因为51单片机把引脚拉高之后,从设备还可以把引脚拉低,但是主设备把引脚拉低了,从设备就无法再次拉高。
at24c02高层时序
写操作
start >> 从设备地址 >> 存储地址 >> 数据 >> stop
- 从器件的地址是由自身决定的,不同的从器件的地址定义方式不一样,要具体看数据手册
- 同一个I2C网络中只有一个主设备,但是从设备可以有多个,这些从设备的地址不能相同(硬件设计师必须保证)
- 高4位1010固定,由电路图可知A2 A1 A0接VCC了,均为1
- 最低位:1是读操作,0是写操作
void AT24C02_write(unsigned char addr,unsigned char dat)
{
I2C_start();
I2C_sendbyte(0xae,1);
I2C_sendbyte(addr,1);
I2C_sendbyte(dat,0);
I2C_stop();
}
读操作
立即地址读
选择性读
连续读