[西门子] 一天一个设计实例-IIC协议及FPGA实现

[复制链接]
查看64946 | 回复0 | 2024-11-26 08:34:04 | 显示全部楼层 |阅读模式
1.1.1IIC 总线规范简介

1) IIC 总线特性介绍

在现代电子产品开发过程中,为了简化系统,提高系统的可靠性,缩短产品开发周期,增加硬件构成的灵活性,推出了一种高效、可靠、方便的 IIC串行总线。二线制的 IIC 串行总线使得各电路单元之间只需要简单的两线连接,总线接口都集成在器件中,可实现电路系统的模块化、标准化设计。在 IIC 总线上,各单元电路相互之间没有其它连线,常用的单元电路基本上与系统电路无关,极易形成自己的标准化、模块化设计。

2) IIC 标准模式总线规范

IIC总线可通过串行数据(SDA)和串行时钟(SCL)线与总线上的任何一个器件连接,每 个器件都有一个唯一的地址,都可以作为一个发送器或接收器。各器件在执行数据传输时也都可被看做是一个主机或从机。

发送器

本次传送中发送数据(不包括地址和命令)到总线的器件;

接收器

本次传送中从总线接收数据(不包括地址和命令)的器件;

主机

初始化发送、产生时钟信号和终止发送的器件,它可以是发送器或接收器, 主机通常是微控制器;

从机

被主机寻址的器件,它可以是发送器或接收器。

IIC总线是一个多主机的总线,可以连接多个能控制总线的器件到总线。当两个以上能控制总线的器件同时发生传输时,只能有一个器件能真正控制总线而成为主机,并使报文不被破坏,这个过程叫做仲裁。与此同时,能使多个能控制总线的器件产生同步的时钟信号。

SDA 和 SCL 都是双向线路,连接到总线的器件的输出级必须是漏极开路或集电极开路,该器件通过一个电流源或上拉电阻连接到正的电源电压,实现线与功能。当总线空闲时,这两条线路都是高电平。IIC总线上数据的传输速率在标准模式下可达100kb/s,在快速模式下可达400kb/s,在高速模式下可达3.4Mb/s。连接到总线的接口数量由总线电容是400pF的限制决定。

3)  IIC总线电路设计要点



图2‑1  I2C总线电路设计要点

4) 位传输

IIC 总线上每传输一个数据位必须产生一个时钟脉冲。

(1) 数据的有效性。SDA 线上的数据必须在时钟线 SCL 的高电平周期保持稳定, 数据线的电平状态只有在 SCL 线的时钟信号是低电平时才能改变,如图 2.11 所示。 在标准模式下,高低电平宽度必须大于等于 4.7us。



图2‑2 数据有效性



图2‑3 IIC总线控制的位传输

(2) 起始和停止条件。在 IIC 总线中,唯一违反上述数据有效性的是起始(S)和停止(P)条件,如图2‑4 所示。

起始条件(重复起始条件): 在 SCL 线是高电平时,SDA 线从高电平向低电平切换。

停止条件: 在 SCL 线是高电平时,SDA 线由低电平向高电平切换。



图2‑4 起始位和停止条件

起始和停止条件一般由主机产生。起始条件是作为一次传送的开始,在起始条件后,总线被认为处于忙的状态。停止条件是作为一次传送的结束,在停止条件的某段时间后,总线被认为再次处于空闲状态。重复起始条件既作为上次传送的结束,也作为下次传送的开始。

5) 数据传输

(1) 字节格式。发送到 SDA 线上的每个字节必须为 8 位。每次传输可以发送的字节数量不受限制,每个字节后必须跟一个应答位。首先传输的是数据的最高位(MSB), 如图2‑5所示。



图2‑5 IIC总线的数据传输

(2) 应答。相应的应答时钟脉冲由从机产生。在应答的时钟脉冲期间,发送器释放 SDA线(高),与此同时,接收器必须将 SDA 线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平,如图2‑5中时钟信号SCL 的第 9 位。

