一,SPI概括:
SPI是串行外设接口(Serial Peripheral
Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议。(引用百度百科)
SPI也有三线制,适用于单向传输。
SPI协议是由Motorola首先在其MC68HCXX系列处理器上定义的。
二,SPI 接口 原理 缺陷:
四线制物理接口:
三线制只是少了SS/CS接口,不能一对多。
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS/SS(片选)。
(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS/SS – Chip Select,从设备使能信号,由主设备控制。
(引用百度百科)
SPI缺点:没有指定的流控制,没有应答机制确认是否接收到数据
三 SPI协议:
SPI协议根据片选线(CS/SS)区分从设备,因此4线和3线的区别就在于此。
SPI协议根据CPOL和CPHA不同,有四种通讯方式。
时钟极性(CPOL)指通讯设备处于空闲状态(SPI开始通讯前、CS/SS线无效)时,SCK的状态。
时钟相位(CPHA)指数据的采样时刻位于SCK的偶数边沿采样还是奇数边沿采样。
CPOL:时钟极性选择,为0时SPI总线空闲为低电平,为1时SPI总线空闲为高电(0/1)
CPHA:时钟相位选择,为0时在SCK第一个跳变沿采样,为1时在SCK第二个跳变沿采样(0/1)
注意:不要认为是上升沿采集数据,下降沿发送数据
spi协议时序图(4种情况)
所以对于的code有四种写法,按实际需求去写。
注意:所有操作需要先拉低对应的片选线(CS/SS)
数据的传输方向一般是高位开始,实际编写操作看需求。
SPI协议有硬件实现和软件模拟两种方式。
//默认一对一
/*
函数功能:SPI底层时序
时序图的第一种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
u8 i=0,rx_data=0;
SCK=0;
for(i=0;i<8;i++)
{
SCK=0;
if(tx_data&0x80)MOSI=1;
else MOSI=0;
SCK=1;
tx_data<<=1;
rx_data<<=1;
if(MISO)rx_data|=0x01;
}
SCK=0;
return rx_data;
}
/*
函数功能:SPI底层时序
时序图的第二种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
u8 i=0,rx_data=0;
SCK=0;
for(i=0;i<8;i++)
{
SCK=1;
if(tx_data&0x80)MOSI=1;
else MOSI=0;
SCK=0;
tx_data<<=1;
rx_data<<=1;
if(MISO)rx_data|=0x01;
}
SCK=0;
return rx_data;
}
/*
函数功能:SPI底层时序
时序图的第三种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
u8 i=0,rx_data=0;
SCK=1;
for(i=0;i<8;i++)
{
SCK=1;
if(tx_data&0x80)MOSI=1;
else MOSI=0;
SCK=0;
tx_data<<=1;
rx_data<<=1;
if(MISO)rx_data|=0x01;
}
SCK=1;
return rx_data;
}
/*
函数功能:SPI底层时序
时序图的第四种写法
*/
u8 SPI_ReadWriteOneByte(u8 tx_data)
{
u8 i=0,rx_data=0;
SCK=1;
for(i=0;i<8;i++)
{
SCK=0;
if(tx_data&0x80)MOSI=1;
else MOSI=0;
SCK=1;
tx_data<<=1;
rx_data<<=1;
if(MISO)rx_data|=0x01;
}
SCK=1;
return rx_data;
}
示例: