STM32通信接口(三)硬件SPI

     一、概述 

      SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,是Motorola最先在其的MC68HCXX芯片上使用,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。

        SPI接口主要应用在实时时钟、E2PROM、FLASH、AD转换器还有数字信号处理器和数字信号解码器之间,它的用途相当广泛。而且其传输速度较快一般可以达到10M以上。

二、基本原理

        

        由图可知SPI一般由四条线组成:MISO(主机输入从机输出)、MOSI(主机输出从机输入)、SCLK(时钟线)、CS(片选信号)

        四线模式的SPI支持全双工,如果把MISO和MOSI合为一条数据线,就变成了三线SPI,只支持半双工。

        主机的数据通过移位寄存器传输给从机时,从机的数据也会通过它的移位寄存器传输给主机

         示例:(从最低位开始)

                                                主机                        从机

                                               00000000                11111111

                第一个时钟周期      00000001                11111110

扫描二维码关注公众号,回复: 396391 查看本文章

                第二个时钟周期      00000011                11111100 

                 ......

                 第八个时钟周期      11111111                00000000

        所以说每次的数据传输就相当于主机从机的数据进行交换

        由此,如果要传输数据给从机,主机只要忽略掉从从机接收到的数据即可,如果要从从机读取数据,就可以发送无意义的数据给从机(如0x00)

       注意:大多数情况下发送和接收并不会同时进行。

三、STM32上的SPI

        STM32 上的SPI接口提供俩个功能,支持SPI协议和I2S音频协议,默认情况下,选择的是SPI功能。可通过软件将接口从SPI切换到I2S。

        STM32上SPI的特性如下

        

    

      SPI的框图如下:       

    这个框图并不复杂,主要要关注的就是MISO和MOSI那里。

    数据总线中的数据写入发送缓冲区,通过移位寄存器一位一位的从MOSI发送,同时从机返回的数据从MISO进入移位寄存器,进入接收缓冲区。

    下面的部分就是波特率发生器,主控制逻辑以及通信控制。

    注意:CPOL(时钟极性)决定SPI接口传输时时钟空闲状态的电平(1,高电平;0,低电平)

                CPHA(时钟相位)控制在时钟的第一个还是第二个边沿被采集(1,第二个边沿,0,第一个边沿)

                

四、STM32 上SPI的实现流程

       1、配置相关引脚的复用功能,使能SPI时钟

        2、设置SPI的工作模式

        3、使能SPI

        代码如下:

        初始化函数     

void SPI1_Init(void)
{	 
	u16 tempreg=0;
	RCC->AHB1ENR|=1<<0;    	//使能PORTA时钟	   
	RCC->APB2ENR|=1<<12;   	//SPI1时钟使能 
	GPIO_Set(GPIOB,7<<3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);	//PB3~5复用功能输出	
  	GPIO_AF_Set(GPIOB,3,5);	//PB3,AF5
 	GPIO_AF_Set(GPIOB,4,5);	//PB4,AF5
 	GPIO_AF_Set(GPIOB,5,5);	//PB5,AF5 

	//这里只针对SPI口初始化
	RCC->APB2RSTR|=1<<12;	//复位SPI1
	RCC->APB2RSTR&=~(1<<12);//停止复位SPI1
	tempreg|=0<<10;			//全双工模式	
	tempreg|=1<<9;			//软件nss管理
	tempreg|=1<<8;			 
	tempreg|=1<<2;			//SPI主机  
	tempreg|=0<<11;			//8位数据格式	
	tempreg|=1<<1;			//空闲模式下SCK为1 CPOL=1 
	tempreg|=1<<0;			//数据采样从第2个时间边沿开始,CPHA=1  
 	//对SPI1属于APB2的外设.时钟频率最大为84Mhz频率.
	tempreg|=7<<3;			//Fsck=Fpclk1/256
	tempreg|=0<<7;			//MSB First  
	tempreg|=1<<6;			//SPI启动 
	SPI1->CR1=tempreg; 		//设置CR1  
	SPI1->I2SCFGR&=~(1<<11);//选择SPI模式
	SPI1_ReadWriteByte(0xff);//启动传输		 
}   

        这里对SPI1进行初始化,首先使能IO口的时钟,初始化IO口味复用功能,复用为SPI1,。首先先复位SPI1,设置为全双工模式,软件从器件管理,内部从器件选择,作为主机,八位数据格式,空闲状态高电平,第二个时间边沿开始采样,设置波特率256分频,从最高位开始传输,使能SPI。

        再选择SPI模式(I2SCFGR寄存器的第11位)

        发送一个字节启动传输

    传输速度设置函数 

//SPI1速度设置函数
//SpeedSet:0~7
//SPI速度=fAPB2/2^(SpeedSet+1)
//fAPB2时钟一般为84Mhz
void SPI1_SetSpeed(u8 SpeedSet)
{
	SpeedSet&=0X07;			//限制范围
	SPI1->CR1&=0XFFC7; 
	SPI1->CR1|=SpeedSet<<3;	//设置SPI1速度  
	SPI1->CR1|=1<<6; 		//SPI设备使能	  
} 

    通过改变分频系数来设置SPI的传输速度

读写一个字节

//SPI1 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI1_ReadWriteByte(u8 TxData)
{		 			 
	while((SPI1->SR&1<<1)==0);		//等待发送区空 
	SPI1->DR=TxData;	 	  		//发送一个byte  
	while((SPI1->SR&1<<0)==0);		//等待接收完一个byte  
 	return SPI1->DR;          		//返回收到的数据				    
}

    TxDate为要发送的字节,函数的返回值为接收到的字节

五、使用SPI

    在使用SPI时先将片选信号拉低选中从器件,然后发送或者接收数据,完成后,拉高片选。

    随后的博客会通过W25Q128的使用来介绍SPI的使用。

      


猜你喜欢

转载自blog.csdn.net/a568713197/article/details/80185187