赞
踩
目录
这是一篇学习笔记,记录自己学习SPI通信。方便之后运用的时候回顾。参考《STM32中文参考手册》
SPI通信设备连接图

SPI框图

SPI主模式配置
1. 通过SPI_CR1寄存器的BR[2:0]位定义串行时钟波特率。
2. 选择CPOL和CPHA位,定义数据传输和串行时钟间的相位关系。
3. 设置DFF位来定义8位或16位数据帧格式。
4. 配置SPI_CR1寄存器的LSBFIRST位定义帧格式。
5. 如果需要NSS引脚工作在输入模式,硬件模式下,在整个数据帧传输期间应把NSS脚连接到高电平;在软件模式下,需设置SPI_CR1寄存器的SSM位和SSI位。如果NSS引脚工作在输出模式,则只需设置SSOE位。
6. 必须设置MSTR位和SPE位(只当NSS脚被连到高电平,这些位才能保持置位)。 在这个配置中,MOSI引脚是数据输出,而MISO引脚是数据输入。
SPI从模式配置
主模式通讯过程

从模式通讯过程

我的想法是在串口助手上发送给主机什么,主机就发什么给从机。之后从机把接收的数据再返回给主机,最终再串口助手上打印出来。验证SPI的全双工通讯。主机和从机都采用中断的方式发送和接收。
SPI配置代码
- void SPI2_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- SPI_InitTypeDef SPI_InitStructure;
-
- /* SPI的IO口和SPI外设打开时钟 */
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PB12推挽输出
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- /* SPI的IO口设置 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_SetBits(GPIOB,GPIO_Pin_12);
-
- 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_16b; //设置SPI的数据大小:SPI发送接收8位帧结构
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
- SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
- SPI_Cmd(SPI2, ENABLE); //使能SPI外设
-
-
- }

串口中断部分
- void USART1_IRQHandler(void) //串口1中断服务程序
- {
- u16 r,i;
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
- {
- GPIO_ResetBits(GPIOB,GPIO_Pin_12);
- r =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空
- SPI_I2S_SendData(SPI2, r);
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //等待接收完一个byte
- i = SPI_I2S_ReceiveData(SPI2);
-
- GPIO_SetBits(GPIOB,GPIO_Pin_12);
- USART_senddate(USART1,i) ;
- }
- }

- void SPI2_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- SPI_InitTypeDef SPI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- /* SPI的IO口和SPI外设打开时钟 */
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PB12推挽输出
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //下拉输入
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- /* SPI的IO口设置 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
- SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; //设置SPI工作模式:设置为主SPI
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //设置SPI的数据大小:SPI发送接收8位帧结构
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
- SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
- SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
-
- SPI_Cmd(SPI2, ENABLE); //使能SPI外设
-
-
- SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);//开启相关中断
- //Usart1 NVIC 配置
- NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;//SPI2中断通道
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =2; //子优先级2
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
-
- }
- u16 i;
- void SPI2_IRQHandler(void)
- {
- //接收数据
- if(SPI_I2S_GetITStatus(SPI2,SPI_I2S_IT_RXNE) != RESET)
- {
- i = SPI_I2S_ReceiveData(SPI2);
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
- SPI_I2S_SendData(SPI2,i);
- USART_senddate(USART1, i);
- }
-
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。