独家揭秘!2024年IIC原理深度解析与物联网嵌入式开发秘籍——火爆IT圈阿里内部笔记
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
如果你需要这些资料,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
主机就是负责整个系统的任务协调与分配,从机一般是通过接收主机的指令从而完成某些特定的任务,主机和从机之间通过总线连接,进行数据通讯。
半双工和全双工:
IIC的协议层
I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。
IIC 总线时序图
下面我们来详细的介绍下IIC的通信协议流程:
初始(空闲)状态
因为IIC的 SCL 和SDA 都需要接上拉电阻,保证空闲状态的稳定性
所以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);
}
在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线;而在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态。
数据有效性
IIC信号在数据传输过程中,当SCL=1高电平时,数据线SDA必须保持稳定状态,不允许有电平跳变,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
SCL=1时 数据线SDA的任何电平变换会看做是总线的起始信号或者停止信号。
也就是在IIC传输数据的过程中,SCL时钟线会频繁的转换电平,以保证数据的传输
应答信号
每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,
应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答
**每发送一个字节(8个bit)**在一个字节传输的8个时钟后的第九个时钟期间,接收器接收数据后必须回一个ACK应答信号给发送器,这样才能进行数据传输。
应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答,
//主机产生应答信号ACK
//1.先拉低SCL,再拉低SDA
//2.拉高SCL
//3.拉低SCL## 标题
void I2C\_Ack(void)
{
IIC_SCL=0; //先拉低SCL,使得SDA数据可以发生改变
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;
}
IIC数据传送
数据传送格式
SDA线上的数据在SCL时钟“高”期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。
当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位ACK, 此时才认为一个字节真正的被传输完成 ,如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。
IIC写数据:
多数从设备的地址为7位或者10位,一般都用七位。
八位设备地址=7位从机地址+读/写地址,
再给地址添加一个方向位位用来表示接下来数据传输的方向,
IIC的每一帧数据由9bit组成,
如果是发送数据,则包含 8bit数据+1bit ACK,
如果是设备地址数据,则8bit包含7bit设备地址 1bit方向
在起始信号后必须传送一个从机的地址(7位) 1~7位为7位接收器件地址,第8位为读写位,用“0”表示主机发送数据(W),“1”表示主机接收数据 (R), 第9位为ACK应答位,紧接着的为第一个数据字节,然后是一位应答位,后面继续第2个数据字节。
IIC发送一个字节数据:
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
//IIC\_SCL=0;
//在SCL上升沿时准备好数据,进行传送数据时,拉高拉低SDA,因为传输一个字节,一个SCL脉冲里传输一个位。
//数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变)
//只有当SCL被拉低后,SDA才能被改变
//总结:在SCL为高电平期间,发送数据,发送8次数据,数据为1,SDA被拉高,数据为0,SDA被拉低。
//传输期间保持传输稳定,所以数据线仅可以在时钟SCL为低电平时改变。
void IIC\_Send\_Byte(u8 txd)
{
u8 t;
SDA\_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
//IIC\_SDA=txd&0x80; //获取最高位
//获取数据的最高位,然后数据左移一位
//如果某位为1,则SDA为1,否则相反
if(txd&0x80)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay\_us(2);
IIC_SCL=1;
delay\_us(2);
IIC_SCL=0;
delay\_us(2);
}
}
或者:
//IIC\_SDA=txd&0x80; //获取最高位
//获取数据的最高位,然后右移7位,假设为 1000 0000 右移7位为 0000 0001
// 假设为 0000 0000 右移7位为 0000 0000
//如果某位为1,则SDA为1,否则相反
IIC_SDA=((txd&0x80)>>7);
txd<<=1;
IIC读取一个字节数据:
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC\_Read\_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA\_IN(); //SDA设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay\_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay\_us(1);
}
if (!ack)
IIC\_NAck(); //发送nACK
else
IIC\_Ack(); //发送ACK
return receive;
}
IIC发送数据
Start: IIC开始信号,表示开始传输。
DEVICE_ADDRESS:: 从设备地址,就是7位从机地址
R/W: W(write)为写,R(read)为读
ACK: 应答信号
WORD_ADDRESS : 从机中对应的寄存器地址 比方说访问 OLED中的 某个寄存器
DATA: 发送的数据
STOP: 停止信号。结束IIC
主机要向从机写数据时:
- 主机首先产生START信号
- 然后紧跟着发送一个从机地址,这个地址共有7位,紧接着的第8位是数据方 向位(R/W),0表示主机发送数据(写),1表示主机接收数据(读)
- 主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,则认为自己正在被主机寻址,根据R/T位将自己确定为发送器和接收器
- 这时候主机等待从机的应答信号(A)
- 当主机收到应答信号时,发送要访问从机的那个地址, 继续等待从机的应答信号
- 当主机收到应答信号时,发送N个字节的数据,继续等待从机的N次应答信号,
- 主机产生停止信号,结束传送过程。
IIC读数据:
主机要从从机读数据时
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
如果你需要这些资料,可以戳这里获取
poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FzNDgwMTMzOTM3,size_16,color_FFFFFF,t_70)
主机要从从机读数据时
[外链图片转存中…(img-pOERcjBs-1715624903966)]
[外链图片转存中…(img-XQe3QJ5A-1715624903967)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新
如果你需要这些资料,可以戳这里获取
作者:普通网友