基本串行通信接口
很多SPI器件并不是单独寻址的。因此,这些器件和总线上其它单个器件通信时,就需要进行额外的硬件或者软件处理。图1所示是一个微控制器和多个从器件通信的系统。![图1. 带有多个从器件独立片选信号的微控制器。](http://www.maxim-ic.com.cn/images/appnotes/3947/3947Fig01.gif)
图1. 带有多个从器件独立片选信号的微控制器。
在上述系统中,微控制器通过一个串行时钟输出(SCLK)和一个主机输出/从机输入(MOSI)信号线向各从器件发送命令。主机为每个器件分配了一个独立的片选信号(/SS_),从而实现各个从器件的独立寻址。由于所有从器件共享同一个时钟和数据线,只有/CS输入变低的从器件才会应答串行时钟和数据线。当从器件数目较少时,该系统较易实现。如果系统中从器件数较多,微控制器需要提供和从器件一样多的/SS_输出,这种结构就增加了硬件和布板的复杂程度。
菊链方法
硬件空间方面的限制往往会使图1所示的电路无法实现或难以实现。可采用菊链法替代实现串行接口。图2是一个有N个从器件的菊链系统结构。![图2. 微控制器连接多个从器件](https://i-blog.csdnimg.cn/blog_migrate/d1380937be483e071e8e784edc924fe5.gif)
图2. 微控制器连接多个从器件
采用一个/SS (或者/CS)信号控制所有从器件的/CS输入;所有从器件接收同一个时钟信号。只有链上的第一个从器件(SLAVE 1)从微控制器直接接收命令。其他所有从器件都从链上前一个器件的DOUT输出获得其DIN数据。
要保证菊链正常工作,每一个从器件就必须能在给定的命令周期内(定义为每一个命令所需的时钟数)从DIN引脚读入命令,而在下一个命令周期从DOUT引脚输出同样的命令。显然,从DIN到DOUT会有一个命令周期的延迟。另外,各个从器件只能在/CS的上升沿执行写入的命令。这意味着只要/CS保持低电平,从器件将不会执行命令,并且会在下一个命令周期将命令通过DOUT引脚输出。如果在给定命令周期之后/CS变高,所有从器件将立即执行写入DIN引脚的命令。如果/CS变高,数据将不会从DOUT输出,这就使得链上每个从器件可以执行不同的命令。只要菊链的这些要求能够满足,微控制器只需三个信号(/SS、SCK和MOSI)就能控制网络上的所有从器件。
如何实现菊链
在菊链系统中(图2),SLAVE 1从微控制器直接接收数据。该数据在时钟驱动下进入SLAVE 1的内部移位寄存器。只要/CS (或/SS)仍然保持低电平,该数据将通过SLAVE 1的DOUT引脚输出。SLAVE 1的DOUT引脚接至SLAVE 2的DI引脚,因此当数据通过SLAVE 1的DOUT引脚端输出时,同时也被同步移入SLAVE 2的内部移位寄存器。同理,当SLAVE 2接收来自SLAVE 1的数据的时候,微控制器可同时向SLAVE 1发送另一个命令。该新命令将覆盖SLAVE 1移位寄存器中原来的数据。只要/CS保持为低,数据会在整条菊链上传递,直到每一个从器件都接收了相应的命令。存储在每一个从器件移位寄存器中的命令将在/CS的上升沿执行。下面例子使用MAX5233和MAX5290构成菊链。电路图范例#1
图3给出的菊链结构中连接了3个MAX5233。MAX5233为双路、10位DAC (包含两个DAC通道,通道A和B)。将RSTV接至VDD,模拟输出的上电状态被设置到中点。![图3. 菊链电路#1](https://i-blog.csdnimg.cn/blog_migrate/924198d2e3f8ddb9065f5c6ba91a74b2.gif)
图3. 菊链电路#1
图4给出了将IC1 (A1和B1)、IC2 (A2和B2)和IC3 (A3和B3)的输出分别设为零点、中点和满刻度的命令序列图。在这个例子中,使用了以下的命令:
- 0x7FF8—将满刻度数据加载到IC3 DAC寄存器,并将两路输出(A3、B3)设置到满刻度
- 0x7000—将满刻度数据加载到IC2 DAC寄存器,并将两路输出(A2、B2)设置到中点
- 0x6000—将满刻度数据加载到IC1 DAC寄存器,并将两路输出(A1、B1)设置到零点
![图4. 电路#1—命令时序A](https://i-blog.csdnimg.cn/blog_migrate/e9fcc49f342064373ff345011c0349eb.gif)
图4. 电路#1—命令时序A
在第一个命令周期(16个SCLK脉冲序列),将0x7FF8载入IC1的移位寄存器。当/CS保持低电平,这一数据将在IC1内传递,并且在下一个命令周期内通过DOUT1输出。在第二个命令周期内,IC1输出端DOUT1上的数据输入到DIN2,将0x7FF8载入IC2的移位寄存器中。同时,新的命令0x7000将载入IC1移位寄存器,覆盖了前一个命令。
第三个命令周期内,第一个命令0x7FF8将载入IC3的移位寄存器,而第二个命令0x7000将载入IC2的移位寄存器,同时IC1将接收到新的命令0x6000。此时,三个IC都从菊链上接收到命令并存储在他们的移位寄存器中。一旦/CS变高,将执行已存储的命令;A1和B1被设为零点、A2和B2被设为中点、A3和B3被设为满刻度。
图5给出了更为复杂的命令序列。在这个例子中,使用以下的命令(更多详细信息,请参考MAX5233数据资料):
- 0x3FF8—将满刻度数据加载到输入寄存器A,不改变DAC寄存器和输出
- 0x3000—将中点数据加载到输入寄存器A,不改变DAC寄存器和输出
- 0x2000—将零点数据加载到输入寄存器A,不改变DAC寄存器和输出
- 0xBFF8—将满刻度数据加载到输入寄存器B,不改变DAC寄存器和输出
- 0xB000—将中点数据加载到输入寄存器B,不改变DAC寄存器和输出
- 0xA000—将零点数据加载到输入寄存器B,不改变DAC寄存器和输出
- 0x0000—空操作
![图5. 电路#1—命令序列B](https://i-blog.csdnimg.cn/blog_migrate/f02dc78962b92e44034b309cf1b272b0.gif)
图5. 电路#1—命令序列B
在第一个三命令周期内,菊链上三个IC中的各个器件的移位寄存器军接收到一条命令。IC1、IC2、IC3接收到的命令分别为0xB000、0xBFF8和0xBFF8。 器件将在/CS的上升沿执行这些命令(第一次执行)。执行完之后,IC1、IC2、IC3的输入寄存器B中分别加载了中点、满刻度和满刻度的数据。此时,由于各IC的DAC寄存器B保持不变,因此B1、B2、B3均未改变。
在接下来的三命令周期内,每个IC的移位寄存器中均写入了仅向输入寄存器A加载数据的命令。DAC寄存器A和输出保持不变。在/CS的上升沿,IC1、IC2、IC3的输入寄存器A分别加载了满刻度、零点和中点数据。此时,由于只更新了输入寄存器A而不是DAC寄存器A,因此A1、A2、A3均保持不变。
在第二次执行命令之后,硬件/LDAC命令(驱动/LDAC为低)将输入寄存器中的数据加载到相应的DAC寄存器中。这样,DAC的输出就被刷新为相应的DAC寄存器中的数据。A1、B2和B3变为满刻度。A2变为零点而A3仍为中点状态。
在第三个命令周期,IC2和IC3接收了空操作命令(0x0000),而IC1接收0xA000命令,将零点数据加载到IC1的输入寄存器B。第三次执行命令之后,所有的输出仍旧没有改变。
在第四个命令周期内,IC1和IC2接收空操作命令,而IC3接收到0x3FF8命令。第四次执行命令之后,IC3的输入寄存器A加载满刻度数据。另一个硬件/LDAC命令将输入寄存器的数据加载到相应DAC寄存器。这将使B1从中点变为零点,A3从中点变为满刻度。其他的输出仍旧不变。
表1. 命令序列B中,上电后以及执行硬件/LDAC命令后,IC1、IC2和IC3的输出状态
Analog Output Name |
| |||
After Power-Up (RSTV = VDD) | First Hardware Active-Low LDAC | Second Hardware Active-Low LDAC | ||
IC1 | A1 | Midscale | Full scale | Full scale |
B1 | Midscale | Midscale | Zero scale | |
IC2 | A2 | Midscale | Zero scale | Zero scale |
B2 | Midscale | Full scale | Full scale | |
IC3 | A3 | Midscale | Midscale | Full scale |
B3 | Midscale | Full scale | Full scale |
电路范例#2
图6给出的菊链结构中有三个MAX5290 (双路12位DAC)。将PU接至DVDD,则上电时模拟输出设置为满刻度。MAX5290没有专用于菊链的数字输出。因此,需通过串口将两个UPIO (用户可编程输入/输出)引脚中的任意一个编程设置为DOUTDC_模式。更多详细信息请见MAX5290数据资料。![图6. 菊链电路#2](https://i-blog.csdnimg.cn/blog_migrate/5f0c4abaddfbfb09bc89ea68ad5aa795.gif)
图6. 菊链电路#2
图7给出了命令序列示例,使用了以下的命令(更多详细信息请见MAX5290数据资料)。
- 0xDFFF—将满刻度数据加载到所有输入寄存器和DAC寄存器,刷新DAC的A和B输出
- 0xD800—将中点数据加载到所有输入寄存器和DAC寄存器,刷新DAC的A和B输出
- 0xD000—将零点数据加载到所有输入寄存器和DAC寄存器,刷新DAC的A和B输出
- 0xE400—将DAC的A和B输出置于关断模式
- 0xE40F—使DAC的A和B输出跳出关断模式
- 0xFFFF—空操作
![图7. 电路#2命令时序示例](https://i-blog.csdnimg.cn/blog_migrate/d9cd194cbc806be218bb4e9b59355df3.gif)
图7. 电路#2命令时序示例
器件在/CS上升沿时执行已经加载到每个器件移位寄存器中的命令。第一次执行命令后,所有DAC输出均刷新。IC1的DAC输出为零点,IC2的DAC输出为中点,而IC3的DAC输出为满刻度。
第二个命令周期时,执行命令0xE400,IC2的DAC的A和B输出都进入关断模式。IC1和IC3由于执行空操作命令而不受影响。第三个命令周期后,IC1的输出变为满刻度,IC3的输出变为零点。而IC2的输出仍处于关断模式,其内部输入寄存器和DAC寄存器数据已被刷新。在最后的命令周期,IC2恢复正常工作模式,所有输出变为满刻度。
表2. 命令序列示例中,上电后和执行命令后,IC1、IC2、IC3的输出状态
Analog Output Name |
| |||||
After Power-Up (PU = VDD) | After First Excution | After Second Execution | After Third Execution | After Fourth Execution | ||
IC1 | A1 | Full scale | Zero scale | Zero scale | Full scale | Full scale |
B1 | Full scale | Zero scale | Zero scale | Full scale | Full scale | |
IC2 | A2 | Full scale | Midscale | Shutdown | Shutdown | Full scale |
B2 | Full scale | Midscale | Shutdown | Shutdown | Full scale | |
IC3 | A3 | Full scale | Full scale | Full scale | Zero scale | Zero scale |
B3 | Full scale | Full scale | Full scale | Zero scale | Zero scale |