以下内容将解释以下问题:1。什么是1。IIC协议?2.什么是2。IIC协议用于?3.3的沟通过程。IIC协议?
1.什么是1。IIC协议?
IIC,IC,字面意思是内部集成电路,实际上是IC bus的简称,所以中文应该叫IC bus。它是一种串行通信总线,采用多主从结构。它是由飞利浦在20世纪80年代开发的,允许主板、嵌入式系统或手机连接低速外围设备。(百度百科)
2.什么是2。IIC协议用于?
简而言之,IIC是一种通信协议,旨在使主板或嵌入式系统能够与其他外围模块通信。玩过stm32开发板的同学都知道,对于一个stm32核心开发板来说,如果要使用其他外围模块,必须经过布线、写代码、烧录的过程。
这个过程其实就是stm32和外围模块的一个通信过程。布线就是搭建通信线路。写代码就是制定通信的传输协议。烧操作是一个正式的沟通过程。只是有些模块的通信过程很简单,大家感觉不到而已。
外设和芯片之间的通信可以比喻为两个人在交谈:
你说的话,别人必须明白:双方约定,约定信号。
你的语速必须是别人能接受的:双方都符合计时要求。
但是随着科技的发展,模块越来越多,总是做不到。每个模块制定一个通信协议是不现实的。因此,总要有一些代表性的协议能够适应大多数模块的通信。IIC这是一种可以在IIC总线上安装多个外部设备的协议。
常用的串行通信协议有:
UART串行通信
IIC议定书
SPI协议
USB协议(难)
常用的并行通信协议有:
8080
6800
3.IIC协议的通信过程(这里是重点)
布线:为了建设IIC的通信线路,除了电源外,还需要两条线路,即SDA和SCLK。
SDA:数据信号线,用来传输数据。
SCLK:时钟信号线,用于产生时钟频率,控制时序,实现协议处理。
可以看出,IIC协议是半双工的,因为它是用于数据传输的单总线。
线路建立后,需要进行具体的沟通。
要交流,你得先发出开始信号。就像如果你想和某人说话,你总是要先打电话给他。如下图所示,协议规定当SCLK时钟信号始终处于高电平状态时,SDA线会从高电平跳变到低电平,表示开始信号。注意,此时即使SDA数据线的电平跳变结束,SCLK线仍然为高。当连接到IIC总线的外围模块检测到该信号时,它将知道数据传输即将开始。同样对于结束信号,协议规定当SCLK时钟信号始终处于高电平状态时,SDA线会从低电平跳变到高电平,表示结束信号。
知道如何开始后,就要开始数据传输了。
根据协议,在数据传输过程中,当SCLK为高电平时,外围模块开始采集SDA数据线上的数据。此时要求SDA数据线上的电平状态必须稳定(或者谁知道这位数据是0还是1),当SCLK处于低电平时,允许SDA线上的数据跳转到另一个状态。
以传输1位数据为例,如下图所示:
现在,我想传输1比特的数据,也就是1。从上面我们知道,发送启动信号后,此时SDA数据线的电平状态为低,SCLK信号仍然为高。这个时候外设有必要开始读取数据吗?
显然不是这样的。在发送开始信号和实际数据传输之间会有一个缓冲时间,以便我们准备数据。在数据准备阶段,SCLK信号会被下拉一段时间,期间SDA数据线会被上拉一段时间(也就是数据1),然后SCLK信号会被上拉。此时,如果外设检测到该时钟信号的高电平,外设将知道要读取数据,因此SDA上的数据将被读取。依此类推,传输下一位数据。
一般来说,在传输1个字节(即8位,高位先入)后,才考虑完整的数据传输,因为存储单元的最小单位是字节。那么如何才能确定每次都完美传输一个字节呢?
在这种情况下,需要外设来响应,就像打电话一样。如果对方不在或者不想听,再多的话也没用。那么外设如何应对呢?
根据协议,主机每发送一个字节的数据,即外设每接收一个字节的数据,在第九个时钟脉冲到来时,外设会拉低SDA数据线进行应答(ACK),并且必须处于稳定的低电平,表示已经接收到一个字节的数据,拉高表示不应答(ACK;请注意,拉低SDA数据线的是外设,而不是主机。如下图所示:
所以主机在传输完一个字节的数据后,要释放总线(协议规定SDA和SCLK同时为高时,表示空闲状态),然后将SDA数据线连接的IO口从输出模式切换到输入模式,才能在SDA数据线上得到应答信号。这样,一个字节的数据从主机传输到外设。
由于IIC是双向通信,主机也必须需要从外设读取数据。这个阅读过程是如何实现的?毕竟外设不能直接给我们操作,只能操作stm32。我们知道一条IIC总线上可以安装多个设备,那么stm32如何确定哪个外设正在与我通信呢?在这方面,那些生产外围模块的制造商已经同意,如果该设备使用IIC协议进行通信,则需要为该设备指定一个设备地址,用于芯片访问。当您购买其模块时,该设备的地址将在用户手册中注明。因此,如果要与哪个模块通信,必须通过查阅其手册找到其设备地址。
所以在前面提到的第一个字节的数据传输过程中,这个数据往往就是设备地址。这样对应的外设就知道是来和我交流的了。读取数据,同理,为了从外设读取数据,主机要明确三点:从哪些外设的哪里读取数据,将读取的数据存储在哪里。
所以主机在开始读取数据之前,必须先将设备地址和数据所在的地址发送给外设,这样外设就会知道你要从这个地址读取数据,从而通过SDA线传输数据。至于每个字节的具体传输过程,和上面说的主机到外设的过程差不多,只是反过来了,主机的等待响应变成了主动响应。
void IIC _设置模式_输出(){ GPIO _ init typedef GPIO _ IIC;RCC _ ah B1 periphclock cmd(RCC _ ah B1 periph _ GPIOE,使能);GPIO .GPIO _ Mode=GPIO _ Mode _ OUT//输出GPIO .GPIO _ OType=GPIO _ OType _ PP//推挽GPIO .GPIO _ Pin=GPIO _ Pin _ 15//引脚GPIO .GPIO _ PuPd=GPIO _ PuPd _ UP//上拉GPIO .GPIO _ Speed=GPIO _ Speed _ 25MHz//输出GPIO_Init(GPIOE,GPIO _ IIC);}void IIC _设置模式_ In(){ GPIO _ init typedef GPIO _ IIC;RCC _ ah B1 periphclock cmd(RCC _ ah B1 periph _ GPIOE,使能);GPIO .GPIO _ Mode=GPIO _ Mode _ IN//输出GPIO .GPIO _ Pin=GPIO _ Pin _ 15//引脚GPIO .GPIO _ PuPd=GPIO _ PuPd _ UP//上拉GPIO_Init(GPIOE,GPIO _ IIC);}void IIC _ Start(){ IIC _设置模式_输出();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);}void IIC _ Stop(){ IIC _设置模式_输出();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);}void IIC _写字节(u8数据){ IIC }设置模式_输出();IIC _ SCL _ OUT(0);//只有时钟线拉低,SDA上的数据才允许写入delay _ us(5);//将数据一位一位的发出去for(int I=0;i8;i ) { if(data(0x1(7-i))) //高位先入{ IIC _ SDA _ OUT(1);} else { IIC _ SDA _ OUT(0);} SCL IIC出(1);//让外设读取数据delay _ us(5);IIC _ SCL _ OUT(0);//重新拉低,准备写入下一位数据delay _ us(5);}}u8 IIC _读取字节({ u8数据=0;IIC _设置模式_输入();IIC _ SCL _ OUT(0);//先拉低,为读取数据做准备delay _ us(5);for(int I=0;i8;I){ SCL IIC _出(1);//SCL为高期间才可以读取数据delay _ us(5);如果(IIC民主行动党)数据|=(0x 01(7-I));} else { data=~(0x 1(7-I));} IIC _ SCL _ OUT(0);delay _ us(5);}返回数据;}u8 IIC _怀塔克(){ u8 ack=0;IIC _设置模式_输入();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);返回ack}void IIC确认(u8确认){ IIC _设置模式_输出();IIC _ SCL _ OUT(0);delay _ us(5);if(ack){ IIC _ SDA _ OUT(1);} else { IIC _ SCL _ OUT(0);} SCL IIC出(1);delay _ us(5);IIC _ SCL _ OUT(0);delay _ us(5);}
审核汤梓红
标签:数据IIC协议