您的位置:首页 > 其它

STM32 3个硬件SPI的使用

2016-08-11 08:51 363 查看

硬件平台:STM32F103

SPI1初始化过程

static OS_EVENT *spi1_sem_event;
static void SPI1SemInit(void)
{
spi1_sem_event = OSSemCreate(1);
}

extern void SPI1SemGet(void)
{
uint8_t err;

OSSemPend(spi1_sem_event, 0, &err);
}

extern void SPI1SemPut(void)
{
OSSemPost(spi1_sem_event);
}
static void Spi1_Init(void)
{
SPI_InitTypeDef  SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

/* Enable SPI1 and GPIO clocks */
/*!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO,
SPI_FLASH_SPI_MISO_GPIO, SPI_FLASH_SPI_DETECT_GPIO
and SPI_FLASH_SPI_SCK_GPIO Periph clock enable */

/*!< SPI_FLASH_SPI Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/*!< AFIO Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

/*!< Configure SPI_FLASH_SPI pins: SCK */
GPIO_InitStructure.GPIO_Pin = PIN_SPI1_SCLK;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(PORT_SPI1_SCLK, &GPIO_InitStructure);

/*!< Configure SPI_FLASH_SPI pins: MISO */
GPIO_InitStructure.GPIO_Pin = PIN_SPI1_MISO;
GPIO_Init(PORT_SPI1_MISO, &GPIO_InitStructure);

/*!< Configure SPI_FLASH_SPI pins: MOSI */
GPIO_InitStructure.GPIO_Pin = PIN_SPI1_MOSI;
GPIO_Init(PORT_SPI1_MOSI, &GPIO_InitStructure);

/* SPI1 configuration */
// W25X16: data input on the DIO pin is sampled on the rising edge of the CLK.
// Data on the DO and DIO pins are clocked out on the falling edge of CLK.
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//设置SPI的数据大小:SPI发送接收8位帧结构
#if 0
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
#else
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;      //时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;    //数据捕获于第1个时钟沿
#endif
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//定义波特率预分频的值:波特率预分频值为2
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure);

/* Enable SPI1  */
SPI_Cmd(SPI1, ENABLE);
SPI1SemInit();
}
extern void SPI1_SetSpeed(u8 SpeedSet)
{
SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
//如果速度设置输入0,则低速模式,非0则高速模式
if(SpeedSet == 1)
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
}
else
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
}
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
}

extern void spi1WriteData(Uchar *buf,Uint len)
{
for (; len ; len--,buf++)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, *buf);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
}
}

extern u8 SPI1_Swap_DataMSB(u8 byte)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI1, byte); //通过外设SPIx发送一个数据
retry=0;

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
}


SPI2初始化过程

static OS_EVENT *spi2_sem_event;
static void SPI2SemInit(void)
{
spi2_sem_event = OSSemCreate(1);
}

extern void SPI2SemGet(void)
{
uint8_t err;

OSSemPend(spi2_sem_event, 0, &err);
}

extern void SPI2SemPut(void)
{
OSSemPost(spi2_sem_event);
}

extern void Spi2_Init(void)
{
SPI_InitTypeDef  SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
/*!< AFIO Periph clock enable */
//RCC_APB2PeriphClockCmd(RCC_APB1Periph_AFIO, ENABLE);

GPIO_InitStructure.GPIO_Pin = PIN_SPI2_SCLK;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(PORT_SPI2_SCLK, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = PIN_SPI2_MISO;
GPIO_Init(PORT_SPI2_MISO, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = PIN_SPI2_MOSI;
GPIO_Init(PORT_SPI2_MOSI, &GPIO_InitStructure);

/* SPI2 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
#if 1
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
#else
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;      //时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        //数据捕获于第1个时钟沿
#endif
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitS
1087c
tructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);

/* Enable SPI2  */
SPI_Cmd(SPI2, ENABLE);
SPI2SemInit();
}

/*******************************************************************************
* Function Name  : SPI_SetSpeed
* Description    : SPI设置速度为高速
* Input          : u8 SpeedSet
*                  如果速度设置输入0,则低速模式,非0则高速模式
*                  SPI_SPEED_HIGH   1
*                  SPI_SPEED_LOW    0
* Output         : None
* Return         : None
*******************************************************************************/
void SPI2_SetSpeed(u8 SpeedSet)
{
SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
//如果速度设置输入0,则低速模式,非0则高速模式
if(SpeedSet == 1)
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
}
else
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
}
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
}

extern void spi2WriteData(Uchar *buf,Uint len)
{
for (; len ; len--,buf++)
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI2, *buf);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI2);
}
}

extern u8 SPI2_Swap_DataMSB(u8 byte)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);

/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(SPI2, byte);

/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI2);
}


SPI3初始化过程

static OS_EVENT *spi3_sem_event;

static void SPI3SemInit(void)
{
spi3_sem_event = OSSemCreate(1);
}

extern void SPI3SemGet(void)
{
uint8_t err;

OSSemPend(spi3_sem_event, 0, &err);
}

extern void SPI3SemPut(void)
{
OSSemPost(spi3_sem_event);
}

