首页 > 编程知识 正文

iic协议应答,iic协议详解

时间:2023-05-03 07:27:00 阅读:49819 作者:4278

以下内容说明以下几个问题

1.IIC协议是什么?

2.IIC协议用于什么?

3.IIC协议的通信流程?

=====================================

1.IIC协议是什么?

IIC,即集成电路(IC ),全称集成电路,字面上是指集成电路之间,实际上是IC Bus的简称,因此在中文中应该称为集成电路总线。 这是一条串行通信总线,使用多主从架构,飞利浦在20世纪80年代推出主板和(百度百科)

2.IIC协议用于什么?

简而言之,IIC是一种通信协议,旨在使主板、嵌入式系统等能够与其他外围模块进行通信。 使用过stm32开发板的学生都知道,在stm32核心开发板上,要使用其他外围设备模块,必须连接电缆、编写代码、执行写操作。 实际上,这个过程是stm32与外围模块通信的过程。 布线是指建立通信的线路。 编写代码是编写通信的传输协议。 写入是正式的通信过程。 只是,因为也有通信过程简单的模块,所以大家感觉不到。 外围设备和芯片之间的通信可以形象地比喻成两个人的对话: I、你说的别人能理解、双方约定信号的协议。 ii、你的语速必须别人接受:双方符合时间序列要求。 但是,随着科学技术的发展,模块越来越多,越来越不可能,必须为每个模块编写通信协议,这是不现实的。 因此,需要能够应对大多数模块通信的代表性协议。 IIC这是一个IIC总线上,可以挂载多个外接设备

典型的串行通信协议包括:

UART串行通信

IIC协议

SPI协议

USB协议(困难)

典型的并行通信协议包括:

8080

6800

3 .IIC协议的通信流程(此处重点

接线:构建集成电路的通信线路,除电源外,还需要SDA和SCLK两条线

SDA:数据信号线,用于数据传输

SCLK:时钟信号线,生成时钟频率,控制定时,实现协议处理

由此可知,IIC协议是通过单总线进行数据传输的,因此为半双工

这里使用软件方式模拟IIC协议。

构建线路后,进行具体的通信。

通信的话,首先必须发出开始的信号吧。 你和人说话的时候,请总是叫他。 如下图所示,在协议中,当SCLK时钟信号一直处于高电平状态时,SDA线由高电平跳变到低电平这个动作,表示起始信号此时,即使SDA电缆的电平跳完,SCLK电缆也保持高电平哦。 可以看到,连接到IIC总线的外围设备模块检测到此信号时,将开始传输数据。 退出信号也同样适用于当SCLK时钟信号一直处于高电平状态时,SDA线由低电平跳变到高电平这个动作,表示结束信号

知道开始方法后,开始传输数据。

根据协定,为在数据的传输过程中,SCLK为高电平时,外设模块开始采集SDA数据线上的数据,此时要求SDA数据线上的电平状态必须稳定(否则幽灵知道该位的数据是0还是1 ),当SCLK为低电平时才允许SDA线上的数据跳变成另外一种状态)。

以下是传输1位数据的示例,如下图所示。

这里,我想传输1位数据。 此位数据为1。 如上所述,发送开始信号后,此时SDA数据线的电平状态为低电平,SCLK信号保持高电平。 此时,外围设备是否要开始读取数据? 这明显不同。 从发送开始信号到真正的数据传输之间有缓冲时间。 准备数据吧。 在准备数据阶段,首先将SCLK信号降低一定时间,在此期间将SDA数据线在意的金鱼设为一定时间,也就是数据1,然后准备SCLK信号在意的金鱼。 此时,如果外围设备检测到该时钟信号的高电平,则外围设备知道读取数据,从而能够读取数据,并依次传输下一位的数据。

通常,只有在传输完1字节(即8bit,高位先入)的数据后,才能进行完整的数据传输。 因为对于存储单元来说最小单位是字节。 怎么每次都有条不紊地传输一个字节呢?

