I2C 学习笔记
I2C(Inter-Integrated Circuit)总线是一种简单、双向、二线制的同步串行通信总线,广泛应用于电子设备中,主要用于连接微控制器(如单片机)和各种外围设备(如传感器、存储器、显示器等)。
1. I2C总线的起源和特点
- 起源:I2C总线由飞利浦公司(现NXP)在1982年开发,最初用于电视内部的芯片间通信。由于其简单、成本低、易于扩展等优点,逐渐被广泛应用。
- 特点
- 简单:仅需要两根线(数据线SDA和时钟线SCL)即可实现通信。
- 多主多从:支持多个主设备和多个从设备连接在同一总线上。
- 低速率:标准速率可达100kbps,快速模式可达400kbps,高速模式可达3.4Mbps。
- 低功耗:通信信号为电平信号,功耗较低。
- 易于扩展:可以方便地连接多个设备,且设备地址可以通过硬件引脚或软件配置来区分。
2. I2C总线的硬件连接
- 总线结构
- SDA(Serial Data Line):数据线,用于传输数据和地址信息。
- SCL(Serial Clock Line):时钟线,由主设备提供,用于同步数据传输。
- 上拉电阻:I2C总线是开漏(Open-Drain)结构,SDA和SCL线需要通过上拉电阻连接到电源,以保证信号的稳定。
- 设备连接
- 每个设备通过SDA和SCL连接到总线上。
- 每个从设备都有一个唯一的7位或10位地址,用于区分不同的设备。
- 主设备通过地址选择特定的从设备进行通信。
3. I2C总线的通信协议
- 起始条件:SCL为高电平时,SDA从高电平跳变为低电平,表示通信开始。
- 停止条件:SCL为高电平时,SDA从低电平跳变为高电平,表示通信结束。
- 数据传输
- 数据以字节为单位传输,每个字节包含8位数据。
- 数据在SCL的上升沿被采样,在下降沿被改变。
- 每个字节传输完成后,接收方需要发送一个应答信号(ACK)或非应答信号(NACK)。
- 地址传输
- 主设备首先发送一个7位或10位的从设备地址,加上一个读/写位(R/W)。
- 从设备通过地址匹配来确定是否响应通信。
- 应答信号
- 当主设备发送数据时,从设备在每个字节后发送ACK信号。
- 当主设备读取数据时,从设备发送数据,主设备在每个字节后发送ACK或NACK信号。
4. I2C总线的工作模式
- 主设备模式:负责发起通信,控制时钟信号SCL,并通过SDA发送地址和数据。
- 从设备模式:根据主设备发送的地址和指令,接收或发送数据。
- 多主设备模式:多个主设备可以共享同一总线,通过仲裁机制避免冲突。
5. I2C总线的应用场景
- 传感器通信:如温度传感器、湿度传感器、加速度传感器等,通过I2C总线将数据传输到主控制器。
- 存储器通信:如EEPROM、Flash存储器等,用于存储配置信息或数据。
- 显示设备通信:如I2C接口的LCD或OLED显示屏,用于显示信息。
- 音频设备通信:如I2C接口的音频编解码器,用于音频信号处理。
6. I2C总线的优缺点
- 优点
- 硬件接口简单,仅需两根线。
- 支持多主多从通信,易于扩展。
- 低功耗,适合低功耗设备。
- 协议简单,易于实现。
- 缺点
- 速率较低,不适合高速数据传输。
- 总线负载能力有限,设备过多可能导致通信不稳定。
- 通信距离较短,通常不超过几米。
I2C总线因其简单、灵活和低功耗的特点,广泛应用于各种嵌入式系统和物联网设备中,是现代电子系统中不可或缺的通信接口之一。
这段代码是基于51单片机的I2C通信协议实现的代码。它包含了I2C通信的基本操作,如启动信号、发送数据、接收数据、应答信号和停止信号等。以下是对代码的详细解释:
1. I2C_Start()
void I2C_Start(){
SDA=1;
SCL=1;
Delay_xms(5);
SDA=0;
Delay_xms(5);
SCL=0;
}
- 功能:生成I2C通信的启动信号。
- 过程:
- 将数据线(SDA)和时钟线(SCL)都拉高(
SDA=1; SCL=1;
)。 - 延时5ms(
Delay_xms(5);
),确保信号稳定。 - 将数据线拉低(
SDA=0;
),保持时钟线为高电平,生成一个下降沿信号,表示通信开始。 - 再次延时5ms,确保信号稳定。
- 将时钟线拉低(
SCL=0;
),完成启动信号的生成。
- 将数据线(SDA)和时钟线(SCL)都拉高(
2. I2C_DalaSend(unsigned char date)
void I2C_DalaSend(unsigned char date){
unsigned char bita=date;
unsigned char i;
for(i=0;i<8;i++){
SCL=0;
if(bita & 0x80){
SDA=1;
}
else{
SDA=0;
}
Delay_xms(5);
SCL=1;
Delay_xms(5);
bita<<=1;
}
SCL = 0;
}
- 功能:发送一个字节的数据。
- 过程:
- 将要发送的数据存储到变量
bita
中。 - 通过一个循环发送8位数据:
- 先将时钟线拉低(
SCL=0;
)。 - 检查当前位是否为1(
if(bita & 0x80)
)。如果是1,则将数据线拉高(SDA=1;
),否则拉低(SDA=0;
)。 - 延时5ms,确保信号稳定。
- 将时钟线拉高(
SCL=1;
),完成一位数据的发送。 - 再次延时5ms,确保信号稳定。
- 将
bita
左移一位(bita<<=1;
),准备发送下一位。
- 先将时钟线拉低(
- 最后将时钟线拉低(
SCL = 0;
),结束数据发送。
- 将要发送的数据存储到变量
3. I2C_Sectchar()
bit I2C_Sectchar(){
bit byte=0;
SDA=1;
SCL=1;
bite=SDA;
SCL=0;
return bite;
}
- 功能:接收从设备的应答信号。
- 过程:
- 将数据线和时钟线都拉高(
SDA=1; SCL=1;
)。 - 读取数据线的状态(
bite=SDA;
),判断从设备是否发送了应答信号。 - 将时钟线拉低(
SCL=0;
),完成应答信号的接收。 - 返回应答信号的状态(
return bite;
)。
- 将数据线和时钟线都拉高(
4. I2C_DalaReceive()
unsigned char I2C_DalaReceive(){
unsigned char acm=0;
unsigned char i;
SDA=1;
for(i=0;i<8;i++){
SCL=0;
Delay_xms(5);
SCL=1;
Delay_xms(5);
acm=(acm<<1)|SDA;
}
SCL = 0;
return acm;
}
- 功能:接收一个字节的数据。
- 过程:
- 将数据线拉高(
SDA=1;
)。 - 通过一个循环接收8位数据:
- 先将时钟线拉低(
SCL=0;
)。 - 延时5ms,确保信号稳定。
- 将时钟线拉高(
SCL=1;
),让从设备发送一位数据。 - 再次延时5ms,确保信号稳定。
- 读取数据线的状态(
SDA
),并将接收到的位左移后与之前接收的位组合(acm=(acm<<1)|SDA;
)。
- 先将时钟线拉低(
- 最后将时钟线拉低(
SCL = 0;
),完成数据接收。 - 返回接收到的数据(
return acm;
)。
- 将数据线拉高(
5. I2C_Ack(bit nmc)
void I2C_Ack(bit nmc){
SCL=1;
SDA=nmc;
SCL=0;
}
- 功能:发送应答信号。
- 过程:
- 将时钟线拉高(
SCL=1;
)。 - 根据参数
nmc
的值,将数据线设置为高或低(SDA=nmc;
)。如果nmc=0
,表示发送应答信号;如果nmc=1
,表示发送非应答信号。 - 将时钟线拉低(
SCL=0;
),完成应答信号的发送。
- 将时钟线拉高(
6. I2C_Stop()
void I2C_Stop(){
SDA=0;
SCL=1;
SDA=1;
}
- 功能:生成I2C通信的停止信号。
- 过程:
- 将数据线拉低(
SDA=0;
)。 - 将时钟线拉高(
SCL=1;
)。 - 将数据线拉高(
SDA=1;
),生成一个上升沿信号,表示通信结束。
- 将数据线拉低(
总结
这段代码实现了一个完整的I2C通信流程,包括启动信号、数据发送、数据接收、应答信号和停止信号。通过这些函数,可以与支持I2C协议的设备进行通信。