鱼C论坛

 找回密码
 立即注册

<stm32系列>SPI接口

已有 972 次阅读2013-11-13 17:06 |个人分类:stm32

 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]




路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-3 22:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部