IIC
- I2C介绍
- I2C物理层(内部结构)
- I2C协议层
- 数据有效性
- 起始和结束信号
- 应答响应
- 时序图
- 数据传输
- 软件模拟IIC
- 使用方法
- 产生IIC起始信号
- 产生IIC停止信号
- 产生ACK应答
- 产生nack非应答
- 等待应答信号到来
- IIC发送一个字节
- IIC读一个字节
- AT24C02介绍
- 硬件设计
- 软件设计
- 实验现象
- 面试问题
硬件资源:使用51单片机的IO口模拟I2C时序,并实现与AT24C02(EEPROM)之间的双向通信。
实现功能:系统运行时,数码管右三位显示0,按K1键将数据写入到EEPROM内保存,按K2键读取EEPROM内保存的数据,按K3键显示数据加1,按卡键显示数据清0,最大能写入的数据是255。
I2C介绍
I2C(Inter-Integrated Circuit)总线两线式串行总线,用于连接微控制器及外围设备。
总线:只有两根双向信号线,一根是数据线SDA,另一根是时钟线SCL。
优点:接口线少,控制方式简单,器件封装形式小,通信速率较高,管脚少,硬件实现简单,可扩展性强。
使用场景:集成芯片内
I2C物理层(内部结构)
I2C协议层
数据有效性
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
起始和结束信号
SCL线为高电平时,SDA线由高电平向低电平的变化表示起始信号;
SCL线为高电平时,SDA线由低电平向高电平的变化表示终止信号。
起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。
应答响应
应答时序图:
每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)
时序图
I2C总线时序如下图所示:
数据传输
软件模拟IIC
由于51单片机没有硬件IIC接口,即使有硬件接口我们通常还是采用软件模拟I2C。主要原因时硬件IIC设计比较复杂,而且稳定性不怎么好,程序移植比较麻烦,而用软件模拟IIC,最大的好处就是移植方便,同一个代码兼容所有单片机,任何一个单片机只要有IO口(不需要特定IO),都可以很快的移植过去。
使用方法
要进行I2C通信,需要编写起始信号、停止信号、应答和非应答信号,I2C编写字节的函数。
这些信号中,起始信号是必须的,结束信号和应答信号都可以不要。
产生IIC起始信号
void iic_start(void)
{
IIC_SCL = 1;
IIC_SDA = 1;
delay_10us(1);
IIC_SDA = 0; //当SCL为高电平时,SDA由高变为低
delay_10us(1);
IIC_SCL = 0; //钳住I2C总线,准备发送或接收数据
}
产生IIC停止信号
void iic_stop(void)
{
IIC_SCL = 1;
IIC_SDA = 0;
delay_10us(1);
IIC_SDA = 1; //当SCL为高电平时,SDA由低变为高
delay_10us(1);
}
产生ACK应答
void iic_ack(void)
{
IIC_SCL = 0;
IIC_SDA = 0;
delay_10us(1);
IIC_SCL = 1;
delay_10us(1);
IIC_SCL = 0;
}
产生nack非应答
void iic_nack(void)
{
IIC_SCL = 0;
IIC_SDA = 1; //SDA为高电平
delay_10us(1);
IIC_SCL = 1;
delay_10us(1);
IIC_SCL = 0;
}
等待应答信号到来
u8 iic_wait_ack(void)
{
u8 time_temp = 0;
IIC_SCL = 1;
delay_10us(1);
while(IIC_SDA) //等待SDA为低电平
{
time_temp++;
if (time_temp > 100) //超时则强制结束IIC通信
{
iic_stop();
return 1;
}
}
IIC_SCL = 0;
return 0;
}
IIC发送一个字节
void iic_write_byte(u8 dat)
{
u8 i = 0;
IIC_SCL = 0;
for (i = 0; i < 8; i++) //循环8次将一个字节传出,先传高再传低位
{
if ((data & 0x80) > 0)
{
IIC_SDA = 1;
}
else
{
IIC_SDA = 0;
}
dat <<= 1;
delay_10us(1);
IIC_SCL = 1;
delay_10us(1);
IIC_SCL = 0
delay_10us(1); //传入这1干什么,延迟很短,也有延迟的必要性吗?
}
}
IIC读一个字节
u8 iic_read_byte(u8 ack)
{
u8 i = 0,receive = 0;
for ( i = 0; i < 8; i++) //循环8次将一个字节读出,先读高再传低位
{
IIC_SCL = 0;
delay_10us(1);
IIC_SCL = 1;
receive<<=1;
if (IIC_SDA)
{
receive++;
}
delay_10us(1);
}
if (!ack)
{
iic_nack();
}
else
{
iic_ack();
}
return receive;
}
AT24C02介绍
硬件设计
软件设计
实验现象
面试问题
1、IIC的特点。
2、IIC的优缺点。
3、数据有效性
4、三种信号
5、IIC工作速率
6、画IIC时序图
7、数据传输的流程
8、IIC如何进行读写操作
9、IIC总线怎么实现?
10、IIC总线仲裁机制是怎么样的?
11、为什么要上拉?
12、怎么用IO口模拟IIC?
13、主设备3.3v从设备1.8v,不使用电平转换如何通过搭电路实现通信