close

9

SPI

9.1 STM32 SPI簡介

serial peripheral interface (SPI) 可以與外部週邊半/ 全雙工、同步、串列通信,SPI可設為master,並提供外部週邊通訊clock (SCK)SPI也可以在多個master情況使用。

STM32F10x處理器SPI結構圖

image001  

 

通常SPI透過4pin去連接外部週邊:

 

MISO: Master In / Slave Out data. SPI設為master,此腳接收從slave傳來的資料,

 

         SPI設為slave,此腳傳送資料到master

 

MOSI: Master Out / Slave In data. SPI設為master,此腳傳送資料到slave

 

         SPI設為slave,此腳接收從master傳來的資料。

 

SCK: master提供clock輸出給slave當成通訊clock.

 

NSS: Slave select. 該腳可以被master當做要和那個slave做構通。

 

單個主從SPI置配

image002  

Slave select (NSS) pin management

STM32F10x提供2NSS模式

Software NSS mode: 透過SP1_CR1暫存器裡的SSM bit啟動此模式,外部的NSS腳就可做為其他用途使用,而內部NSS信號透過SP1_CR1暫存器SSI設置。

Hardware NSS mode: 有二種配置

– NSS output is enabled: 透過SPI_CR2暫存器裡SSOE bit允許輸出,當NSS被拉低時,其他SPI配置為NSS模式,則會被當成slave,此清形只允許一個master存在。

– NSS output is disabled: 透過SPI_CR2暫存器裡SSOE bit禁止輸出,且可以允許多個master的配置。.

Figure 208. Hardware/software slave select management

image003  

 

9.2 SPI Standard Driver Library

本節說明ST提供SPI Standard Driver Library

Function name

Description

SPI_I2S_DeInit

Re-initializes the SPIx peripheral registers to their default reset values.

SPI_Init

Initializes the SPIx peripheral according to the specified parameters in the SPI_InitStruct.

SPI_StructInit

Fills each SPI_InitStruct member with its default value.

SPI_Cmd

Enables or disables the specified SPI peripheral.

SPI_I2S_ITConfig

Enables or disables the specified SPI/I2S interrupts.

SPI_I2S_DMACmd

Enables or disables the SPIx/I2Sx DMA interface.

SPI_I2S_SendData

Transmits data through the SPIx/I2Sx peripheral.

SPI_I2S_ReceiveData

Returns the most recent received data through the SPIx/I2Sx peripheral.

SPI_NSSInternalSoftwareConfig

Configures internally by software the NSS pin for the selected SPI.

SPI_SSOutputCmd

Enables or disables the SS output for the selected SPI.

SPI_DataSizeConfig

Configures the data size for the selected SPI.

SPI_TransmitCRC

Transmits the SPIx CRC value

SPI_CalculateCRC

Enables or disables the CRC value calculation of the transferred bytes.

SPI_GetCRC

Returns the transmit or the receive CRC register value for the specified SPI.

SPI_GetCRCPolynomial

Returns the CRC Polynomial register value for the specified SPI.

SPI_BiDirectionalLineConfig

Selects the data transfer direction in bidirectional mode for the specified SPI.

SPI_I2S_GetFlagStatus

Checks whether the specified SPI/I2S flag is set or not.

SPI_I2S_ClearFlag

Clears the SPIx/I2Sx pending flags.

SPI_I2S_GetITStatus

Checks whether the specified SPI/I2S interrupt has occurred or not.

SPI_I2S_ClearITPendingBit

Clears the SPIx/I2Sx interrupt pending bits.

9.2.1 SPI_I2S_DeInit function

describes the SPI_I2S_DeInit function.

Function name

SPI_I2S_DeInit

Function prototype

void SPI_I2S_DeInit(SPI_TypeDef* SPIx)

Behavior description

Resets the SPIx/I2Sx peripheral registers to their default reset values.

Input parameter

SPIx: where x can be 1 or 2 to select the SPI peripheral.

Output parameter

None

Return parameter

None

Required preconditions

None

Called functions

RCC_APB2PeriphClockCmd() for SPI1

RCC_APB1PeriphClockCmd() for SPI2 and SPI3

 

Example:

/* Deinitialize the SPI2 */

SPI_DeInit(SPI2);

/* Deinitialize the I2S3 */

SPI_DeInit(SPI3);

9.2.2 SPI_Init function

describes the SPI_Init function.

Function name

SPI_Init

Function prototype

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)

Behavior description

Initializes the SPIx peripheral according to the parameters specified in