一般说来,被寻址匹配的从机或可继续接收下一字节的接收器将产生一个应答。若作为发送器的主机在发送完一个字节后没有收到应答位(或收到一个非应答位),或作为接收器的主机没有发送应答位(或发送一个非应答位),那么,主机必须产生一个停止条件或重复起始条件来结束木次传输。若从机(接收器)不能接收更多的数据字节,将不产生这个应答位 :主机(接收器)在接收完最后一个字节后不产生应答, 通知从机(发送器)数据结束。

6) 仲裁与时钟发生

(1) 同步。时钟同步是通过各个能产生时钟的器件“线与” 连接到 SCL 线上来实现的,各器件可能都有自己独立的时钟 各个时钟信号的频率、周期、相位和占空比可能都不相同,由于 “线与” 的结果,在 SCL 线上产生的实际时钟的低电平宽度由低电平持续时间最长的器件决定,他高电平宽度由高电平持续时间最短的器件决定。

(2) 仲裁。当总线空闲时,多个主机同时启动传输,可能检测到不止一个主机满足起始条件,而同时获得主机权,这样就要进行仲裁。当SCL 线是高电平时,仲裁在 SDA 线发生,当其他主机发送低电平时,发送高电平的主机将丢失仲裁,因为总线上的电平与它自己的电平不同。

仲裁可以持续多位,它的第一个阶段是比较地址位,如果每个主机都尝试寻址相同的器件,仲裁会继续比较数据位,或者比较响应位。因为 IIC 总线的地址和数据信息由赢得仲裁的主机决定,所以在仲裁过程中不会丢失信息。

(3) 用时钟同步机制作伪握手。器件可以快速接收数据字节,但可能需要更多时间保存接收到的字节或准备一个要发送的字节。此时,这个器件可以使 SCL 线保持低电平, 迫使与之交换数据的器件进入等待状态,直到准备好下一字节的发送或接收 。

7) 传输协议

(1) 寻址字节。主机产生起始条件后,发送的第一个字节为寻址字节。该字节的头 7位(高7 位)为从机地址,最低位(LSB)决定了报文的方向,“0”表示主机写信息到从机, “1”表示主机读从机中的信息,如图 2.14 所示。当发送了一个地址后,系统中的每个器件都将头 7 位与它自已的地址比较。如果一样,器件会应答主机的寻址,至于是从机-接收器还是从机-发送器都由R / W

位决定。



图2‑6 起始条件后的笫一个字节

从机地址由一个固定的部分和一个可编程的部分构成。例如,某些器件有 4 个固定的位(高4位)和 3 个可编程的地址位(低 3 位),那么同一总线上共可以连接 8 个相同的器件。IIC 总线委员会协调 IIC 地址的分配,保留了 2 组 8 位地址(0000XXX 和 1111XXX), 这 2组地址的用途可查阅有关资料。

(2) 传输格式。主机产生起始条件后,发送一个寻址字节,收到应答跟着就是数椐传输,数据传输一般由主机产生的停止位来终止。但是,如果主机仍希望在总线上通信,它可以产生重复起始条件(Sr)且寻址另一个从机,而不是首先产一个停止条件。在这种传输中,可能有不同的读/写格式结合。

数据的传输格式有以下三种 :

① 主机-发送器发送数据到从机-接收器,见图 2.15, 寻址字节的 “R/W” 位为 0,数据传输的方向不改变。

② 寻址字节后,主机-接收器立即读从机-发送器中的数据,见图 2.16,寻址字节的R/W

位为1。在第一次从机产生响应时, 主机-发送器变成主机-接收器,从机-接收器变成从机-发送器。之后,数据由从机发送,主机接收,每个应答由主机产生,时钟信号 CLK仍由主机产生。若主机要终止本次传输,则发送一个非应答信号(

/A),接着主机产生停止条件。



图2‑7 主机-发送器发送数据



图2‑8 寻址字节后,主机-接收器立即读数据

③ 复合格式,见图 2.17。 传输改变方向的时候,起始条件和从机地址都会被重复, 但

位取反。如果主机-接收器发送一个重复起始条件,它之前应该要发送一个非应答信号(

/A )。



图2‑9 复合格式

默认下,设备地址为八位宽,因此设备地址也称为设备字节。设备地址的高四位,即[7..4]记录硬件 ID,接续三位即 [3..1] 则记录硬件地址,最后一位则是设备的访问方向。结果如表2‑1所示:

