串行外设接口(Serial Peripheral Interface)是一种同步外设接口,它可以使单片机与各种外围设备以串行方式进行通信以交换信息。SPI最早是Motorola公司提出的全双工三线同步串行外围接口,采用主从模式(Master—Slave)架构,支持一个或多个Slave设备,由于其简单实用、性能优异,因此许多厂家的设备都支持该接口,广泛应用于单片机和外设模块之间的连接。
SPI接口只需4条线:串行时钟线(SCK)、主机输入/从机输出数据线(MISO)、主机输出/从机输人数据线(MOSI)和低电平有效的从机选择线(SS)。
(1)MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。
(2)MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
(3)SCK:串口时钟,作为主设备的输出,从设备的输入。
(4)SS:从设备选择。这是一个可选的引脚,用来选择主/从设备。它的功能是用来作为片选引脚,让主设备可以单独地与特定从设备通信,避免数据线上的冲突。
SPI是一个环形总线结构,MOSI引脚相互连接,MISO引脚相互连接,数据在主和从之间串行地传输(MSB位在前),具体如下图所示。
SPI有主从两种工作模式,在主模式下,SPI为其他节点的CLK引脚提供串行时钟,数据从MOSI引脚输出,从MISO引脚输入。在从模式下,数据从MISO引脚移出并由MOSI引脚移入,CLK引脚作为串行移位时钟的输入。
LPC824片内设计有SPI接口,具体的引脚取决于开关矩阵SWM的配置。
LPC824的SPI接口具有以下特点:
•直接支持1至16位的数据发送。软件支持更大的帧。
•主机和从机操作。
•无需读取输入数据即可将数据发送至从机,这在设置SPI存储器的时候很有用。
•控制信息还可与数据一同写入,这样便实现了极为丰富的操作,包括任意长度的帧。
•最多4个从机选择输入/输出,极性可选且使用灵活。
•支持DMA传输,SPIn发送与接收功能可配合系统DMA控制器使用。
下图是SPI接口的功能框图。
在LPC824中,一共有两组SPI接口,分别为SIP0和SPI1。其中SPI0组接口有7根引脚(SCK、MOSI、MISO及SSEL0~3),SPI1组接口有5根引脚(SCK、MOSI、MISO及SSEL0~1)。在默认状态下,这些引脚并没有被分配到芯片的物理引脚上,所以在使用SPI功能之前,需要先配置SWM矩阵,以把这些引脚部分或全部连接到物理引脚上。下面给出了这些引脚各自的SWM配置寄存器。
从上表中可以看出,两个SPI接口的共12个引脚可以被分配到任意一个物理引脚上,涉及的配置寄存器为PINASSIGN3~PINASSIGN6共4个,接下来就分别给出这4个寄存的具体结构。
下表给出的是引脚分配寄存器PINASSIGN3的全部位结构,其字节地址为0x4000C00C。
(1)第0到7位为串口USART2中的请求发送端RTS分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(2)第8到15位为串口USART2中的清除发送端CTS分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(3)第16到23位为串口USART2中的同步时钟端SCLK分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(4)第24到31位为SPI0接口中的时钟端SCK分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
下表给出的是引脚分配寄存器PINASSIGN4的全部位结构,其字节地址为0x4000C010。
(1)第0到7位为SPI0接口中的主出从入端MOSI分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(2)第8到15位为SPI0接口中的主入从出端MISO分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(3)第16到23位为SPI0接口中的片选端SSEL0分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(4)第24到31位为SPI0接口中的片选端SSEL1分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
下表给出的是引脚分配寄存器PINASSIGN5的全部位结构,其字节地址为0x4000C014。
(1)第0到7位为SPI0接口中的片选端SSEL2分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(2)第8到15位为SPI0接口中的片选端SSEL3分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(3)第16到23位为SPI1接口中的时钟端SCK分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(4)第24到31位为SPI1接口中的主出从入端MOSI分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
下表给出的是引脚分配寄存器PINASSIGN6的全部位结构,其字节地址为0x4000C018。
(1)第0到7位为SPI1接口中的主入从出端MISO分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(2)第8到15位为SPI1接口中的片选端SSEL0分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(3)第16到23位为SPI1接口中的片选端SSEL1分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(4)第24到31位为多功能定时/计数器SCT的计数输入端PIN0分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
下表给出了SPI接口用到的全部寄存器描述。
由于LPC824的SPI接口功能很完善,所以涉及到的寄存器较多,它一共使用了11个寄存器来进行控制,应用上有些复杂。下面给出了上述寄存器对应的结构体定义。
typedef struct {
__IO uint32_t CFG;
__IO uint32_t DLY;
__IO uint32_t STAT;
__IO uint32_t INTENSET;
__O uint32_t INTENCLR;
__I uint32_t RXDAT;
__IO uint32_t TXDATCTL;
__IO uint32_t TXDAT;
__IO uint32_t TXCTL;
__IO uint32_t DIV;
__I uint32_t INTSTAT;
} LPC_SPI0_Type;
为了将2个SPI的基址指针强制转换为上述结构体,还要加上下面的定义。
#define LPC_SPI0_BASE 0x40058000UL
#define LPC_SPI1_BASE 0x4005C000UL
#define LPC_SPI0 ((LPC_SPI0_Type *) LPC_SPI0_BASE)
#define LPC_SPI1 ((LPC_SPI0_Type *) LPC_SPI1_BASE)
SPI接口涉及到的寄存器较多,后面会对它们进行具体分析。
--待续--