SPI(Serial Peripheral Interface--串行外设接口)总线系统是一种同步串行外设接口,它可以使MCU与各种外围设备以串行方式进行通信以交换信息。SPI有三个寄存器分别为:控制寄存器SPCR,状态寄存器SPSR,数据寄存器SPDR。
可以用模拟的来实现,也可以用硬件上来实现。模拟的速度达不到硬件上的速度,如果数据量大的话,最好选择硬件上的SPI来实现。
//模拟方式的控制程序
[code]
GPIO_InitStructure.GPIO_Pin = GCS | GSCLK;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_GT30_C, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GSO;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_GT30_D, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GSI;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIO_GT30_D, &GPIO_InitStructure);
#define SPI1_CS_0 GPIO_ResetBits(GPIO_GT30_C, GCS) //设置对应的引脚
#define SPI1_CS_1 GPIO_SetBits(GPIO_GT30_C, GCS)
#define SPI1_SCLK_0 GPIO_ResetBits(GPIO_GT30_C, GSCLK)
#define SPI1_SCLK_1 GPIO_SetBits(GPIO_GT30_C, GSCLK)
#define SPI1_SO_0 GPIO_ResetBits(GPIO_GT30_D, GSO)
#define SPI1_SO_1 GPIO_SetBits(GPIO_GT30_D, GSO)
#define READ_SPI1SI GPIO_ReadInputDataBit(GPIO_GT30_D, GSI)
/****************************************************************
// Summary: SPI的写字节和读字节
// Parameter: [in/u8]SPIx 针对哪个SPI接口
// [in/u8]u8Data 要写的数据
//
// return: [out/u8]读出的数据
****************************************************************/
u8 SPIx_Write(u8 SPIx, u8 u8Data)
{
u8 i;
u8 u8Read;
if(SPIx == SIM_SPI1)
{
SPI1_SCLK_0;
for(i = 0; i < 8; i ++)
{
SPI1_SCLK_0;
u8Read <<= 1;
if(READ_SPI1SI)
u8Read |= 0x01;
else
u8Read &= 0xfe;
if(u8Data & 0x80)
SPI1_SO_1;
else
SPI1_SO_0;
u8Data <<= 1;
SPI1_SCLK_1;
}
}
return u8Read;
}
//读操作
u8 SPIx_Read(u8 SPIx)
{
return SPIx_Write(SPIx, 0);
}
[/code]
使用stm32自带的SPI1脚
[code]
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 |GPIO_Pin_5| GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 ,ENABLE);
void SPI1_Config(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //2线2向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位数据
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟悬空时为高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第二个时钟
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //内部SSI控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //波特率分频值为16
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //传输数据高字节开始
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
#define SPI1_CS_0 GPIO_ResetBits(GPIO_GT30_C, GCS)
#define SPI1_CS_1 GPIO_SetBits(GPIO_GT30_C, GCS)
#define SPI_ReadByte(SPIx) SPI_WriteByte(SPIx, 0)
/****************************************************************
// Summary: SPI的写字节
// Parameter: [in/u8]SPIx 针对哪个SPI接口
// [in/u8]u8Data 要写的数据
//
// return: [void]
****************************************************************/
#define TRY_TIMES 32
u8 SPI_WriteByte(SPI_TypeDef* SPIx, u8 u8Byte)
{
u8 t;
t = TRY_TIMES;
while((SPIx->SR & SPI_I2S_FLAG_TXE) == RESET && t > 0);
{
t --;
}
if(t == 0)
{
return 0;
}
SPIx->DR = u8Byte; //发送一个byte
t = TRY_TIMES;
while((SPIx->SR & SPI_I2S_FLAG_RXNE) == RESET && t > 0); //等待接收完一个byte
{
t --;
}
if(t == 0)
{
return 0;
}
return SPIx->DR; //返回收到的数据
}
[/code]