Serial Peripheral Interface,串行外围设备接口,一种高速全双工的通信总线。
1 物理层
MOSI
Master Output Slave Input,主设备输出/从设备输入引脚
MISO
Master Input Slave Output,主设备输入/从设备输出引脚
SCK 时钟信号信号线,用于通讯数据同步,由通讯主机产生
NSS
从设备选择信号线,NSS线置低电平为开始信号,NSS线被拉高
作为结束信号
2 协议层
2.1 基本通讯过程
主机控制产生NSS、SCK、MOSI信号,从机产生MISO信号,主机在MISO信号线读取从机的数据。 NSS为低电平时,MOSI和MISO信号有效,在SCK的每个时钟周期MOSI和MISO传输一位数据。
2.2 通讯起始和停止信号
SPI通讯的起始信号-NSS信号由高变低 SPI通讯的停止信号-NSS信号由低变高
2.3 数据有效性
参考CPOL和CPHA
2.4 CPOL/CPHA
时钟极性CPOL SPI通讯设备处于空闲时,SCK信号线的电平信号
CPOL=0,SCK在空闲状态时为低电平
CPOL=1,SCK在空闲状态时为高电平
时钟相位CPHA 数据的采样时刻 CPHA=0,数据线在SCK时钟线的"奇数边沿"被采样 CPHA=1,数据线在SCK时钟线的"偶数边沿"被采样
CPHA=0,CPOL=0,时钟的奇数边沿是上升沿
CPHA=0,CPOL=1,时钟的奇数边沿是下降沿 MOSI和MISO数据线的有效信号在SCK的奇数边沿保持不变;在SCK奇数边沿采样数据信号;在非采样时刻,MOSI和MISO的有效信号发送切换。
CPHA=1,CPOL=0,时钟的奇数边沿是下降沿
CPHA=1,CPOL=1,时钟的奇数边沿是上升沿
主机和从机需要在相同的模式下才可以正常通讯
模拟SPI
IO配置
/************************************************
函数名称 : SPI_GPIO_Configuration
功 能 : SPI引脚配置
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void SPI_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* CS */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_CS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(PORT_SPI_CS, &GPIO_InitStructure);
/* SCK */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_SCK;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(PORT_SPI_SCK, &GPIO_InitStructure);
/* MISO */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_MISO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(PORT_SPI_MISO, &GPIO_InitStructure);
/* MOSI */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_MOSI;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(PORT_SPI_MOSI, &GPIO_InitStructure);
}
/************************************************
函数名称 : SPI_Initializes
功 能 : SPI初始化
参 数 : 无
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void SPI_Initializes(void)
{
SPI_GPIO_Configuration();
SPI_CS_DISABLE;
SPI_SCK_HIGH;
SPI_MOSI_HIGH;
}
写一字节数据
/************************************************
函数名称 : SPI_WriteByte
功 能 : SPI写一字节数据
参 数 : TxData --- 发送的字节数据
返 回 值 : 无
作 者 : strongerHuang
*************************************************/
void SPI_WriteByte(uint8_t TxData)
{
uint8_t cnt;
for(cnt=0; cnt<8; cnt++)
{
SPI_SCK_LOW; //时钟 - 低
SPI_Delay();
if(TxData & 0x80)//发送数据
SPI_MOSI_HIGH;
else
SPI_MOSI_LOW;
TxData <<= 1;
SPI_Delay();
SPI_SCK_HIGH;//时钟 - 高
SPI_Delay();
}
}
读一字节数据
/************************************************
函数名称 : SPI_ReadByte
功 能 : SPI读一字节数据
参 数 : 无
返 回 值 : 读回来的字节数据
作 者 : strongerHuang
*************************************************/
uint8_t SPI_ReadByte(void)
{
uint8_t cnt;
uint8_t RxData = 0;
for(cnt=0; cnt<8; cnt++)
{
SPI_SCK_LOW;//时钟 - 低
SPI_Delay();
RxData <<= 1;
if(SPI_MISO_READ) //读取数据
{
RxData |= 0x01;
}
SPI_SCK_HIGH;//时钟 - 高
SPI_Delay();
}
return RxData;
}