SPI总结

概念

SPI,又称串行外设接口,一种全双工的高速同步总线,没有速度的限定,通常能到10Mbps,并且可以同时接收同时发送,以工作与主机或从机模式,但不支持多主机模式,支持一主机多从机

硬件原理

SPI通信需要至少4根线(如图一所示),单向传输时是3根线(如图二、三、四所示),它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)和CS/SS(片选)。

图一:

image-20221202143104664

图二:典型的单工模式连接(主机:接收,从机:发送)

image-20221202190618541

图三:典型的单工模式连接(主机:只发送,从机:接收)

图四:典型的双向线连接

image-20221202190833072

MISO/SDI:从机向主机发送数据(接收总线);

MOSI/ SDO:主机向从机发送数据(发送总线);

SCLK:时钟信号,由主设备产生;

CS/SS:选择从机,只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。

注:时钟极性(CKP/CPOL)和相位(CKE/CPHA)共同决定读取数据的方式,比如信号上升沿读取数据还是信号下降沿读取数据。

多从机模式

有两种方法可以将多个从设备连接到主设备:多片选和菊花链。

方式一:多片选

每个从机都需要一条单独的片选(SS)线。如果要和特定的从机进行通讯,可以将相应的片选信号(NSS)线拉低,并保持其他SS信号线的状态为高电平。

缺点:

如果同时将两个SS信号线拉低,则可能会出现乱码,因为从机可能都试图在同一条MISO线上传输数据,最终导致接收数据乱码。

image-20221202182623588

方式二:菊花链

在设备信号(总线信号或中断信号)以串行的方式从一 个设备依次传到下一个设备,不断循环直到数据到达目标设备的方式被称为菊花链。

缺点:

菊花链的最大缺点是因为是信号串行传输,因为越到下面的设备,优先级越低,所以一旦数据链路中的某设备发生故障的时候,它下面优先级较低的设备就不可能得到服务了,可能将接收不到数据。

image-20221202183112607

工作模式

通信操作模式有4种,区别是定义了在时钟脉冲的哪条边沿发送数据,然而发送数据又取决于 “时钟极性(CKP/CPOL)” 和 “相位(CKE/CPHA)”,如下图所示。

Mode0:CKP=0,CKE =0:当空闲态时,SCK处于低电平,数据采样是在第1个边沿,也就是SCK由低电平到高电平的跳变,所以数据采样是在上升沿(准备数据),(发送数据)数据发送是在下降沿。

Mode1:CKP=0,CKE=1:当空闲态时,SCK处于低电平,数据发送是在第2个边沿,也就是SCK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。

Mode2:CKP=1,CKE=0:当空闲态时,SCK处于高电平,数据采集是在第1个边沿,也就是SCK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。

Mode3:CKP=1,CKE=1:当空闲态时,SCK处于高电平,数据发送是在第2个边沿,也就是SCK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。

image-20241013205611174

SPI优缺点

  • 优点

  1. 无起始位和停止位,因此数据位可以连续传输而不会被中断;

  2. 没有像I2C这样复杂的从设备寻址系统;

  3. 数据传输速率比I2C更高(几乎快两倍);

  4. 分离的MISO和MOSI信号线,因此可以同时发送和接收数据;

  5. 极其灵活的数据传输,不限于8位,它可以是任意大小的字;

  6. 非常简单的硬件结构。从站不需要唯一地址(与I2C不同)。

  7. 从机使用主机时钟,不需要精密时钟振荡器/晶振(与UART不同)。

  8. 不需要收发器(与CAN不同)。

  • 缺点

  1. 使用四根信号线(I2C和UART使用两根信号线);

  2. 无法确认是否已成功接收数据(I2C拥有此功能);

  3. 没有任何形式的错误检查,如UART中的奇偶校验位;

  4. 只允许一个主设备;

  5. 没有硬件从机应答信号(主机可能在不知情的情况下无处发送);

  6. 没有定义硬件级别的错误检查协议;

  7. 与RS-232和CAN总线相比,只能支持非常短的距离;