the SPI_InitStruct.

Input parameter1

SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.

Input parameter2

SPI_InitStruct: pointer to a SPI_InitTypeDef structure that contains the

configuration information for the specified SPI peripheral.

Refer to the SPI_InitTypeDef structure for more details on the allowed

values for this parameter.

Output parameter

None

Return parameter

None

Required preconditions

None

Called functions

None

 

The SPI_InitTypeDef structure is defined in the stm32f10x_spi.h file:

typedef struct

{

u16 SPI_Direction;

u16 SPI_Mode;

u16 SPI_DataSize;

u16 SPI_CPOL;

u16 SPI_CPHA;

u16 SPI_NSS;

u16 SPI_BaudRatePrescaler;

u16 SPI_FirstBit;

u16 SPI_CRCPolynomial;

} SPI_InitTypeDef;

9.2.3 SPI_Direction

SPI_Direction configures the SPI unidirectional or bidirectional data mode. Refer to

for the values taken by this member.

SPI_Direction

Description

SPI_Direction_2Lines_FullDuplex

SPI configured as 2 lines unidirectional full duplex

SPI_Direction_2Lines_RxOnly

SPI configured as 2 lines unidirectional Rx only

SPI_Direction_1Line_Rx

SPI configured as 1 line bidirectional Rx only

SPI_Direction_1Line_Tx

SPI configured as 1 line bidirectional Tx only

9.2.4 SPI_Mode

SPI_Mode configures the SPI operating mode. Refer to for the values taken by

this member.

SPI_Mode

Description

SPI_Mode_Master

SPI configured as a master

SPI_Mode_Slave

SPI configured as a slave

9.2.5 SPI_DataSize

SPI_DataSize configures the SPI data size. Refer to for the values taken by this member.

SPI_DataSize

Description

SPI_DataSize_16b

SPI 16-bit data frame format for transmission and

reception

SPI_DataSize_8b

SPI 8-bit data frame format for transmission and reception

9.2.6 SPI_CPOL

SPI_CPOL selects the serial clock steady state. Refer to for the values taken by

this member.

SPI_CPOL

Description

SPI_CPHA_2Edge

Data is captured on the second edge

SPI_CPHA_1Edge

Data is captured on the first edge

9.2.7 SPI_CPHA

SPI_CPHA configures the clock active edge for the bit capture. Refer to for the

values taken by this member.

SPI_CPHA

Description

SPI_CPHA_2Edge

Data is captured on the second edge

SPI_CPHA_1Edge

Data is captured on the first edge

9.2.8 SPI_NSS

SPI_NSS specifies whether the NSS signal is managed by hardware (NSS pin) or by

software using the SSI bit. Refer to Table 418 for the values taken by this member.

SPI_NSS

Description

SPI_NSS_Hard

NSS managed by external pin

SPI_NSS_Soft

Internal NSS signal controlled by SSI bit

9.2.9 SPI_BaudRatePrescaler

SPI_BaudRatePrescaler is used to define the Baud Rate prescaler value which will be used

to configure the transmit and receive SCK clock. Refer to for the values taken by

this member.

SPI_BaudratePrescaler

Description

SPI_BaudRatePrescaler2

Baud Rate Prescaler equal to 2

SPI_BaudRatePrescaler4

Baud Rate Prescaler equal to 4

SPI_BaudRatePrescaler8

Baud Rate Prescaler equal to 8

SPI_BaudRatePrescaler16

Baud Rate Prescaler equal to 16

SPI_BaudRatePrescaler32

Baud Rate Prescaler equal to 32

SPI_BaudRatePrescaler64

Baud Rate Prescaler equal to 64

SPI_BaudRatePrescaler128

Baud Rate Prescaler equal to 128

SPI_BaudRatePrescaler256

Baud Rate Prescaler equal to 256

9.2.10 SPI_FirstBit

SPI_FirstBit specifies whether data transfers start from MSB or LSB bit. Refer to for the values taken by this member.

SPI_FirstBit

Description

SPI_FisrtBit_MSB

First bit to transfer is the MSB

SPI_FisrtBit_LSB

First bit to transfer is the LSB

 

9.2.11 SPI_Cmd function

describes the SPI_Cmd function.

Function name

SPI_Cmd

Function prototype

void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)

Behavior description

Enables or disables the specified SPI peripheral.

Input parameter1

SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.

Input parameter2

NewState: new state of the SPIx peripheral.

This parameter can be: ENABLE or DISABLE.

Output parameter

