一、SPI简介
- 1、全称:Serial Peripheral interface,串行外围设备接口
- 2、特征:高速、全双工、同步通信、四根线
- 3、四线:CS片选、SCLK时钟、MISO主入从出、MOSI主出从入
二、SPI工作原理
- 1、SPI通信方式简明图:
- 2、SPI可以挂载多个设备,通过片选线CS来选择哪个设备被选中。
- 3、主机和从机都有一个串行移位寄存器,当开始传输数据时,主机通过向自己的移位寄存器写入一个字节的数据来发起一次数据传输。
- 4、当开始传输数据时,主机移位寄存器将一个字节的数据通过MOSI信号线按位逐次移位到从机的移位寄存器,同时从机移位寄存器将数据通过MISO信号线按位逐次移位到主机的移位寄存器。这样就完成了主机和从机之间的数据交换。
- 5、通过第3点,可以看出:SPI通信方式对外设的写操作跟读操作是同步完成的。如果用户只想进行写操作,则主机主需要忽略到接收到的字节,若只想进行读操作,必须发送一个空字节来引发从机数据的传输。
三、SPI专有名词
- 1、时钟极性CPOL:决定了空闲时刻时钟SCLK信号线的电平
CPOL=0:表示SCLK在空闲状态为低电平
CPOL=1:表示SCLK在空闲状态电平为高电平 - 2、时钟相位CPHA:决定了数据在时钟信号线的第几个跳变沿被采样
CPHA=0:表示在SCK**第一个跳变沿**数据被采样
CPHA=1:表示在SCK**第二个跳变沿**数据被采样
- 3、MSB:Most Significant Bit 最高有效位
- 4、LSB:Least Significant Bit 最低有效位
四、STM32F1 SPI初始化
待补充
五、STM8L151 SPI初始化
待补充
六、STM8S SPI初始化
待补充
七、STM8L151 使用GPIO口模拟SPI
#define RF_CE_L GPIO_WriteBit(GPIOB, GPIO_Pin_4,RESET) //SPI_CS
#define RF_CE_H GPIO_WriteBit(GPIOB, GPIO_Pin_4,SET)
#define RF_CKL_L GPIO_WriteBit(GPIOB, GPIO_Pin_5,RESET) //SPI_CLK
#define RF_CKL_H GPIO_WriteBit(GPIOB, GPIO_Pin_5,SET)
#define RF_SDI_L GPIO_WriteBit(GPIOB, GPIO_Pin_6,RESET) //SPI_MOSI
#define RF_SDI_H GPIO_WriteBit(GPIOB, GPIO_Pin_6,SET)
#define SX1278_SDO GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) //SPI_MISO
//功能:SPI初始化
void SPI1_Init(void)
{
GPIO_Init(GPIOB, GPIO_Pin_5, GPIO_Mode_Out_PP_High_Fast); //CLK
GPIO_Init(GPIOB, GPIO_Pin_6, GPIO_Mode_Out_PP_High_Fast); //MOSI
GPIO_Init(GPIOB, GPIO_Pin_7, GPIO_Mode_In_PU_No_IT); //MISO
}
//功能:向从机发送一个字节
//参数:要发送的字节
//返回值:无
void RF_SPI_MasterIO(unsigned char out)
{
unsigned char i;
for(i=0; i<8; i++) //8次,一个字节
{
if(out & 0x80)
{
RF_SDI_H;
}
else
{
RF_SDI_L;
}
RF_CKL_H; // toggle clock high //
out = (out << 1);
RF_CKL_L; // toggle clock low //
}
}
//功能:从从机读取一个字节
//参数:无
//返回值:读取到的字节
unsigned char RF_SPI_READ_BYTE(void)
{
unsigned char j;
unsigned char i;
j = 0;
for (i = 0; i < 8; i++) //8次,一个字节
{
RF_CKL_H; // toggle clock high //
j = (j << 1); // shift 1 place to the left or shift in 0 //
if(SX1278_SDO) // check to see if bit is high //
{
j = j | 0x01; // if high, make bit high //
}
RF_CKL_L; // toggle clock low //
}
return j;
}