SPI通讯

本文详细介绍了SPI物理层的连接方式和功能,包括SCK、MOSI、MISO和NSS的作用。进一步阐述了SPI协议层的基本通讯过程、数据有效性、CPOL/CPHA设置以及与I2C的比较,指出SPI在高速应用中的优势和I2C在低速场景的适用性。



前言

本章可与I2C章节对比阅读,体会两种通讯总线差异。本章主要对SPI协议层进行总结。

一、介绍SPI通讯

基本概念

SPI通讯是一种串行数据传输接口,通常用于在数字系统中通过高速(Mbps)的方式进行短距离通信。它被广泛应用于嵌入式系统、传感器网络、外围设备等领域。
SPI通讯设备之间的常用连接方式见下图。

工作原理

SPI通讯使用3条总线及片选线,3条总线分别为SCKMOSIMISO,片选线为NSS ,它们的作用介绍如下:
SCK (Serial Clock):时钟信号线,用于通讯数据同步。
MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。
MISO(Master Input,Slave Output):主设备输入/从设备输出引脚。
NSS(Slave Select):从设备选择信号线,即有几个从设备就有几个NSS引脚。
在这里插入图片描述

二、总线结构

基本通讯过程

这是一个主机的通讯时序。NSS、SCK、MOSI信号都由主机控制产生,而MISO的信号由从机产生。

先发送高位再发送低位,发送完一个字节之后无需应答即可开始下个字节,NSS片选从设备作为起始/终止信号

在这里插入图片描述

数据有效性

  1. 在时钟线SCK上升沿/下降沿(CPOL=0/1)时,MOSI及MISO数据传输一位 数据传输时
  2. MSB先行或LSB先行并没有作硬性规定,但要保证两个SPI通讯设备之间使用同样的协定
  3. SPI每次数据传输可以8位或16位为单位,每次传输的单位数不受限制

CPOL/CPHA及通讯模式

SPI一共有四种通讯模式,如图

CPOLCPHA空闲时SCK时钟采样时刻
00低电平奇数边沿
01低电平偶数边沿
10高电平奇数边沿
11高电平偶数边沿

代码分析

  1. 打开SPI 总线的设备文件
  2. 设置SPI 工作模式
  3. 设置SPI通信过程中一个字节所占的位数(8)
  4. 设置SPI通信的波特率(500K)
static  uint32_t mode = SPI_MODE_2;    //用于保存 SPI 工作模式
static  uint8_t bits = 8;        // 接收、发送数据位数
static  uint32_t speed = 500000; // 发送速度

/*
* 初始化SPI
*/
void spi_init(void)
{
  int ret = 0;
  /*-------------------第一部分-------------------------*/
  /*打开 SPI 设备*/
  fd = open("/dev/spidev2.0", O_RDWR);
  if (fd < 0)
  {
    pabort("can't open /dev/spidev2.0 ");
  }

  /*-------------------第二部分-------------------------*/
  /*
      * spi mode 设置SPI 工作模式
      */
  ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
  if (ret == -1)
    pabort("can't set spi mode");

  ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
  if (ret == -1)
    pabort("can't get spi mode");

  /*-------------------第三部分-------------------------*/
  /*
      * bits per word  设置一个字节的位数
      */
  ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
  if (ret == -1)
    pabort("can't set bits per word");

  ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
  if (ret == -1)
    pabort("can't get bits per word");

  /*-------------------第四部分-------------------------*/
  /*
      * max speed hz  设置SPI 最高工作频率
      */
  ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
  if (ret == -1)
    pabort("can't set max speed hz");

  ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
  if (ret == -1)
    pabort("can't get max speed hz");

  printf("spi mode: 0x%x\n", mode);
  printf("bits per word: %d\n", bits);
  printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
}

SPI发送:将要发送的数据填入结构体spi_ioc_transfer,然后调用ioctl函数执行发送

void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
  int ret;
  /*------------------第一部分--------------------*/
  struct spi_ioc_transfer tr = {
      .tx_buf = (unsigned long)tx,
      .rx_buf = (unsigned long)rx,
      .len = len,
      .delay_usecs = delay,
      .speed_hz = speed,
      .bits_per_word = bits,
      .tx_nbits = 1,
      .rx_nbits = 1
  };

  /*------------------第二部分--------------------*/
  ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
  if (ret < 1)
  {
    pabort("can't send spi message");
  }
}
/*-------------------第一部分---------------------*/
/*SPI 接收 、发送 缓冲区*/
unsigned char tx_buffer[100] = "hello the world !";
unsigned char rx_buffer[100];

/*-------------------第二部分---------------------*/
int main(int argc, char *argv[])
{
     /*初始化SPI */
     spi_init();

     /*执行发送*/
     transfer(fd, tx_buffer, rx_buffer, sizeof(tx_buffer));

     /*打印 tx_buffer 和 rx_buffer*/
     printf("tx_buffer: \n %s\n ", tx_buffer);
     printf("rx_buffer: \n %s\n ", rx_buffer);

     close(fd);

     return 0;
}

三、SPI与I2C对比

  1. I2C速率:标准: 100 KHz、快速: 400 KHz、快速+: 1 MHz、高速: 3.4 MHz
    SPI速率:主要取决于 CPU 的 SPI 控制器时钟(clock)。常用设备比如STM32F103 最高支持 18 MHzi.MX6ULL 最高支持 52 MHzW25Q128 最高支持 80 MHz
    因此 I2C适用于低速外围设备,多用于传输命令SPI适用于高速应用,如SD卡、液晶屏多用于传输数据
  2. IIC为半双工,SPI为全双工
  3. IIC有应答机制信号,SPI无
  4. IIC的时钟和极性是固定的(空闲时高电平,SCL为高电平时读取数据),SPI是可以变化设置的
  5. 寻址方式不同,IIC是发送一个字节去寻址,SPI通过片选位选择

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值