前言
写文章的目的是想通过记录自己的学习过程,以便以后使用到相关的知识点可以回顾和参考。
SPI简介
SPI 全称是 Serial Perripheral Interface,也就是串行外围设备接口。SPI 是 Motorola 公司推出的一种同步串行接口技术,是一种高速、全双工的同步通信总线,SPI 时钟频率相比 I2C 要高很多,最高可以工作在上百 MHz。SPI 以主从方式工作,通常是有一个主设备和一个或多个从设备,一般 SPI 需要4 根线,但是也可以使用三根线(单向传输),这四根线如下:
①、CS/SS,Slave Select/Chip Select,这个是片选信号线,用于选择需要进行通信的从设备。
I2C 主机是通过发送从机设备地址来选择需要进行通信的从机设备的,SPI 主机不需要发送从机
设备,直接将相应的从机设备片选信号拉低即可。
②、SCK,Serial Clock,串行时钟,和 I2C 的 SCL 一样,为 SPI 通信提供时钟。
③、MOSI/SDO,Master Out Slave In/Serial Data Output,简称主出从入信号线,这根数据线
只能用于主机向从机发送数据,也就是主机输出,从机输入。
④、MISO/SDI,Master In Slave Out/Serial Data Input,简称主入从出信号线,这根数据线只
能用户从机向主机发送数据,也就是主机输入,从机输出。
SPI 通信都是由主机发起的,主机需要提供通信的时钟信号。主机通过 SPI 线连接多个从
设备的结构如图所示:
SPI 有四种工作模式,通过串行时钟极性(CPOL)和相位(CPHA)的搭配来得到四种工作模式:
①、CPOL=0,串行时钟空闲状态为低电平。
②、CPOL=1,串行时钟空闲状态为高电平,此时可以通过配置时钟相位(CPHA)来选择具
体的传输协议。
③、CPHA=0,串行时钟的第一个跳变沿(上升沿或下降沿)采集数据。
④、CPHA=1,串行时钟的第二个跳变沿(上升沿或下降沿)采集数据。
实现流程
1、设置spi时钟,初始化spi
2、编写发送接收函数
具体实现
1、设置spi时钟,初始化spi
void spiclk_init(SPIClk_Type* Base)
{
Base->SSPCLKENB &= ~(1<<2); /* 关闭时钟 */
Base->SSPCLKEN0L &= ~(7<<2); /* 选择PLL1作为时钟源,800MHz */
Base->SSPCLKEN0L |= (1<<2);
Base->SSPCLKEN0L &= ~(0xFF<<5);
Base->SSPCLKEN0L |= (39<<5); /* 80分频,800 / 40 = 20MHz ,内部经过2分频到spi_clk,即10MHz */
Base->SSPCLKENB |= (1<<2); /* 打开时钟 */
}
void spi_init(SPI_Type* Base)
{
spiclk_init(SPI0_Clk); /* 初始化时钟 */
Base->CONFIGURE |= (1<<5); /* 软复位 */
Base->CONFIGURE &= ~(3<<0); /* 关闭SPI */
Base->CONFIGURE &= ~(1<<2); /* 第一个时钟沿采集数据 */
Base->CONFIGURE &= ~(1<<3); /* 空闲时为低电平 */
Base->CONFIGURE &= ~(1<<4); /* 主机模式 */
Base->FIFOCON = 0; /* 清寄存器 */
Base->FIFOCON &= ~(3<<29); /* 1字节的数据宽 */
//Base->SELSIGNALCON &= ~(1<<1); /* 手动控制片选信号 */
Base->CONFIGURE |= (3<<0); /* 启动SPI */
}
2、编写发送接收函数
void spi_send(SPI_Type* Base, unsigned char data)
{
//unsigned char temp;
while((Base->STATUS & (1<<0)) == 0);
Base->TXDATA = data;
while((Base->STATUS & (1<<1)) == 0);
//temp = Base->RXDATA;
}
unsigned char spi_recv(SPI_Type* Base)
{
unsigned char data;
while((Base->STATUS & (1<<0)) == 0);
Base->TXDATA = 0x00;
while((Base->STATUS & (1<<1)) == 0);
data = Base->RXDATA;
return data;
}