与IIC异同点

IICSPI
半双工全双工
有应答机制无应答机制
通过向总线广播从机地址来寻址通过向对应从机发送使能信号来寻址
时钟极性和时钟相位固定时钟极性和时钟相位可调

配置方式

spi_init_struct.trans_mode           = 	SPI_TRANSMODE_FULLDUPLEX;	//配置SPI的类型
spi_init_struct.device_mode          =  SPI_MASTER;					//配置为主机或从机模式
spi_init_struct.frame_size           =  SPI_FRAMESIZE_8BIT;			//配置SPI帧的大小
spi_init_struct.clock_polarity_phase =  SPI_CK_PL_LOW_PH_1EDGE;		//配置时钟相位和极性,选择四种模式的一种
spi_init_struct.nss                  =  SPI_NSS_SOFT;				//选择SPI的nss控制由硬件或软件
spi_init_struct.prescale             =  SPI_PSC_32;					//选择SPI的时钟分频
spi_init_struct.endian               =  SPI_ENDIAN_MSB;				//选择发送方式(大端序或小端序)
spi_init(SPI5, &spi_init_struct);	 								//对SPI的参数进行初始化

使用方法

qspi_flash_buffer_write(tx_buffer,FLASH_WRITE_ADDRESS,256);		//往flash里面写数据
qspi_flash_buffer_read(rx_buffer,FLASH_READ_ADDRESS,256);		//从flash里面读数据
03-29
### Java SPI机制详解 Java SPI(Service Provider Interface)是一种服务发现机制,允许开发者通过接口的方式定义功能,并由第三方提供具体实现。这种设计模式使得框架可以动态加载不同的实现类。 #### 什么是SPISPI的核心思想是将API的使用者和服务的提供者分离[^1]。它通过`META-INF/services`目录下的配置文件来指定某个接口的具体实现类名称。当程序运行时,JVM会自动扫描这些配置文件并加载对应的实现类。 #### 配置方式 假设有一个接口`java.sql.Driver`,其具体的数据库驱动实现是由各个厂商提供的。为了使JDBC能够找到合适的驱动程序,在相应的jar包中的`META-INF/services/java.sql.Driver`文件里写入了该驱动的全限定名。例如MySQL可能如下所示: ``` com.mysql.cj.jdbc.Driver ``` #### 使用案例分析 下面是一个简单的例子展示如何利用SPI机制完成日志记录的功能: ```java public interface LoggerService { void info(String message); void debug(String message); static LoggerService getService() { Iterator<LoggerService> iterator; try { iterator = ServiceLoader.load(LoggerService.class).iterator(); return iterator.next(); } catch (Exception e) { throw new RuntimeException(e); } } } ``` 接着创建两个独立的日志库分别实现了上述接口——Logback和SLF4J。它们各自都有自己的`META-INF/services/com.example.LoggerService`文件指向各自的实现类。 测试代码片段展示了调用过程: ```java public class TestJavaSPI { public static void main(String[] args) { LoggerService loggerService = LoggerService.getService(); loggerService.info("你好"); loggerService.debug("测试Java SPI 机制"); } } ``` 如果当前classpath下存在多个满足条件的服务,则按照优先级顺序依次尝试获取第一个可用实例[^2]。 另外还有一种更直观的例子就是字符串打印操作。我们先声明一个通用接口: ```java public interface SayHelloI { void sayHello(); } ``` 然后给出它的具体实现版本之一: ```java public class SayHelloImpl implements SayHelloI { @Override public void sayHello() { System.out.println("Hello"); } } ``` 同样地,在资源路径下建立关联关系即可让系统知道哪里能找到这个方法的实际执行体[^3]。 #### 总结 综上所述,SPI为应用程序提供了极大的灵活性,尤其适用于插件化开发场景之中.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值