None

Return parameter

None

Required preconditions

None

Called functions

None

 

Example:

/* Enable SPI3 */

SPI_Cmd(SPI3, ENABLE);

9.2.12 SPI_I2S_ITConfig function

describes the SPI_I2S_ITConfig function.

Function name

SPI_I2S_ITConfig

Function prototype

void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, u8 SPI_I2S_IT,

FunctionalState NewState)

Behavior description

Enables or disables the specified SPI/I2S interrupts.

Input parameter1

SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.

Input parameter2

SPI_I2S_IT: SPI interrupt source to be enabled or disabled.

Refer to SPI_I2S_IT for more details on the allowed values for this

parameter.

Input parameter3

NewState: new state of the specified SPI/I2S interrupt.

This parameter can be: ENABLE or DISABLE.

Output parameter

None

Return parameter

None

Required preconditions

None

Called functions

None

 

9.2.13 SPI_I2S_IT

SPI_I2S_IT enables or disables SPI/I2S interrupts. See for the values taken by

this parameter.

SPI_I2S_IT

Description

SPI_I2S_IT_TXE

Tx buffer empty interrupt mask

SPI_I2S_IT_RXNE

Rx buffer not empty interrupt mask

SPI_I2S_IT_ERR

Error interrupt mask

Example:

/* Enable SPI2 Tx buffer empty interrupt */

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);

9.2.14 SPI_I2S_SendData function

describes the SPI_I2S_SendData function.

Function name

SPI_I2S_SendData

Function prototype

void SPI_I2S_SendData(SPI_TypeDef* SPIx, u16 Data)

Behavior description

Transmits data through the SPIx/I2Sx peripheral.

Input parameter1

SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.

Input parameter2

Data: Byte or half word (in SPI mode), or half word (in I2S mode) to be

transmitted.

Output parameter

None

Return parameter

None

Required preconditions

None

Called functions

None

 

Example:

/* Send 0xA5 through the SPI1 peripheral */

SPI_I2S_SendData(SPI1, 0xA5);

9.2.15 SPI_I2S_ReceiveData function

describes the SPI_I2S_ReceiveData function.

Function name

SPI_I2S_ReceiveData

Function prototype

u16 SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)

Behavior description

Returns the most recent data received through the SPIx/I2Sx peripheral.

Input parameter

SPIx: where x can be 1, 2 or 3 to select the SPI/I2S? peripheral.

Output parameter

None

Return parameter

The value of the received data.

Required preconditions

None

Called functions

None

 

Example:

/* Read the most recent data received by the SPI2 peripheral */

u16 ReceivedData;

ReceivedData = SPI_I2S_ReceiveData(SPI2);

9.2.16 SPI_I2S_GetFlagStatus function

describes the SPI_I2S_GetFlagStatus function.

Function name

SPI_I2S_GetFlagStatus

Function prototype

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, u16

SPI_I2S_FLAG)

Behavior description

Checks whether the specified SPI/I2S flag is set or not.

Input parameter1

SPIx: where x can be 1, 2 or 3 to select the SPI/I2S? peripheral.

Input parameter2

SPI_I2S_FLAG: flag to be checked.

Refer to SPI_I2S_FLAG for more details on the allowed values for this

parameter.

Output parameter

None

Return parameter

The new state of SPI_I2S_FLAG (SET or RESET).

Required preconditions

None

Called functions

None

9.2.17 SPI_I2S_FLAG

The SPI/I2S flags that can be checked by issuing an SPI_I2S_GetFlagStatus function are

listed in Table

SPI_I2S_FLAG

Description

SPI_I2S_FLAG_BSY

Busy flag

SPI_I2S_FLAG_OVR

Overrun flag

SPI_FLAG_MODF

Mode fault flag

SPI_FLAG_CRCERR

CRC error flag

I2S_FLAG_UDR

Underrun flag

I2S_FLAG_CHSIDE

Channel side flag

SPI_I2S_FLAG_TXE

Transmit buffer empty flag

SPI_I2S_FLAG_RXNE

Receive buffer not empty flag

 

Example:

/* Test if the SPI1 transmit buffer empty flag is set or not */

FlagStatus Status;

Status = SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE);

/* Get the I2S3 received (or to be transmitted) data channel side

(left or right) */

FlagStatus Status;

Status = SPI_I2S_GetFlagStatus(SPI3, I2S_FLAG_CHSIDE);

9.3實例演練

實驗一 二塊SIOC使用SPI通訊介面傳收資料