表2‑1设备地址的位分配

[7]

[6]

[5]

[4]

[3]

[2]

[1]

[0]

硬件ID

硬件地址

访问方向

所谓硬件 ID 就是 IIC 设备的辨识 ID,硬件 ID 会随着厂商还有设备的种类而有所改变。开发板上的 IIC 设备是某厂商的 IIC 储存器,即 24LC04,硬件 ID 为 4’b1010。至于硬件地址就是 IIC 设备在总线上辨识地址,默认下为 3 位,即同类的 IIC 设备在同一条 IIC总线上仅允许占据 8 个而已。然而,开发板上的 24LC04 为 3’b000。最后的访问方向位则是主机用来通知从机,此刻的访问目的是读还是写。

总结来说,设备地址除了访问方向以外,前七位一般都是固定的,例如常见的开发板的 IIC 储存器 24LC04,设备地址就是 8’b1010_000_×。



图2‑10 24LC04 的写操作(主机视角)

IIC 总线的时序,感觉上一组完成的操作宛如是一堆拼图。如图2‑10所示,那是 24LC04的写操作,时序先填上为起始位,再来是设备地址,余下是应答位,随之是数据地址,然后又是应答位,接着是写如数据,再一次应答位,最后挂上结束位以示一次性的写操作已经完成。那么,写操作的经过如下所示:

(一) 主机发送起始位;

(二) 主机发送设备地址(写);

(三) 等待从机应答;

(四) 主机发送数据地址;

(五) 等待从机应答;

(六) 主机发送数据;

(七) 等待从机应答;

(八) 主机发送结束位。

稍微注意一下设备地址的最低位。由于此刻是写操作,所以设备地址的访问方向是“写”,所以访问方向位设置为 0。



图2‑11 24LC04 的读操作(主机视角)

图2‑11是 24LC04 的读时序,同样它也是由一堆“拼图”组合而成。相较写操作,读操作不仅多了许多“拼图”,而且途中也改变访问方向。那么,读操作的经过如下所示:

(一) 主机发送起始位;

(二) 主机发送设备地址(写);

(三) 等待从机应答;

(四) 主机发送数据地址;

(五) 主机发送起始位;

(六) 主机发送设备地址(读);

(七) 等待从机应答;

(八) 主机读取数据;

(九) 从机没有应答(主机无视应答);

(十) 主机发送结束位。

IIC总线上数据的传输速率在标准模式下可达100kb/s,在快速模式下可达400kb/s,在高速模式下可达3.4Mb/s。实验十六会以 400Khz 的速率作为标准。连接到总线的接口数量由总线电容是400pF的限制决定。在此,实验会以 400Khz 的速率作为标准。

在进行IIC时序分析时,必须要考虑芯片的时序,见下表:



图2‑12 芯片 24LC04 的时序表

IIC 总线是一种串行传输协议,既有时钟信号 SCL,还有数据信号 SDA。 Clock Frequency表示 SCL 信号的频率, Clock High Time 表示 SCL 信号保持高电平所需的最小时间,Clock Low Time 则表示 SCL 信号保持低电平所需的最小的时间。

至于 Rise Time 与 Fall Time 表示, SCL 信号还有 SDA 信号由高变低或者由低变高时所需的最小时间,即上山与下山时间。 Hold Time 与 Setup Time 是用来评估数据是否成功打入寄存器的时序参数,算是典型中的典型。 Setup Time 表示建立时间,即数据写入寄存器之前所需的稳定时间;反之, Hold Time 则是保持时间,即数据打入寄存器之后所需的稳定时间。只要两者得到满足,那么数据的寄存活动就得到确保。

Start 是 IIC 总线的起始位, Stop 是 IIC 总线的结束位, Data 是 IIC 总线的数据位,为了确保三者成功写入从机, Setup Time 与 Hold Time 必须得到满足。 Ouput Valid FromClock 是关系数据位的时序参数,还有 Bus Free Time 是关系结束位的时序参数。此外, 为了简化时序,笔者将各种参数的实际时间转换为 50Mhz 量化以后的结果。将上表进行解读如下:

表2‑2 各种时序参数( 50Mhz 量化)



Clock Frequency,既是频率也是速率,在此是 400Khz。

