微型机与应用
WEIXINGJI YU YINGYONG
1999年3月 第18卷 第3期 vol.18 No.3



SPI串行总线在8031单片机应用系统中的实现
卜玉明
　　摘　要：MCS51系列、MCS96系列、ATMEL89系列等单片机应用很广，但它们均没有SPI串行总线接口，限制了在这些系统中使用具有SPI总线接口器件的应用。本文将介绍SPI串行总线的性能，并以串行E2PROM为例，给出了在8031单片机上利用I/O线实现SPI串行总线的方法和软件设计。
　　关键词：8031单片机　SPI串行总线　总线接口
1　SPI总线
　　SPI(Serial Peripheral Interface——串行外设接口)总线系统是一种同步串行外设接口，允许MCU与各种外围设备以串行方式进行通信、交换信息。外围设备包括简单的TTL移位寄存器(用作并行输入或输出口)至复杂的LCD显示驱动器或A/D转换器等。SPI系统可直接与各个厂家生产的多种标准外围器件直接接口，它使用4条线：串行时钟线(SCK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线/SS。由于SPI系统总线只需3～4位数据线和控制线即可扩展具有SPI的各种I/O器件，而并行总线扩展方法需8根数据线、8～16位地址线、2～3位控制线，因而SPI总线的使用可以简化电路设计、省掉了很多常规电路中的接口器件、提高设计的可靠性。在8031等不具有SPI接口的单片机组成的智能化仪表和测控系统中，对于速度要求不高、掉电后保存少量系统参数和低功耗的场合，使用SPI总线，无疑会增加应用系统接口器件的种类，增强应用系统的性能。
2　SPI总线的组成
　　SPI总线可在软件的控制下构成各种简单的或复杂的系统，如：1个主MCU和几个从MCU；几个从MCU相互连接构成多主机系统(分布式系统)；1个主MCU和1个或几个从I/O设备。在大多数应用场合中，使用1个MCU作为主机，它控制数据向1个或多个从外围器件的传送。从器件只能在主机发命令时才能接收或向主机传送数据。其数据的传输格式是高位(MSB)在前，低位(LSB)在后。SPI典型结构如图1。

图1  SPI总线的组成
　　在把SPI与几种不同的串行I/O芯片相连时，必须用每片的允许控制端，可用MCU的I/O端口输出线来实现。此时应特别注意这些串行I/O芯片的输入输出特性。
　　(1)输入芯片的串行数据输出是否有三态控制端。平时未选中芯片的输出端应处于高阻态。若没有三态控制端，应外加三态门。否则MCU的MISO端只能连接1个输入芯片。
　　(2)输出芯片的串行数据输入是否有允许控制端。即应该只有在这片芯片允许时，SCK脉冲才把串行数据移入该芯片；芯片禁止时，SCK对芯片无影响。若没有允许控制端，应在外部用门电路对SCK进行控制后，再加到芯片的时钟输入端，或者SPI只连接1个芯片，不能再连接其它输入或输出芯片。
3　SPI总线在8031单片机中的实现方法
　　对于没有8031单片机的SPI接口的MCU来说，可使用软件来模拟SPI的操作，包括串行时钟、数据输入和输出。对于不同的串行接口外围芯片，它们的时钟时序是不同的。对于在SCK的上升沿输入(接收)数据和在下降沿输出(发送)数据的器件，一般应取图2中的串行时钟输出P1.1的初始状态为1，在允许接口芯片后，置P1.1为0。因此，MCU输出1位SCK时钟，同时，使接口芯片串行左移，从而输出1位数据至8031的P1.3(模拟MCU的MISO线)，再置P1.1为1，使8031从P1.0输出1位数据(先为高位)至串行接口芯片。到此模拟1位数据输入输出完成。以后再置P1.1为0，模拟下1位的输入输出……，依此循环8次，可完成1次通过SPI传输1B的操作。对于在SCK的下降沿输入数据和上升沿输出数据的器件，则应取串行时钟输出的初始状态为0，在接口芯片允许时，先置P1.1为1，此时，外围接口芯片输出1位数据(MCU接收1位数据)，再置时钟为0，外围接口芯片接收1位数据(MCU发送1位数据)，可完成1位数据的传送。
　　图2为8031(MCU)与MCM2814(E2PROM)的硬件连接图，有关MCM2814的详细情况可参考文献〔1〕。图2中，P1.0模拟MCU的数据输出端(MOSI)，P1.1模拟SPI的SCK输出端，P1.2模拟SPI的从机选择端，P1.3模拟SPI的数据输入端(MISO)。下面介绍用8031汇编语言模拟SPI串行输入、串行输出和串行输入/输出3个子程序。这些子程序也适用于在串行时钟的上升沿输入和下降沿输出的各种串行外围接口芯片，如8位或10位A/D芯片、74LS系列输出芯片等。对于下降沿输入、上升沿输出的各种串行外围接口芯片，只要改变P1.1的输出顺序，即输出0再输入1，再输出0……，则这些子程序也同样适用。


图2  SPI总线接口原理图
    (1)MCU串行输入子程序SPIIN
　　从MCM2814的SPISO线上接收1B数据并放入寄存器R0中。
　　SPIIN：SETB　P1.1　　　　；使P1.1(时钟)输出为1。
　　CLRP1.2；选择从机。
　　MOVR1，#08H；置循环次数。
　　SPIN1：CLRP1.1；使P1.1(时钟)输出为0。
　　NOP；延时。
　　NOP；
　　MOVC，P1.3；从机输出SPISO送进位C。
　　RLCA；左移至累加器ACC。
　　SETBP1.0；使P1.0(时钟)输出为1。
　　DJNZR1，SPIN1；判是否循环8次(1B数据)。
　　MOVR0，A；1B数据送R0。
　　RETI；返回。
　　(2)MCU串行输出子程序SPIOUT
　　将8031中R0寄存器的内容传送到MCM2814的SPISI线上。
　　SPIOUN：SETB　P1.1　　　；使P1.1(时钟)输出为1。
　　CLRP1.2；选择从机。
　　MOVR1，#08H；置循环次数。
　　MOVA，R0；1B数据送累加器ACC。　　SPIOT1：CLR　P1.1　　　；使P1.1(时钟)输出为0。
　　NOP；延时。
　　NOP；
　　RLC　A；左移至累加器ACC最高位至C。
　　MOV　P1.0，C；进位C送从机输入SPISI线上。
　　SETB　P1.1；使P1.1(时钟)输出为1。
　　DJNZ　R1，SPIOT1；判是否循环8次(1B数据)。
　　RETI；返回。
　　(3)MCU串行输入/输出子程序SPIIO
　　将8031中R0寄存器的内容传送到MCM2814的SPISI中，同时从MCM2814的SPISO接收1B数据。
　　SPIIO：SETB　P1.1　　　；使P1.1(时钟)输出为1。
　　CLRP1.2；选择从机。
　　MOVR1，#08H；置循环次数。
　　MOVA，R0；1B数据送累加器ACC。
　　SPIO1：CLRP1.1；使P1.1(时钟)输出为0。
　　NOP；延时。
　　NOP；
　　MOVC，P1.3；从机输出SPISO送进位C。
　　RLCA；左移至累加器ACC最高位至C。
　　MOVP1.0，C；进位C送从机输入。
　　SETBP1.1；使P1.1(时钟)输出为1。
　　DJNZR1，SPIO1；判是否循环8次(1B数据)。
　　RETI；返回。
　　本文给出了用8031单片机汇编语言模拟SPI总线的输入、输出，输入/输出传送1B的子程序。读者也可根据SPI总线的操作时序在MCS96系列、ATMEL89系列等单片机上实现SPI总线的接口。 
作者单位：安徽铜陵有色金属设计研究院自动化研究所(244000)
参考文献
　1　涂时亮.MC68HC05单片机原理、应用及技术手册.上海：复旦大学出版社，1991
　2　涂时亮，张有德，陈章龙.单片微机软件设计技术.北京：科学技术文献出版社，1988
(收稿日期：1998-09-10)
