2024年IIC原理超详细讲解---值得一看,2024年最新阿里内部物联网嵌入式开发笔记火爆IT圈

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

主机就是负责整个系统的任务协调与分配,从机一般是通过接收主机的指令从而完成某些特定的任务,主机和从机之间通过总线连接,进行数据通讯。

  • 发布主要命令的称为主机
  • 接受命令的称为从机

半双工和全双工:

IIC的协议层

I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。

  • 开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
  • 结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
  • 应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。

IIC 总线时序图

img

下面我们来详细的介绍下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时钟线会频繁的转换电平,以保证数据的传输

在这里插入图片描述

img

应答信号

每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,

应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答

  • 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
  • 应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

在这里插入图片描述

**每发送一个字节(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, 此时才认为一个字节真正的被传输完成 ,如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。

img

IIC写数据:

img

多数从设备的地址为7位或者10位,一般都用七位。
八位设备地址=7位从机地址+读/写地址,

再给地址添加一个方向位位用来表示接下来数据传输的方向,

  • 0表示主设备向从设备(write)写数据,
  • 1表示主设备向从设备(read)读数据

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

主机要向从机写数据时:

  1. 主机首先产生START信号
  2. 然后紧跟着发送一个从机地址,这个地址共有7位,紧接着的第8位是数据方 向位(R/W),0表示主机发送数据(写),1表示主机接收数据(读)
  3. 主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,若相同,则认为自己正在被主机寻址,根据R/T位将自己确定为发送器和接收器
  4. 这时候主机等待从机的应答信号(A)
  5. 当主机收到应答信号时,发送要访问从机的那个地址, 继续等待从机的应答信号
  6. 当主机收到应答信号时,发送N个字节的数据,继续等待从机的N次应答信号,
  7. 主机产生停止信号,结束传送过程。
IIC读数据:

在这里插入图片描述
主机要从从机读数据时

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FzNDgwMTMzOTM3,size_16,color_FFFFFF,t_70)
主机要从从机读数据时

[外链图片转存中…(img-pOERcjBs-1715624903966)]
[外链图片转存中…(img-XQe3QJ5A-1715624903967)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值