static void Spi3_Init(void)
{
SPI_InitTypeDef  SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

/* Enable SPI1 and GPIO clocks */
/*!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO,
SPI_FLASH_SPI_MISO_GPIO, SPI_FLASH_SPI_DETECT_GPIO
and SPI_FLASH_SPI_SCK_GPIO Periph clock enable */

/*!< SPI_FLASH_SPI Periph clock enable */
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
/*!< AFIO Periph clock enable */
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

/*!< Configure SPI_FLASH_SPI pins: SCK */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_SCLK;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(PORT_SPI_SCLK, &GPIO_InitStructure);

/*!< Configure SPI_FLASH_SPI pins: MISO */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_MISO;
GPIO_Init(PORT_SPI_MISO, &GPIO_InitStructure);

/*!< Configure SPI_FLASH_SPI pins: MOSI */
GPIO_InitStructure.GPIO_Pin = PIN_SPI_MOSI;
GPIO_Init(PORT_SPI_MOSI, &GPIO_InitStructure);

/* SPI1 configuration */
// W25X16: data input on the DIO pin is sampled on the rising edge of the CLK.
// Data on the DO and DIO pins are clocked out on the falling edge of CLK.
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
#if 1
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
#else
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;      //时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;    //数据捕获于第1个时钟沿
#endif
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI3, &SPI_InitStructure);

/* Enable SPI1  */
SPI_Cmd(SPI3, ENABLE);
SPI3SemInit();
}

/*******************************************************************************
* Function Name  : SPI_SetSpeed
* Description    : SPI设置速度为高速
* Input          : u8 SpeedSet
*                  如果速度设置输入0,则低速模式,非0则高速模式
*                  SPI_SPEED_HIGH   1
*                  SPI_SPEED_LOW    0
* Output         : None
* Return         : None
*******************************************************************************/
void SPI3SetSpeed(u8 SpeedSet)
{
SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
//如果速度设置输入0,则低速模式,非0则高速模式
if(SpeedSet == 1)
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
}
else
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
}
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI3, &SPI_InitStructure);
}

extern void spi3WriteData(Uchar *buf,Uint len)
{
for (; len ; len--,buf++)
{
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI3, *buf);
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI3);
}
}

extern u8 SPI3_Swap_DataMSB(u8 byte)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);

/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(SPI3, byte);

/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);

/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI3);
}


SPI用GPIO模拟注意以下四种状态的时序,转自网络~~~

#define _CPOL     1
#define _CPHA     0
#define SCK_IO    DDRA|=0X01
#define MOSI_IO   DDRA|=0X02
#define MISO_IO   DDRA&=0XFB
#define SSEL_IO   DDRA|=0X08
#define SCK_D(X)   (X?(PORTA|=0X01):(PORTA&=0XFE))
#define MOSI_D(X)  (X?(PORTA|=0X02):(PORTA&=0XFD))
#define SSEL_D(X)  (X?(PORTA|=0X08):(PORTA&=0XF7))

#define MISO_I()  (PINA&0X04)
void delay()
{
unsigned char m,n;
for(n=0;n<5;n++);
for(m=0;m<100;m++);
}
/************************************************
端口方向配置  与输出初始化
************************************************/
void SPI_Init(void)
{
SCK_IO   ;
MOSI_IO  ;
MISO_IO  ;
SSEL_IO  ;
SSEL_D(1);
MOSI_D(1);

#if _CPOL==0
SCK_D(0);
#else
SCK_D(1);
#endif
}

/**********************************************
模式零           写数据
***********************************************/
#if _CPOL==0&&_CPHA==0          //MODE   0  0
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
for(n=0;n<8;n++)
{
SCK_D(0);
if(dat&0x80)MOSI_D(1);
else MOSI_D(0);
dat<<=1;
SCK_D(1);
}
SCK_D(0);
}
/*********************************************
模式零         读数据
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
SCK_D(0);
dat<<=1;
if(MISO_I())dat|=0x01;
else dat&=0xfe;
SCK_D(1);
}
SCK_D(0);
return dat;
}
#endif
/**********************************************
模式二           写数据
***********************************************/
#if _CPOL==1&&_CPHA==0           //MODE   1  0
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
for(n=0;n<8;n++)
{
SCK_D(1);
if(dat&0x80)MOSI_D(1);
else MOSI_D(0);
dat<<=1;
SCK_D(0);
}
SCK_D(1);
}
/*********************************************
模式二          读数据
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
SCK_D(1);
dat<<=1;
if(MISO_I())dat|=0x01;
else dat&=0xfe;
SCK_D(0);
}
SCK_D(1);
return dat;
}

#endif
/*********************************************
模式一        写数据
*********************************************/
#if _CPOL==0&&_CPHA==1           //MODE  0  1
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
SCK_D(0);
for(n=0;n<8;n++)
{
SCK_D(1);
if(dat&0x80)MOSI_D(1);
else MOSI_D(0);
dat<<=1;
SCK_D(0);
}
}
/*********************************************
模式一       读数据
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
SCK_D(1);
dat<<=1;
if(MISO_I())dat|=0x01;
else dat&=0xfe;
SCK_D(0);
}
SCK_D(0);
return dat;
}
#endif
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////

#if _CPOL==1&&_CPHA==1            //MODE  1  1
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
SCK_D(1);
for(n=0;n<8;n++)
{
SCK_D(0);
if(dat&0x80)MOSI_D(1);
else MOSI_D(0);
dat<<=1;
SCK_D(1);
}
}
/************************************
模式三          读数据
************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
SCK_D(0);
for(n=0;n<8;n++)
{
SCK_D(0);
dat<<=1;
if(MISO_I())dat|=0x01;
else dat&=0xfe;
SCK_D(1);
}
SCK_D(1);
return dat;
}
#endif
/*************************************
*************************************/
void main()
{

SPI_Init();
DDRB = 0XFF;
//#if _CPOL
//SCK_D(0);
//#endif
while(1)
{
//SSEL_D(0);
//SPI_Send_Dat(0x01);
//SPI_Send_Dat(0x31);
//SSEL_D(1);
SSEL_D(0);
SPI_Send_Dat(0x81);
PORTB =SPI_Receiver_Dat();
SSEL_D(1);
//delay();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  stm32 c 硬件SPI