實驗說明:將一SIOCSPI1設為master ,另一SIOCSPI2設為slaveSPI1傳送3216位元的資料給SPI2,並使用VCP觀察其結果。

主要程式碼說明

傳送端(SPI1 master)程式碼

#include "stm32f10x.h"

#include "stdio.h"

#include "hw_config.h"

#include "stm32_eval.h"

 

/* Private define ------------------------------------------------------------*/

#define BufferSize  32 //傳送資料buffer大小

 

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef  SPI_InitStructure;

/*傳送資料,3216位元資料*/

uint16_t SPI1_Buffer_Tx[BufferSize] = {1, 2, 3, 4, 5, 6,

                                7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};

uint32_t TxIdx = 0; //

/* Private functions ---------------------------------------------------------*/

void RCC_Configuration(void);//設定SPI RCC

void GPIO_Configuration(void);//設定SPI GPIO

 

int main(void)

{

  int a,b;

  Set_System();

  /* SPI clocks configuration ---------------------------------------------*/

  RCC_Configuration();

  /* SPI GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

 

  /* SPI1 configuration ------------------------------------------------------*/

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 

  SPI_Init(SPI1, &SPI_InitStructure); 

 

  /* Enable SPI1 */

  SPI_Cmd(SPI1, ENABLE);

 

  /* Transfer procedure */

  while (TxIdx < BufferSize )

  {

    /* Wait for SPI1 Tx buffer empty */

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

    /* Send SPI1 data */

    SPI_I2S_SendData(SPI1, SPI1_Buffer_Tx[TxIdx++]);   

  }

 

  while (1)

  {

      getchar();

/**********************/

    /*使用VCP印出傳送資料*/

        b = 0;

        while (b<  32 )

        {

         printf("SPI1 Tx %d : %d\n\r",b,SPI1_Buffer_Tx[b]);

         b++;

        }

/**********************/

  }

}

void RCC_Configuration(void)

{

  /* PCLK2 = HCLK/2 */

  RCC_PCLK2Config(RCC_HCLK_Div2);

 

  /* Enable peripheral clocks --------------------------------------------------*/

  /* GPIOA, GPIOB and SPI1 clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |

                         RCC_APB2Periph_SPI1, ENABLE);

}

 

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

 

  /* Configure SPI1 pins: SCK, MISO and MOSI ---------------------------------*/

  /* Confugure SCK and MOSI pins as Alternate Function Push Pull */

  GPIO_InitStructure.GPIO_Pin = 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);

 

  /* Confugure MISO pin as Input Floating  */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

接送端(SPI2 slave)程式碼

#include "stm32f10x.h"

#include "stdio.h"

#include "hw_config.h"

#include "stm32_eval.h"

 

/* Private define ------------------------------------------------------------*/

#define BufferSize  32 //接收資料buffer大小

 

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef  SPI_InitStructure;

/*接收資料,3216位元資料*/

uint16_t  SPI2_Buffer_Rx[BufferSize]={0 };

uint32_t RxIdx = 0;

/* Private functions ---------------------------------------------------------*/

void RCC_Configuration(void);//設定SPI RCC

void GPIO_Configuration(void);//設定SPI GPIO

 

int main(void)

{

  int a,b;

  Set_System();

  /* SPI clocks configuration ---------------------------------------------*/

  RCC_Configuration();

  /* SPI GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

 

  /* SPI2 configuration ------------------------------------------------------*/

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   

  SPI_Init(SPI2, &SPI_InitStructure);

 

  /* Enable SPI2 */

  SPI_Cmd(SPI2, ENABLE);    

 

  /* received procedure */

  while (RxIdx< BufferSize )

  {

    /* Wait for SPI2 data reception */

   while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

    /* Read SPI2 received data */

     SPI2_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI2);

 }  

 

  while (1)

  {

      getchar();

/**********************/

    /*使用VCP印出接收資料*/

        b = 0;

        while (b<  32 )

        {

         printf("SPI2 Rx %d : %d\n\r",a,SPI2_Buffer_Rx[a]);

         b++;

        }

/**********************/

  }

}

void RCC_Configuration(void)

