一般SPI经过4个引脚与外部器材相连:
● MISO:主设备输入/从设备输出引脚。该引脚在从形式下发送数据,在主形式下接纳数据。
● MOSI:主设备输出/从设备输入引脚。该引脚在主形式下发送数据,在从形式下接纳数据。
● SCK:串口时钟,作为主设备的输出,从设备的输入
●NSS:从设备挑选。这是一个可选的引脚,用来挑选主/从设备。它的功用是用来作为“片选引脚”,让主设备能够单独地与特定从设备通讯,防止数据线上的抵触。从设备的NSS引脚能够由主设备的一个规范I/O引脚来驱动。一旦被使能(SSOE位),NSS引脚也能够作为输出引脚,并在SPI处于主形式时拉低;此刻,一切的SPI设备,假如它们的NSS引脚衔接到主设备的NSS引脚,则会检测到低电平,假如它们被设置为NSS硬件形式,就会主动进入从设备状况。当装备为主设备、NSS装备为输入引脚(MSTR=1,SSOE=0)时,假如NSS被拉低,则这个SPI设备进入主形式失利状况:即MSTR位被主动铲除,此设备进入从形式。
时钟信号的相位和极性
SPI_CR存放器的CPOL和CPHA位,能够组合成四种或许的时序联系。CPOL(时钟极性)位控制在没有数据传输时时钟的闲暇状况电平,此位对主形式和从形式下的设备都有用。假如CPOL被清’0’,SCK引脚在闲暇状况坚持低电平;假如CPOL被置’1’,SCK引脚在闲暇状况坚持高电平。
假如CPHA(时钟相位)位被置’1’,SCK时钟的第二个边缘(CPOL位为0时便是下降沿,CPOL位为’1’时便是上升沿)进行数据位的采样,数据在第二个时钟边缘被锁存。假如CPHA位被清’0’,SCK时钟的榜首边缘(CPOL位为’0’时便是下降沿,CPOL位为’1’时便是上升沿)进行数据位采样,数据在榜首个时钟边缘被锁存。
CPOL时钟极性和CPHA时钟相位的组合挑选数据捕捉的时钟边缘。
图212显现了SPI传输的4种CPHA和CPOL位组合。此图能够解释为主设备和从设备的SCK脚、MISO脚、MOSI脚直接衔接的主或从时序图。
CPOL时钟极性和CPHA时钟相位的组合挑选数据捕捉的时钟边缘。
上图显现了SPI传输的4种CPHA和CPOL位组合。此图能够解释为主设备和从设备的SCK脚、MISO脚、MOSI脚直接衔接的主或从时序图。
留意:
1. 在改动CPOL/CPHA位之前,有必要铲除SPE位将SPI制止。
2. 主和从有必要装备成相同的时序形式。
3.SCK的闲暇状况有必要和SPI_CR1存放器指定的极性共同(CPOL为’1’时,闲暇时应上拉SCK为高电平;CPOL为’0’时,闲暇时应下拉SCK为低电平)。
4. 数据帧格局(8位或16位)由SPI_CR1存放器的DFF位挑选,而且决议发送/接纳的数据长度。
我只需知道主机和从机的CPOL和CPHA位要共同就够了。
有2种NSS形式:
●软件NSS形式:能够经过设置SPI_CR1存放器的SSM位来使能这种形式。在这种形式下NSS引脚能够用作它用,而内部NSS信号电平能够经过写SPI_CR1的SSI位来驱动
● 硬件NSS形式,分两种状况:
─NSS输出被使能:当STM32F10xxx作业为主SPI,而且NSS输出现已经过SPI_CR2存放器的SSOE位使能,这时NSS引脚被拉低,一切NSS引脚与这个主SPI的NSS引脚相连并装备为硬件NSS的SPI设备,将主动变成从SPI设备。当一个SPI设备需求发送播送数据,它有必要拉低NSS信号,以告诉一切其它的设备它是主设备;假如它不能拉低NSS,这意味着总线上有别的一个主设备在通讯,这时将发生一个硬件失利过错(HardFault)。
─ NSS输出被封闭:答应操作于多主环境。
//咱们用软件NSS主从的转化都可凭借库来完成
数据帧格局
依据SPI_CR1存放器中的LSBFIRST位,输出数据位时能够MSB在先也能够LSB在先。
依据SPI_CR1存放器的DFF位,每个数据帧能够是8位或是16位。所挑选的数据帧格局对发送和/或接纳都有用。
装备一个SPI 这儿选SPI2
如下:
SPI_InitTypeDef SPI_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
SPI_Cmd(SPI2, DISABLE);//有必要先禁能,才干改动MODE
SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex;//两线全双工
SPI_InitStructure.SPI_Mode =SPI_Mode_Master;//主
SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b;//8位
SPI_InitStructure.SPI_CPOL =SPI_CPOL_High;//CPOL=1时钟悬空高
SPI_InitStructure.SPI_CPHA =SPI_CPHA_1Edge;//CPHA=1 数据捕获第2个
SPI_InitStructure.SPI_NSS =SPI_NSS_Soft;//软件NSS
SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_2;//2分频
SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB;//高位在前
SPI_InitStructure.SPI_CRCPolynomial =7;//CRC7
SPI_Init(SPI2,&SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
//spi的装备完毕了能够使用了。
也可用 函数SPI_StructInit 把SPI_InitStruct中的每一个参数按缺省值填入
_____________________________________________________________________________________
发送缓冲器闲暇标志(TXE)
此标志为’1’时标明发送缓冲器为空,能够写下一个待发送的数据进入缓冲器中。当写入SPI_DR时,TXE标志被铲除。
接纳缓冲器非空(RXNE)
此标志为’1’时标明在接纳缓冲器中包括有用的接纳数据。读SPI数据存放器能够铲除此标志。
留意在2.0的库中函数 SPI_SendData SPI_ReceiveDataSPI_GetFlagStatus 等在3.0的库中 变为
SPI_I2S_SendDataSPI_I2S_ReceiveData SPI_I2S_GetFlagStatus
写一个发送/承受函数
static u8 SPIByte(u8 byte)
{
while((SPI2->SR &SPI_I2S_FLAG_TXE)==RESET);
//while((SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE))==RESET);
SPI2->DR = byte;
//SPI_I2S_SendData(SPI2,byte);
while((SPI2->SR &SPI_I2S_FLAG_RXNE)==RESET);
//while((SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE))==RESET);
return(SPI2->DR);
//returnSPI_I2S_ReceiveData(SPI2);读存放器用硬件铲除标志位。
//SPI_I2S_ClearFlag(SPI2,SPI_I2S_FLAG_RXNE) ;直接软件铲除标志位。
}
这儿有两种写法直接操作存放器与用库函数,相对来说直接操作存放器应该更直观一些