STM32的SPI控制器实现SPI

控制/MCU

1883人已加入

描述

SPI是一种高速的,全双工,同步的通信总线,原理和使用简单,占用引脚资源少,是一种常用的通信方式。STM32通常有2~3个SPI接口。

SPI接口

使用SPI控制器时,GPIO引脚的模式配置就要改为复用功能了,复用为SPI1功能。由于片选信号引脚没有连接到STM32中SPI1的NCC引脚上,所以片选信号引脚仍要设置为通用输出模式。

配置完GPIO口,接下来就要配置SPI1功能了。

SPI控制寄存器1(SPI_CR1)

SPI接口

双向通信数据模式使能位BIDIMODE(Bidirectional data mode enable)在位15,置0为选择双线单向通信数据模式,置1为选择单线双向通信数据模式。

双向通信模式下的输出使能位BIDIOE (Output enable in bidirectional mode)在位14,此位结合 BIDIMODE 位,用于选择双向通信模式下的传输方向,置0为禁止输出(只接收模式),置1为使能输出(只发送模式)。

数据帧格式位DFF (Data frame format)在位11,置0为发送/接收选择8位数据帧格式,置1为发送/接收选择16为数据帧格式。为确保正确操作,只应在禁止SPI时对此位执行操作。

软件从器件管理位SSM (Software slave management)在位9,当SSM置1时,NSS引脚输入替换为SSI位的值。

帧格式位LSBFIRST (Frame format)在位7,置0时先发送MSB,置1时先发送LSB。正在通信时不应更改此位。

SPI 使能位SPE (SPI enable)在位6,置0时关闭外设,置1时使能外设。

波特率控制位BR(Baud rate control)[2:0]在位3~5,000时为fPCLK/2,001时为fPCLK/4,010时为fPCLK/8,011时为fPCLK/16,100时为fPCLK/32,101时为fPCLK/64,110时为fPCLK/128,111时为fPCLK/256。正在通信时不应更改这些位。

主模式选择位MSTR (Master selection)在位2,置0时为从配置,置1时为主配置。正在通信时不应更改此位。

时钟极性位CPOL (Clock polarity)在位1,置0时,空闲状态时,SCK保持低电平;置1时,空闲状态时,SCK保持高电平。正在通信时不应更改此位。

时钟相位位CPHA (Clock phase)在位0,置0时从第一个时钟边沿开始采样数据,置1时从第二个时钟边沿开始采样数据。正在通信时不应更改此位。

//F_CS:PB14
//SPI1_SCK:PB3
//SPI1_MISO:PB4  - >输入
//SPI1_MOSI:PB5
void Spi1_Init()
{
  //1. 开端口时钟
  RCC- >AHB1ENR  |= 1< < 1;
  //2. 设置模式(复用:PB3/4/5)、通用输出:PB14
  GPIOB- >MODER  &= ~(0X3< < 28);
  GPIOB- >MODER  |= 1< < 28;

  GPIOB- >MODER  &= ~(0X3F< < 6);
  GPIOB- >MODER  |= 2< < 6 | 2< < 8 | 2< < 10;  

  //3. 设置输出类型、输出速度
  GPIOB- >OTYPER  &= ~(1< < 14 | 1< < 3 | 1< < 5);    //推挽
  GPIOB- >OSPEEDR  &= ~(0X3< < 28 | 0X3F< < 6);
  GPIOB- >OSPEEDR  |= 1< < 28;      //25mHZ
  GPIOB- >OSPEEDR  |= 2< < 6 | 2< < 8 | 2< < 10;
  //4. 上下拉
  GPIOB- >PUPDR    &= ~(0X3F< < 6 | 0X3< < 28);
  //5. 复用功能选择
  GPIOB- >AFR[0]    &= 0XFF000FFF;
  GPIOB- >AFR[0]    |= 0X00555000;    //复用为SPI1

  //6. 开spi1模块时钟
  RCC- >APB2ENR    |= 1< < 12;
  //7. 传输方式(两线)、帧数据位数(8),校验(无)、设置先发位(高位)
  SPI1- >CR1  = 0;
  SPI1- >CR1 |= 0X3< < 8;      //ssm=1,ssi=1,采用软件管理
  //8. 波特率、模式(主)
  SPI1- >CR1  |= 1< < 3;        //波特率为:21M,最高可设置42M
  SPI1- >CR1 |= 1< < 2;
  //9. 极性、相位(模式0、模式3均可)
  SPI1- >CR1  |= 3< < 0;        //模式3
  //使能SPI
  SPI1- >CR1  |= 1< < 6;
}

SPI状态寄存器(SPI_SR)

SPI接口

发送缓冲区为空判断位TXE (Transmit buffer empty)在位1,置0时发送缓冲区非空,置1时发送缓冲区为空。

接收缓冲区非空判断位RXNE (Receive buffer not empty)在位0,置0时接收缓冲区为空,置1时接收缓冲区非空。

GPIO口和复用功能配置好后,就是数据的收发了,现在不再判断输入输出口的电平来收发数据。发送数据时通过判断状态寄存器的发送缓冲区是否为空,再把数据送到数据寄存器。接收数据时通过判断接收缓冲区是否有数据,再从数据寄存器读取数据。

//spi收发
//发数据,高位在前
u8 Spi1_RevSendByte(u8 dat)
{
  //发送数据
  while((SPI1- >SR  & (1< < 1)) == 0);
  SPI1- >DR = dat;
  //接收数据
  while((SPI1- >SR & (1< < 0)) == 0);
  dat = SPI1- >DR;

  return dat;
}

配置为SPI控制器读写W25Q64,只要更改以上两个函数就可以了。主函数仍为串口接收文件并保存。程序编译后烧入开发板,串口发送main.c文件并保存到W25Q64,从W25Q64读取并打印保存的内容,与main.c文件完全一致,SPI控制器读写W25Q64成功。

SPI接口

SPI控制器读写W25Q64与IO口模拟SPI读写W25Q64相比,使用SPI控制器时只需配置寄存器就可以由硬件自动产生时序,不需要STM32通过软件模拟构造,减少了对CPU资源的消耗。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分