|||
一、概述
采用SPI 中断模式实现两个STM32F205 MCU之间传输数据,传输数据量为1000*16bit。
二、通信方式
主机作为发送数据的一方,采用SPI2发送数据;从机作为接收数据的一方,采用SPI1接收数据。硬件连接方式如下:
主机——从机
SPI2_NSS——SPI1_NSS
SPI2_SCK——SPI1_SCK
SPI2_MISO——SPI1_MISO
SPI2_MOSI——SPI1_MOSI
在设计中采用两线全双工方式,只用到SCK和MOSI两根信号线。
三、主机(SPI2)代码详解
1、结构体变量定义
SPI_InitTypeDef
SPI_InitStructure;
GPIO_InitTypeDef
GPIO_InitStructure;
NVIC_InitTypeDef
NVIC_InitStructure;
2、相关时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
3、复用管脚映射
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
4、GPIO初始化
GPIO_InitStructure.GPIO_Mode =
GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed =
GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType =
GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd =
GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_13;
GPIO_Init(GPIOB,
&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOB,
&GPIO_InitStructure);
5、SPI初始化
SPI_I2S_DeInit(SPI2);
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_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2,
&SPI_InitStructure);
6、NVIC初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel =
SPI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =
0;
NVIC_InitStructure.NVIC_IRQChannelCmd =
ENABLE;
NVIC_Init(&NVIC_InitStructure);
7、使能中断和SPI2
SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_TXE,ENABLE);
SPI_Cmd(SPI2,
ENABLE);
8、SPI2中断服务函数
void
SPI2_IRQHandler(void)
{
if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_TXE)
== SET)
{
SPI_I2S_SendData(SPI2,TxBuffer[Tx_Idx++]);
if(Tx_Idx == TXBUFFERSIZE)
{
Tx_Idx = 0;
}
}
}
四、从机(SPI1)代码详解
1、结构体变量定义
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
2、相关时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA
,ENABLE);
3、复用管脚映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1);
4、GPIO初始化
GPIO_InitStructure.GPIO_Mode =
GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed=
GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType=
GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=
GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOA,
&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA,
&GPIO_InitStructure);
5、SPI初始化
SPI_Cmd(SPI1,
DISABLE);
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_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1,
&SPI_InitStructure);
6、NVIC初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Configure
the SPI interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
7、使能中断和SPI2
SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
SPI_Cmd(SPI1, ENABLE);
8、SPI1中断服务函数
void
SPI1_IRQHandler(void)
{
if (SPI_I2S_GetITStatus(SPI1,
SPI_I2S_IT_RXNE) == SET)
{
RxBuffer[Rx_Idx++] =
SPI_I2S_ReceiveData(SPI1);
if(Rx_Idx == RXBUFFERSIZE)
{
Rx_Idx = 0;
}
}
}
五、相关设计说明
1、发送和接收数据量均1000,单次发送,从机接收到的数据不会错乱,连续发送会出现数据错乱现象,这可以通过软件方式来区分每次发送的起始和开始来解决,今后本博客会采用STM32F2系列SPI所支持的TI
Mode来解决。
2、波特率设置
细心的读者会发现主机的波特率设置为SPI_BaudRatePrescaler_2,而从机的波特率设置为SPI_BaudRatePrescaler_4。这是因为对于STM32F2系列的单片机来说,SPI1挂接在APB2总线上,其最高时钟频率为60MHz,而SPI的最高波特率为该时钟频率的一半,即30Mbps;而SPI2挂接在APB1总线上,其最高时钟频率为30MHz,而SPI的最高波特率为该时钟频率的一半,即15Mbps。为了能使二者能够通信,波特率必须相同,因而设置通信波特率为15Mbps,那么就需要对SPI1的波特率设置为时钟的4分频。