把参考链接里的我觉着对我来说有用的搬运过来了,方便以后自己查阅。(有点乱,第一次写)
参考链接1: IIC原理超详细讲解—值得一看
参考链接2: STM32之IIC详细解析
IIC 简介
两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。
在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。
SCL和SDA都需要接上拉电阻 (大小由速度和容性负载决定一般在3.3K-10K之间) 保证数据的稳定性,减少干扰。
IIC是半双工,而不是全双工 ,同一时间只可以单向通信
IIC有哪些线?
只有两个总线: 双向的串行数据线SDA;串行时钟线SCL
SDA(Serial data)是数据线,D代表Data也就是数据,Send Data 也就是用来传输数据的
SCL(Serial clock line)是时钟线,C代表Clock 也就是时钟 也就是控制数据发送的时序的
用到IIC的设备都将两条线连在上面,每个设备都有一个唯一的地址,来区分不同设备。
IIC 使用介绍
IIC数据传输过程存在的信号
传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
——开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变(下降沿),开始传送数据。
——结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变(上升沿),结束传送数据。
——应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。
因为有上拉电阻的存在,所以在空闲时刻保证了SDA和SCL保持高电平状态
IIC数据传输过程信号产生范例
——IIC初始化——:SCL、SDA均处于高电平状态。
void IIC_init() //IIC初始化
{
SCL=1; //首先把时钟线拉高
delay_us(4);//延时函数
SDA=1; //在SCL为高的情况下把SDA拉高
delay_us(4); //延时函数
}
——开始信号——:SCL保持高电平,SDA由高电平变为低电平后,延时(>4.7us),SCL变为低电平。
//产生IIC开始信号
//1.先拉高SDA,再拉高SCL,空闲状态
//2.拉低SDA
void IIC_Start() //启动信号
{
SDA=1; //确保SDA线为高电平
delay_us(5);
SCL=1; //确保SCL高电平
delay_us(5);
SDA=0; //在SCL为高时拉低SDA线,即为起始信号
delay_us(5);
SCL=0; //钳住I2C总线,准备发送或接收数据
}
——结束信号——:停止信号:SCL保持高电平。SDA由低电平变为高电平。
//产生IIC结束信号
//1.先拉低SDA,再拉低SCL
//2.拉高SCL
//3.拉高SDA
//4.停止接收数据
void IIC_Stop(void)
{
IIC_SCL=0;
IIC_SDA=0; //STOP:当SCL高时,数据由低变高
delay_us(4);
IIC_SCL=1;
IIC_SDA=1; //发送I2C总线结束信号
delay_us(4);
}
——应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;(ACK:在大于一个时钟脉冲的时间保持SDA为低电平)
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。(NACK:在大于一个时钟脉冲的时间保持SDA为高电平)
在一个字节(8bit)传输的第九个时钟期间内,接收数据方必须回一个ACK应答信号给发送方。(应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答)
//****************主机产生应答信号ACK****************//
//1.先拉低SCL,再拉低SDA
//2.拉高SCL
//3.拉低SCL## 标题
//SCL ___——_
//SDA ——____
void I2C_Ack(void)
{
IIC_SCL=0; //先拉低SCL,使得SDA数据可以发生改变(因为只有SCL低电平,数据才能变)
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
//****************主机不产生应答信号NACK****************//
//1.先拉低SCL,再拉高SDA
//2.拉高SCL
//3.拉低SCL
void I2C_NAck(void)
{
IIC_SCL=0; //先拉低SCL,使得SDA数据可以发生改变
IIC_SDA=1; //拉高SDA,不产生应答信号
delay_us(2);
IIC_SCL=1;
delay_us(5);
IIC_SCL=0;
}
//****************等待应答信号到来****************//
//返回值:1,接收应答失败
// 0,接收应答成功
char IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(IIC_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
SDA线上的数据在SCL时钟“高”期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。
**当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位ACK, 此时才认为一个字节真正的被传输完成 **
向从机发送数据总体的一个过程:
1-主机发送start信号;
2-主机发送从机地址,高7bit是地址,bit0是读写控制位,0表示写,1表示读;
3-从机返回ACK响应信号;
4-主机发送要给从机写入数据的地址;(有的设备不用)
5-从机返回ACK响应信号;
6-主机发送数据;
7-从机返回ACK响应信号;
8-重复第6和7步,直到从机返回一个NACK非响应信号;
9-主机发送停止信号,结束数据传输。
读取从机发来数据的一个过程:
先向从机写入从机地址,因为IIC总线上可能不止一台从机设备,只有地址相等的从机才会返回应答,才可以进行之后的步骤;之后发送要读取数据的地址;再重启IIC总线,发送从机地址并改为读数据模式;接下来就可以读取数据直到主机发送非响应信号为止。
1-主机发送start信号;
2-主机发送从机地址,高7bit是地址,bit0是读写控制位,0表示写,1表示读;
3-从机返回ACK响应信号;
4-主机发送要给从机写入数据的地址;(有的设备不用)
5-从机返回ACK响应信号;
6-重新启动IIC总线,发送start信号;(前面步骤的目的向从机传送地址,下面开始读取数据)
7-主机发送从机地址,高7bit是地址,bit0是读写控制位,0表示写,1表示读;
8-从机返回ACK响应信号;
9-主机接收数据;
10-从机返回ACK响应信号;
11重复第9和01步,直到从机返回一个NACK非响应信号;
12主机发送停止信号,结束数据传输。