这种情况下,外围设备需要应对。 打点电话之类的,如果没有对象或者不想听的话,再多说也没用。 外围设备如何应对呢?协议规定,主机每传完一个字节的数据即外设每收到一个字节的数据,外设就要在第9个时钟脉冲到来的时候,将SDA数据线拉低进行应答(ACK),且必须是稳定的低电平,表示已经收到了一个字节的数据,顺心的金鱼表示不进行应答(NACK请注意,此处外围设备会降低SDA电缆。 不是主体哦。 如下图所示。

因此,在从主机传递了1字节的数据后,需要释放总线(协议规定,当SDA和SCLK同时为高时,表示空闲状态),将连接有SDA数据线的IO端口从输出模式变换为输入模式,取得SDA数据

线上的应答信号。这样,一个字节的数据就从主机到外设传输完毕了。

既然IIC是双向通信的,那主机肯定也是需要从外设读取数据的,那这个读取的过程又是怎么实现的呢?毕竟外设对于我们而言是不能直接操作的,我们能操作的只有stm32。我们知道,一个IIC总线上,可以挂载多个设备,那么stm32如何确定是哪个外设正在跟我进行通信呢。对于此,那些生产外设模块的厂商们就约定,要是这个设备使用IIC协议进行通信,那么就要给这个设备指定一个器件地址,以供芯片访问。这个器件地址会在你购买其模块的时候在使用手册上注明。所以,要跟哪个模块通信,就一定要通过查阅其使用手册,找到它的器件地址。
所以,在上文所述的最开始的一个字节的数据传输过程中,这一个数据往往是器件地址。这样,对应的外设才知道,是要跟我进行通信。读取数据,也是同理,要想从外设中读取到数据,主机要明确三点:从哪个外设中的哪个地方读取数据,读取到的数据要存到哪里。
所以主机,在开始读数据之前,主机必须要先给外设发器件地址,数据所在的地址,外设才会知道你要从该地址读取数据,从而把数据通过SDA线传出来。至于具体的每个字节的传输过程,和上面所讲的从主机到外设的过程差不多,只不过反了一个反向而已,并且主机的等待应答变成了主动应答。

以下是IIC协议代码

/*设置SDA总线为输出模式参数值:NULL返回值:NULL*/void IIC_setSDAMode_Out(){GPIO_InitTypeDef GPIO_IIC;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_IIC.GPIO_Mode = GPIO_Mode_OUT;//输出GPIO_IIC.GPIO_OType = GPIO_OType_PP;//推挽GPIO_IIC.GPIO_Pin = GPIO_Pin_15; //引脚GPIO_IIC.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_IIC.GPIO_Speed = GPIO_Speed_25MHz;//输出GPIO_Init(GPIOE, &GPIO_IIC);}/*设置SDA总线为输入模式参数值:NULL返回值:NULL*/void IIC_setSDAMode_In(){GPIO_InitTypeDef GPIO_IIC;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_IIC.GPIO_Mode = GPIO_Mode_IN; //输出GPIO_IIC.GPIO_Pin = GPIO_Pin_15; //引脚GPIO_IIC.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOE, &GPIO_IIC);}/*IIC开始信号参数值:NULL返回值:NULL*/void IIC_Start(){IIC_setSDAMode_Out();IIC_SDA_OUT(1); //总线释放状态IIC_SCL_OUT(1);delay_us(5);IIC_SDA_OUT(0); //SDA跳变为低电平delay_us(5);IIC_SCL_OUT(0); delay_us(5);}/*IIC停止信号参数值:NULL返回值:NULL*/void IIC_Stop(){IIC_setSDAMode_Out();IIC_SDA_OUT(0); IIC_SCL_OUT(0);delay_us(5);IIC_SCL_OUT(1); //SDA跳变为高电平delay_us(5);IIC_SDA_OUT(1); delay_us(5);}/*主机写入数据到外设中参数值: data 要写入的一个字节返回值:NULL*/void IIC_writeByte(u8 data){IIC_setSDAMode_Out();IIC_SCL_OUT(0); //只有时钟线拉低,SDA上的数据才允许写入delay_us(5);//将数据一位一位的发出去for(int i =0;i<8;i++){if(data&(0x1<<(7-i))) //高位先入{IIC_SDA_OUT(1);}else{IIC_SDA_OUT(0);} IIC_SCL_OUT(1); //让外设读取数据 delay_us(5); IIC_SCL_OUT(0); //重新拉低,准备写入下一位数据 delay_us(5);}}/*主机从外设中读取一个字节的数据参数值:NULL返回值:NULL*/u8 IIC_readByte(){ u8 data = 0;IIC_setSDAMode_In();IIC_SCL_OUT(0); //先拉低,为读取数据做准备delay_us(5);for(int i=0;i<8;i++){IIC_SCL_OUT(1); // SCL为高期间才可以读取数据delay_us(5);if(IIC_SDA_IN){data|=(0x01<<(7-i));}else{data &= ~(0x1<<(7-i));}IIC_SCL_OUT(0);delay_us(5);}return data;}/*主机等待应答参数值:NULL返回值:ack 0 应答 1 不应答*/u8 IIC_waitAck(){u8 ack =0;IIC_setSDAMode_In();IIC_SCL_OUT(0); //准备时序delay_us(5);IIC_SCL_OUT(1);delay_us(5);if(IIC_SDA_IN){ack =1;}else{ack =0;}IIC_SCL_OUT(0); //拉低,表示应答完成delay_us(5);return ack;}/*主机主动应答参数值:ack 0 应答 1 不应答返回值:NULL*/void IIC_Ack(u8 ack){IIC_setSDAMode_Out();IIC_SCL_OUT(0);delay_us(5);if(ack){IIC_SDA_OUT(1);} else{IIC_SCL_OUT(0);}IIC_SCL_OUT(1);delay_us(5);IIC_SCL_OUT(0);delay_us(5);}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。