Clock High Time,既 SCL 信号保持高电平所需的最小时间。

Clock Low Time,既 SCL 信号保持低电平所需的最小时间。

Rise Time,既信号由底变高所需最大的时间。

Fall Time,既信号又高变低所需最小的时间。

Start Hold Time,既起始位所需最小的保持时间。

Start Setup Time,既起始位所需最小的建立时间。

Data Input Hold Time,既数据位所需最小的保持时间。

Data Input Setup Time,既数据位所需最小的建立时间。

Stop Setup Time,既结束位所需的最小保持时间。

Ouput Valid From Clock,既数据位经时钟沿触发以后的有效时间。

Bus Free Time,既释放总线的最小时间。

1.1.2IIC协议的FPGA实现



图2‑13 IIC模块的建模图

图2‑13是 IIC 储存模块的建模图,左边是顶层信号,右边则是沟通用的问答信号,写入地址 iAddr,写入数据 iData,还有读出数据 oData。 Call/Done 有两位,即表示该模块有读功能还有些功能。具体内容,我们还是来看代码吧:

代码2‑1 IIC代码声明

1.parameter FCLK = 10'd125, FHALF = 10'd62, FQUARTER = 10'd31;

2.parameter THIGH = 10'd30, TLOW = 10'd65, TR = 10'd15, TF = 10'd15;

3.parameter THD_STA = 10'd30, TSU_STA = 10'd30, TSU_STO = 10'd30;

如代码2‑1 所示, FCLK 表示 400Khz 的周期, FHALF 表示 1/2 周期, FQUARTER 表示 1/4 周期。



图2‑14 起始位

首先让我们先瞧瞧起始位这枚拼图。如图2‑14所示,左图是起始位的理想时序,右图是起始位的物理时序。 IIC 总线的起始位也就类似串口或者 PS/2 等传输协议的起始位,然而不同的是, IIC 总线的起始位是 SCL 拉高 TR + TSU_STA + THD_STA + TF 之久,换之 SDA 则是拉高 TR + THIGH 然后拉低 TF + TLOW。起始位总和所用掉的时间,恰恰好有一个速率的周期。对此, Verilog 则可以这样描述,结果如下所示:

代码2‑2 IIC起始位产生代码

1.begin

2.     isQ = 1;

3.     rSCL <= 1'b1;

4.     if( C1 == 0 ) rSDA <= 1'b1;

5.     else if( C1 == (TR + THIGH) ) rSDA <= 1'b0;

6.     if( C1 == (FCLK) -1) begin C1 <= 10'd0; i <= i + 1'b1; end

7.     else C1 <= C1 + 1'b1;

8.end

如代码2‑2所示,第 2 行的 isQ = 1 表示设置 SDA 为输出状态(即时结果),第 3 行则表示 SCL 一直持续拉高状态,第 4~5 行表示 C1 为 0 的时候 SDA 拉高,直到 C1 为TR+THIGH 才拉低 SDA。第 6~7 行表示一个步骤所逗留的时间。



图2‑15 结束位

图2‑15是结束位的时序图, IIC 设备的操作好坏一般都取决结束位。保险起见, SCL 与SDA 都事先拉低 1/4 周期,紧接着 SCL 会拉高 TR+TSU_STO(或者 1/2 周期),最后又保持高电平 1/2 周期。反之, SDA 会拉低 1/2 周期,随之拉高 TR+THIGH(或者 1/2周期)。对此, Verilog 可以这样表示,结果如代码2‑3所示:

代码2‑3 IIC结束位代码实现

1.begin

2.    isQ = 1'b1;

3.      

4.    if( C1 == 0 ) rSCL <= 1'b0;

5.    else if( C1 == FQUARTER ) rSCL <= 1'b1;  

6.      

7.      if( C1 == 0 ) rSDA <= 1'b0;

8.      else if( C1 == (FQUARTER + TR + TSU_STO ) ) rSDA <= 1'b1;

9.      

