SPI概述

来源:互联网 发布:广东淘宝卖家卷款逃跑 编辑:程序博客网 时间:2024/05/16 03:57

SPI概述

一、SPI简介    

        SPI是一种串行外围设备接口,高速全双工的通信总线,广泛应用于ADCLCD等设备于MCU间通信场合。   

         SPI包含4条总线,分别为NSSSCKMISOMOSI,各信号线功能如下:     

  1. NSS  

       NSS为片选信号,当NSS信号为低电平时,片选有效,开始SPI主从模式通讯。

       SPI主从模式的配置真正起作用的是内部NSS引脚,内部NSS引脚才真正连接到SPI通讯控制器上。软件NSS模式和硬件NSS模式由SSM控制位实现,SSM位控制内部NSS引脚与SSI位(软件模式)相连,还是与NSS外部引脚(STM32引脚,硬件模式)。如图1-1所示。

 

1-1内外部NSS

    在实际的应用中,STM32SPI功能通常用作主模式。选择软件模式输入控制内部NSS为高电平,使能外部NSS管脚为普通IO口输出低电平来使能从设备,实现一主多从设备的数据交流。如图1-2所示。

 

1-2 一主多从

 

  2. SCK  

      SCK时钟信号线,由主通讯设备产生,不同的设备支持的时钟频率不一样,STM32SPI时钟频率最大为fpclk/2.

  3.  MISOMOSI

      MISOMOSI主设备和从设备通讯数据线。MISO为从主机到从机,MOSI为从从机到主机。

二、SPI寄存器配置

    因为在实际的应用中,STM32SPI功能通常用作主模式,选择软件模式配置NSS管脚,在此SPI1为例说明该种SPI工作模式配置步骤:

  1. 使能SP1时钟,配置GPIOA5678

   查找《STM32参考手册》中系统结构图得知SPIGPIOA均挂载在APB2时钟线上,查找APB2外设时钟使能寄存器(RCC_APB2ENR)(图1-4),使能SPIGPIOA的时钟:

      RCC->APB2ENR |= 1<<2;   //使能GPIOA时钟;

      RCC->APB2ENR |= 1<<12;  //使能SPI1时钟;

   参考前文《GPIO概述》配置5,6,7,为复用推挽输出:

      GPIOA->CRL &= 0x000FFFFF;    

      GPIOA->CRL |= 0xBBB00000;  //复用推挽输出

      GPIOA->ODR |= 0x07<<5;    //上拉

 

1-3 STM32系统结构图

 

1-4 RCC_APB2ENR

  2. 开全双工模式并配置软件管理NSS

      SPI1->CR1 |= 0<<10;   //全双工模式

      SPI1->CR1 |= 1<<9;    //软件NSS-SSM

      SPI1->CR1 |= 1<<8;    //软件NSS-SSI

 

1-5 SPI_CR1

 

  3. 设置SPI1位主机并设置数据帧格式

      SPI1->CR1 |= 1<<2;    //SPI主机

      SPI1->CR1 |= 0<<11;   //8bit数据格式

  4. 设置时钟极性和相位极性

      SPI1->CR1 =1<<1;    //空闲模式下SCK=1CPOL=1

      SPI1->CR1 = 1<<0;   //数据采样从第二个时钟边沿开始,CPHA=1

  5. 传输速度和LSBfIRST帧格式设置

     SPI1->CR1 |=7<<3;    //设置SCK波特率为

     SPI1->CR1 |=0<<7;  //MSBfirst

  6. 使能SPI1

     SPI1->CR1 |=1<<6;     //SPI设备使能

三、SPI库配置

   Void SPI1_Configuration(void)

       {

          SPI_InitTypeDef SPI_InitStructure;

          GPIO_InitTypeDef GPIO_InitStructure;

          GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;

          GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

          GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出

          GPIO_Init(GPIOA,&GPIO_InitStructure);

 

          GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;

          GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

          GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //NSS推挽输出

          GPIO_Init(GPIOB,&GPIO_InitStructure);

 

          SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//SPI设置为双线双向全双工

          SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//设置为主SPI

          SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//SPI发送接收8位帧结构

          SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;//设置时钟悬空高

          SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;//数据捕获于第二个时钟沿

          SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//内部NSS信号SSI位控制,SSI=1SSM=1

          SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//波特率预分频值为 8

          SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//数据传输从MSB位开始

          SPI_InitStructure.SPI_CRCPolynomial = 7;//SPI_CRCPolynomial定义了用于CRC值计算的多项式

         SPI_Init(SPI1,&SPI_InitStructure);//参数传送

         SPI_Cmd(SPI1,ENABLE); //使能 SPI

    }

四、SPI数据接收/发送

   寄存器版

     u8 SPI1_ReadWriteByte(u8 TxData)

     {

          While((SPI1->SR &1<<1) ==0);  //发送区非空循环,TXE=1为空

           SPI1->DR = TxData;

         While((SPI1->SR &1<<0) ==0);    //等待接收到一个字节,RXNE=1为空

        Return SPI1->DR;  

   }

   库操作版:

     u8 SPI_SendWriteByte(u8 byte) //SPI 读写函数

    {

       while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET);//判断发送缓冲区是否为空

       SPI_I2S_SendData(SPI1,byte);//发送数据

       while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET);//判断接收缓冲区是否是空的

       return SPI_I2S_ReceiveData(SPI1);//接收数据,并返回到接收缓冲区

   }

五、SPI接收中断

    中断开启:SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);

    中断清除:SPI_I2S_ClearFlag(SPI1,SPI_I2S_IT_RXNE);  //实际工作中,读取SPI_DR寄存器时将清除RXNE位,因此可以不用清除中断标志,同USART

 

 

  

原创粉丝点击