单总线、IIC、SPI接口详解(三)

SPI为串行外设接口的缩写,SPI为高速全双工同步通信总线,共使用4根线。SPI以主从方式工作,通常可以一个主设备和一个或多个从设备。需要至少4根线。MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。CS是从设备是否被主设备选中的引脚,当被选中时(通常以CS为低电平选中),主设备与从设备的操作才有效。

三、SPI总线

1、采用SPI总线的常用设备。

常用的设备有:①W25Qxx的大容量FLASH存储芯片。②SPI的小OLED屏幕。③RC522的射频RFID读卡器④MCP2515的CAN总线模块等等

2、SPI总线的优点。

①仅占用4个引脚,节约了芯片的管脚。②简单易用。③支持高速(100Mhz以上)④支持全双工

3、SPI的缺点

①没有应答机制确认是否接收到数据②没有寻址机制,只能靠片选选择不同设备③典型应用只支持单主控

4、SPI协议

SPI也为串行通讯协议,数据通过MISO和MOSI一位一位的传进传出,SCLK提供时钟脉冲,且该信号只由主设备控制,从设备不能控制。普通的串行通讯一次需连续传送8bit,而SPI允许一位一位的传送,且可暂停。

二、硬件连接

SPI总线定义两个及两个以上设备间的数据通信,提供时钟信号的为主机,接收时钟信号的设备为从机。

1、电路连接:

①单主机单从机,如下图

spi总线

②单个主机和多个从机的连接

单个主机和多个从机的连接

2、SPI相关寄存器

以STM32为例,与SPI相关寄存器有:

SPI控制寄存器1(SPI_CR1)

SPI控制寄存器2(SPI_CR2)

SPI状态寄存器  (SPI_SR)

SPI数据寄存器  (SPI_DR)

SPI_I2S配置寄存器(SPI_I2S_CFGR)

SPI_I2S预分频寄存器(SPI_I2SPR)

3、SPI传输模式

通过控制SPI控制寄存器1中的CPOL和CPHA位,将SPI分为4种传输模式。

Mode0 CPOL=0,CPHA=0

Mode1 CPOL=0,CPHA=1

Mode2 CPOL=1,CPHA=0

Mode3 CPOL=1,CPHA=1

时钟极性CPOL:SPI空闲时,时钟信号sclk的电平(1:空闲时高电平,0:空闲时低电平)

时钟相位CPHA:SPI在SCLK第几个边沿开始采样(0:第一个边沿开始,1:第二个边沿开始)

其中常用的为Mode0和Mode3。

4、以STM32为例,SPI初始化程序以及设置速度程序如下:

  1. void SPI1_Init(void)
  2. {
  3.     RCC->APB2ENR|=1<<2;       //PORTA时钟使能    
  4.     RCC->APB2ENR|=1<<12;      //SPI1时钟使能 
  5.     //这里只针对SPI口初始化
  6.     GPIOA->CRL&=0X000FFFFF;
  7.     GPIOA->CRL|=0XBBB00000;//PA5.6.7复用      
  8.     GPIOA->ODR|=0X7<<5;    //PA5.6.7上拉
  9.     SPI1->CR1|=0<<10;//设置为双线双向全双工工作模式   
  10.     SPI1->CR1|=1<<9; //内部NSS信号管理:设置为软件管理
  11.     SPI1->CR1|=1<<8;
  12.     SPI1->CR1|=1<<2; //设置SPI为主机
  13.     SPI1->CR1|=0<<11;//SPI发送接收8位帧数据
  14.     SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1 空闲信号下的时钟极性
  15.     SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1 时间相位
  16.     SPI1->CR1|=7<<3; //Fsck=Fcpu/256 设置SPI分频系数
  17.     SPI1->CR1|=0<<7; //定义数据以MSB位开始 
  18.     SPI1->CR1|=1<<6; //SPI设备使能
  19.     SPI1_ReadWriteByte(0xff);//启动传输(主要作用:维持MOSI为高)       
  20. }
  21. //SpeedSet:0~7
  22. //SPI速度=fAPB2/2^(SpeedSet+1)
  23. //APB2时钟一般为72Mhz
  24. void SPI1_SetSpeed(u8 SpeedSet)
  25. {
  26.     SpeedSet&=0X07;         //限制范围
  27.     SPI1->CR1&=0XFFC7;
  28.     SPI1->CR1|=SpeedSet<<3;         //设置SPI1速度  
  29.     SPI1->CR1|=1<<6;        //SPI设备使能 
  30. }

5、SPI读写操作及时序

1、SPI的读取,以读取W25X16的ID为例,顺序为:主机拉低CS引脚,选中W25X16,主机控制SCLK引脚产生时钟信号。主机控制MOSI引脚,发送读取ID的指令0x90。

紧接着发送24位地址码。最后,读取MISO引脚,查看W25x16返回给主机的ID。

SPI读写操作及时序

参考代码:

  1. u16 SPI_Flash_ReadID(void)
  2. {
  3.     u16 Temp = 0;
  4.     SPI_FLASH_CS=0;
  5.     SPI1_ReadWriteByte(0x90);//发送读取ID命令     
  6.     SPI1_ReadWriteByte(0x00);
  7.     SPI1_ReadWriteByte(0x00);
  8.     SPI1_ReadWriteByte(0x00);
  9.     Temp|=SPI1_ReadWriteByte(0xFF)<<8;
  10.     Temp|=SPI1_ReadWriteByte(0xFF);
  11.     SPI_FLASH_CS=1;
  12.     return Temp;
  13. }

2、SPI的写入,同样以W25X16为例,指定地址写入数据的时序如下如所示,图中仅用16位数据位,可以更换为更长。

SPI的写入

参考代码:

  1. void SPI_Flash_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
  2. {
  3.     u16 i;
  4.     SPI_FLASH_Write_Enable();                  //SET WEL 
  5.     SPI_FLASH_CS=0;                            //使能器件   
  6.     SPI1_ReadWriteByte(W25X_PageProgram);      //发送写页命令 (0x02)  
  7.     SPI1_ReadWriteByte((u8)((WriteAddr)>>16)); //发送24bit地址    
  8.     SPI1_ReadWriteByte((u8)((WriteAddr)>>8));
  9.     SPI1_ReadWriteByte((u8)WriteAddr);
  10.     for(i=0;i<NumByteToWrite;i++)SPI1_ReadWriteByte(pBuffer[i]);//循环写数  
  11.     SPI_FLASH_CS=1;                            //取消片选 
  12.     SPI_Flash_Wait_Busy();                     //等待写入结束
  13. }

 

注:文章转自电子芯客吧,侵权删。

  • 版权声明: 本文源自 电子芯客吧, 于6年前,由整理发表,共 2999字。
  • 原文链接:点此查看原文
你想把广告放到这里吗?

发表评论

您必须 登录 才能发表留言!