第9章
SPI
9.1 STM32 SPI簡介
serial peripheral interface (SPI) 可以與外部週邊半/ 全雙工、同步、串列通信,SPI可設為master,並提供外部週邊通訊clock (SCK),SPI也可以在多個master情況使用。
STM32F10x處理器SPI結構圖
通常SPI透過4個pin去連接外部週邊:
● 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置配
Slave select (NSS) pin management
STM32F10x提供2種NSS模式
● 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
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通訊介面傳收資料
實驗說明:將一SIOC的SPI1設為master ,另一SIOC的SPI2設為slave,SPI1傳送32筆16位元的資料給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;
/*傳送資料,32筆16位元資料*/
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;
/*接收資料,32筆16位元資料*/
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);
}
接線示意圖
實驗結果
COM4為SPI1結果,COM9為SPI2結果
實驗二 可變資料筆數的傳收
實驗說明:接續實驗一,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;
/*傳送資料,32筆16位元資料*/
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;
/*接收資料,32筆16位元資料*/
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++;
};
/**********************/
}
}
實驗結果
COM4為SPI1結果,COM9為SPI2結果
實驗三 傳送32位元的資料
實驗說明:接續實驗一,SPI1傳送16筆32位元的資料給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;
/*傳送資料,16筆32位元資料*/
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;
/*接收資料,16筆32位元資料*/
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++;
}
}
}
實驗結果
COM4為SPI1結果,COM9為SPI2結果
留言列表