YFY的工程师之路 https://bbs.21ic.com/?660325 [收藏] [复制] [RSS] 见证YFY技术发展之路!

日志

STM32F2系列驱动开发——双机SPI通信(中断模式)

已有 1041 次阅读2016-5-11 16:40 |个人分类:嵌入式系统开发|系统分类:嵌入式系统| STM32F2, SPI, 双机通信

一、概述



采用SPI 中断模式实现两个STM32F205 MCU之间传输数据,传输数据量为1000*16bit



二、通信方式



主机作为发送数据的一方,采用SPI2发送数据;从机作为接收数据的一方,采用SPI1接收数据。硬件连接方式如下:



主机——从机



SPI2_NSS——SPI1_NSS



SPI2_SCK——SPI1_SCK



SPI2_MISO——SPI1_MISO



SPI2_MOSI——SPI1_MOSI



在设计中采用两线全双工方式,只用到SCKMOSI两根信号线。



三、主机(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);



4GPIO初始化



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);



5SPI初始化



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);



6NVIC初始化



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);



8SPI2中断服务函数



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);



4GPIO初始化



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);



5SPI初始化



  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);



6NVIC初始化



 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);



8SPI1中断服务函数



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分频。



 


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)