10.      if( C1 == (FQUARTER + FCLK) -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end

11.      else C1 <= C1 + 1'b1;  

12.end

如代码2‑3所示,第 2 行表示 SDA 为输出状态(即时),第 3~4 行表示 C1 为 0 拉高SCL, C1 为 1/4 周期就拉高。第 5~6 行表示, C1 为 0 拉低 SDA, C1 为 1/4 周期 + TR +TSU_STO 就拉高 SDA。第 7~8 行表示该步骤所逗留的时间。



图2‑16 释放总线

此外,结束位还有 Bus Free Time 这个时序参数,IIC 总线在闲置的状态下 SCL 与 SDA等信号都持续高电平。主机发送结束位以示结束操作,然而主机持续拉高 SCL 信号与SDA 信号 TBUF 以示总线释放。 TBUF 的有效时间从 SCL 信号与 SDA 信号拉高那一刻开始算起

根据表2‑2 所示, TBUF 是 65 个时钟,结果如图 16.6 所示, SDA 信号拉高之后, SCL与 SDA 信号只要持续保持 1/2 周期(即 62 个时),基本上就能满足 TBUF。如果笔者是一位紧密控时狂人,可能无法接受这样的结果,因为满足 TBUF 少了 3 个时钟,为此代码2‑3需要更动一下:

代码2‑4 IIC结束位代码修改

1.if( C1 == ( FQUARTER + FCLK + 3) -1 )  

2.     begin C1 <= 10'd0; i <= i + 1'b1; end

3.else C1 <= C1 + 1'b1;

如代码2‑4所示,笔者为第 1 行写下 +3 表示该步骤多逗留 3 个时钟,以致满足 TBUF。



不管对象是设备地址,数据地址,写入数据,读出数据,还是应答位,大伙都视为数据位。 IIC 总线类似其他传输协议,它有时钟信号也有上升沿与下降沿。如图 16.7 所示,SCL 信号的下降沿导致设备设置(更新)数据,上升沿则是锁存(读取)数据。期间,TF+TLOW 表示时钟信号的前半周期, TR+THIGH 则表示后半周期。此外,为了确保数据成功打入寄存器,数据被上升沿锁存哪一刻起, TSU_DAT 还有 THD_DAT 必须得到满足。



图2‑17 数据位更新有效

除此之外,为了确保数据有效被更新,也必须确保 TAA 得到满足,结果如图2‑17所示。理解完毕以后,就可以开始学习,写一字节数据与读一字节数据,还有应答位。



图2‑18 写一字节

IIC 总线一般都是一个字节一个字节读写数据,如图2‑18 所示,那是写一字节的理想时序图,一字节数据是从最高位开始写起。对此, Verilog 可以这样描述,结果如代码2‑5所示:

代码2‑5 IIC 总线写一个字节

1.7,8,9,10,11,12,13,14:

2.begin

3.    isQ = 1'b1;

4.    rSDA <= D1[14-i];

5.    if( C1 == 0 ) rSCL <= 1'b0;

6.    else if( C1 == (TF + TLOW) ) rSCL <= 1'b1;  

7.    if( C1 == FCLK -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end

8.    else C1 <= C1 + 1'b1;

9.end

如代码2‑5 所示,第 1 行有 8 个步骤,表示写一个字节。第 3 行 isQ 为 1 表示 SDA 为输出状态。第 4 行表示从最高位开始更新 SDA 的数据位。第 5~6 行表示, C1 为 0 拉低SCL, C1 为 TF+TLOW 则拉高 SCL。第 7~8 行表示该步骤逗留一个周期的时间。



图2‑19 应答位

应答位是从机给予主机的回答, 0 为是,1 为否。然而,从旁观看,读取应答位也是读取一位数据位。当主机完成写入一个字节或者读取一个字节数据的时候,从机都会产生应答位。主机拉低 SCL 那刻,从机便会发送应答位,然后主机会借由上升沿读取应答位。如图2‑19 所示,上升沿会产生在 TF + TLOW 之后,也是 1/2 周期。对此, Verilog 可以这样表示,结果如代码2‑6所示:

代码2‑6 IIC应答位

1.begin

2.    isQ = 1'b0;

3.     

4.  if( C1 == FHALF ) isAck <= SDA;

5.   

6.  if( C1 == 0 ) rSCL <= 1'b0;

7.  else if( C1 == FHALF ) rSCL <= 1'b1;

8.   

9.  if( C1 == FCLK -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end

10.  else C1 <= C1 + 1'b1;  

11.end

如代码2‑6所示,第 2 行表示 SDA 为输入状态。第 4~5 行表示, C1 为 0 拉低 SCL,C1 为 1/2 周期则拉高 SCL。第 3 行表示, C1 为 1/2 周期的时候读取应答位。第 6~7 行表示该步骤逗留 1 个周期的时间。



图2‑20 读一字节

所谓读一字节数据就是重复读取 8 次应答位。如图2‑20所示, SCL 的下降沿导致从机更新数据,然后主机在 SCL 的上升沿读取数据。此外,从机也会由高至低更新数据位。至于 Verilog 则可以这样表示,结果如代码2‑7所示:

代码2‑7 IIC读一字节

1.19,20,21,22,23,24,25,26: // Read

2.begin

3.    isQ = 1'b0;

4.    if( C1 == FHALF ) D1[26-i] <= SDA;

5.   

6.  if( C1 == 0 ) rSCL <= 1'b0;

7.  else if( C1 == FHALF  ) rSCL <= 1'b1;  

8.   

9.  if( C1 == FCLK -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end

10.  else C1 <= C1 + 1'b1;

11.end   

如代码2‑7所示,第 1 行表示读取一字节。第 3 行表示 SDA 为输入状态,第 5~6 行表示, C1 为 0 拉低 SCL, C1 为 1/2 周期则拉高 SCL。第 4 行表示, C1 为 1/2 周期的时候读取数据,而且数据位由高至低存入 D1。第 7~8 行表示该步骤逗留一个周期的时间。



图2‑21 第二次起始位

知道主机向从机读取数据的时候,它必须改变设备地址的方向,因此读操作又第二次起始位。如图2‑21所示,感觉上第二次起始位也是第一次起始位,不过为了促使改变方向成功,第二次起始位相较第一次起始位的前后都拉低 1/4 周期。对此, Verilog 可以这样表示,结果如代码2‑8所示:

代码2‑8 IIC第二次起始位

1.begin

2.     isQ = 1'b1;

3.     if( C1 == 0 ) rSCL <= 1'b0;

4.     else if( C1 == FQUARTER ) rSCL <= 1'b1;

5.     else if( C1 == (FQUARTER + TR + TSU_STA + THD_STA + TF) ) rSCL <= 1'b0;

6.  

7.     if( C1 == 0 ) rSDA <= 1'b0;

8.     else if( C1 == FQUARTER ) rSDA <= 1'b1;

9.     else if( C1 == ( FQUARTER + TR + THIGH) ) rSDA <= 1'b0;

10.  

11.     if( C1 == (FQUARTER + FCLK + FQUARTER) -1 ) begin C1 <= 10'd0; i <= i + 1'b1; end

12.     else C1 <= C1 + 1'b1;

13.end

如代码2‑8 所示,第 2 行表示 SDA 为输出状态。第 3~5 行表示, C1 为 0 拉低 SCL,C1 为 1/4 周期拉高 SCL, C1 为 1/4 周期 + TR + TSU_STA + THD_STA + TF 便拉低SCL。第 7~9 行表示, C1 为 0 拉低 SDA, C1 为 1/4 周期拉高 SDA, C1 为 1/4 周期 + TR+ THIGH 便拉低 SDA。第 11~12 行表示该步骤停留一个周期的时间。

接下来是仿真验证,结果如下:





图2‑22 IIC总线仿真时序图

结合上述仿真波形图和程序可以看出:

起始位:SCLK为高电平时,SDAT由高到低,指示IIC总线传输数据的开始;

之后,传送一个字节的数据,即4A,为从机的地址,随后,跟了一个高电平,为应答位;

  之后,传送一个字节的数据,即01,为从机地址的子地址,随后,跟了一个高电平,为应答位;

  之后,传送一个字节的数据,即08,为上面子地址寄存器配置的数据,随后,跟了一个高电平,为应答位;

  最后,为停止位,SCLK为高电平时,SDAT由低到高,指示该次IIC总线传输数据的结束。

  由仿真结果可知,当传送完一个字节后,SDAT为一个脉冲的高电平,而不是从器件先将SDAT拉低再拉高,这样也是可以的。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则