{

  /* PCLK2 = HCLK/2 */

  RCC_PCLK2Config(RCC_HCLK_Div2);

 

  /* Enable peripheral clocks --------------------------------------------------*/

  /* SPI2 Periph clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

}

 

void GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

 

   /* Configure SPI2 pins: SCK, MISO and MOSI ---------------------------------*/

  /* Confugure SCK and MOSI pins as Input Floating */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Confugure MISO pin as Alternate Function Push Pull */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

 

 

 

 

接線示意圖

image004  

 

實驗結果

image005  

 

COM4SPI1結果,COM9SPI2結果


 

實驗二 可變資料筆數的傳收

實驗說明:接續實驗一,SPI1可設定傳送資料筆數,SPI2接收設定資料筆數的資料,SPI1先傳送資料筆數給SPI2,之後SPI2依照接收的數目,接收資料。

主要程式碼說明

傳送端(SPI1 master)程式碼

#include "stm32f10x.h"

#include "stdio.h"

#include "hw_config.h"

#include "stm32_eval.h"

 

/* Private define ------------------------------------------------------------*/

#define BufferSize  32 //傳送資料buffer大小

 

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef  SPI_InitStructure;

/*傳送資料,3216位元資料*/

uint16_t SPI1_Buffer_Tx[BufferSize] = {1, 2, 3, 4, 5, 6,

                                7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};

uint32_t TxIdx = 0; //

/* Private functions ---------------------------------------------------------*/

void RCC_Configuration(void);//設定SPI RCC

void GPIO_Configuration(void);//設定SPI GPIO

 

int main(void)

{

  int a;//傳送筆數

  Set_System();

  /* SPI clocks configuration ---------------------------------------------*/

  RCC_Configuration();

  /* SPI GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

 

  /* SPI1 configuration ------------------------------------------------------*/

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 

  SPI_Init(SPI1, &SPI_InitStructure); 

 

  /* Enable SPI1 */

  SPI_Cmd(SPI1, ENABLE);

 

  while (1)

  {

      getchar();

    /********************************/

    //設定傳送資料量

        printf("input BufferSize :");

        scanf("%d",&a);

        printf("\n\r");                                            

        /********************************/

    

    //傳送要預傳送資料量

      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

    SPI_I2S_SendData(SPI1, a);

       

      /* Transfer procedure */

TxIdx = 0;

      while (TxIdx < a )

      {

            /* Wait for SPI1 Tx buffer empty */

            while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

            SPI_I2S_SendData(SPI1, SPI1_Buffer_Tx[TxIdx++]);      

      }

}

}

接送端(SPI2 slave)程式碼

#include "stm32f10x.h"

#include "stdio.h"

#include "hw_config.h"

#include "stm32_eval.h"

 

/* Private define ------------------------------------------------------------*/

#define BufferSize  32 //接收資料buffer大小

 

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef  SPI_InitStructure;

/*接收資料,3216位元資料*/

uint16_t  SPI2_Buffer_Rx[BufferSize]={0 };

uint32_t RxIdx = 0;

/* Private functions ---------------------------------------------------------*/

void RCC_Configuration(void);//設定SPI RCC

void GPIO_Configuration(void);//設定SPI GPIO

 

int main(void)

{

  int a,b;//b為接收筆數

  Set_System();

  /* SPI clocks configuration ---------------------------------------------*/

  RCC_Configuration();

  /* SPI GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

 

  /* SPI2 configuration ------------------------------------------------------*/

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   

  SPI_Init(SPI2, &SPI_InitStructure);

 

  /* Enable SPI2 */

  SPI_Cmd(SPI2, ENABLE);    

 

  while (1)

  {  

      while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

    /* 接收要接收的資料數量 */

     b = SPI_I2S_ReceiveData(SPI2);

         /* received procedure */

RxIdx = 0;

  while (RxIdx< b)

  {

    /* Wait for SPI2 data reception */

   while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

    /* Read SPI2 received data */

   SPI2_Buffer_Rx[RxIdx] = SPI_I2S_ReceiveData(SPI2);

     RxIdx++;                  

  }                                                         

       

/**********************/

    /*使用VCP印出接收資料*/

        printf("get data %d\n\r",b);

        a = 0;

        while (a <  b)

        {

         printf("SPI2 Rx%d : %d\n\r",a,SPI2_Buffer_Rx[a]);

         a++;

        };     

/**********************/

  }

}

實驗結果

 

image006  

 

COM4SPI1結果,COM9SPI2結果

實驗三 傳送32位元的資料

實驗說明:接續實驗一,SPI1傳送1632位元的資料給SPI2,因為傳收和接收buffer,只有16位元,所以SPI1先將32位元的資料拆成二筆16位元的資料,再傳給SPI2,而SPI2收到後,再將二筆16位元資料組成一筆32位元資料。

主要程式碼說明

傳送端(SPI1 master)程式碼

#include "stm32f10x.h"

#include "stdio.h"

#include "hw_config.h"

#include "stm32_eval.h"

 

/* Private define ------------------------------------------------------------*/

#define BufferSize  32 //傳送資料buffer大小

 

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef  SPI_InitStructure;

/*傳送資料,1632位元資料*/

uint32_t SPI1_Buffer_Data[BufferSize/2] = {65536,65537,65538,65539,65540,65541,65542,65543,65544,65545,65546,65547,65548,65549,65550,65551}; uint32_t TxIdx = 0; //

/* Private functions ---------------------------------------------------------*/

void RCC_Configuration(void);//設定SPI RCC

void GPIO_Configuration(void);//設定SPI GPIO

 

int main(void)

{

  int a;//傳送筆數

  Set_System();

  /* SPI clocks configuration ---------------------------------------------*/

  RCC_Configuration();

  /* SPI GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

 

  /* SPI1 configuration ------------------------------------------------------*/

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 

  SPI_Init(SPI1, &SPI_InitStructure); 

 

  /* Enable SPI1 */

  SPI_Cmd(SPI1, ENABLE);

 

 /* Transfer procedure */

  while (TxIdx < BufferSize )

  {

    /* Wait for SPI1 Tx buffer empty */

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

       

    //32位元資料拆成二筆16位元資料

        if(TxIdx % 2 == 0)

     SPI1_Buffer_Tx[TxIdx] = ((SPI1_Buffer_Data[TxIdx/2] & 0xffff0000) >> 16);

        else 

         SPI1_Buffer_Tx[TxIdx] = ((SPI1_Buffer_Data[TxIdx/2] & 0x0000ffff));

 

    /* Send SPI1 data */      

    SPI_I2S_SendData(SPI1, SPI1_Buffer_Tx[TxIdx++]);   

  }

  while (1)

  {                                                                   

        getchar();

        printf("transmit complete\n\r");

        a = 0;

        while(a < 16)

        {

           printf("%d\n\r",SPI1_Buffer_Data[a]);

           a++;

        }   

  }

}

接送端(SPI2 slave)程式碼

#include "stm32f10x.h"

#include "stdio.h"

#include "hw_config.h"

#include "stm32_eval.h"

 

/* Private define ------------------------------------------------------------*/

#define BufferSize  32 //接收資料buffer大小

 

/* Private variables ---------------------------------------------------------*/

SPI_InitTypeDef  SPI_InitStructure;

/*接收資料,1632位元資料*/

uint32_t SPI2_Buffer_Data[BufferSize/2]={55,55,55,

55,55,55,55,55,55,55,55,55,55,55};

uint32_t RxIdx = 0;

/* Private functions ---------------------------------------------------------*/

void RCC_Configuration(void);//設定SPI RCC

void GPIO_Configuration(void);//設定SPI GPIO

 

int main(void)

{

  int a,b;//b為接收筆數

  Set_System();

  /* SPI clocks configuration ---------------------------------------------*/

  RCC_Configuration();

  /* SPI GPIO configuration ------------------------------------------------------*/

  GPIO_Configuration();

 

  /* SPI2 configuration ------------------------------------------------------*/

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   

  SPI_Init(SPI2, &SPI_InitStructure);

 

  /* Enable SPI2 */

  SPI_Cmd(SPI2, ENABLE);    

    /* received procedure */

  while (RxIdx< BufferSize )

  {

       /* Wait for SPI2 data reception */

    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

     /* Read SPI2 received data */

      SPI2_Buffer_Rx[RxIdx] = SPI_I2S_ReceiveData(SPI2);

         //將二筆16位元資料組成一筆32位元

         if(RxIdx % 2 == 0)

                  SPI2_Buffer_Data[RxIdx/2] = SPI2_Buffer_Rx[RxIdx] << 16;

         else

               SPI2_Buffer_Data[RxIdx/2] += SPI2_Buffer_Rx[RxIdx] ;

        RxIdx++; 

  }

 

  while (1)

  {                                                                   

        getchar();

       

        a = 0;

        while (a <  BufferSize/2)

        {

         printf("SPI2 RX%d : %d\n\r",a,SPI2_Buffer_Data[a]);

         a++;

        }

  }

}

實驗結果

 

image007  

COM4SPI1結果,COM9SPI2結果

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 youboook 的頭像
    youboook

    youboook的部落格

    youboook 發表在 痞客邦 留言(0) 人氣()