SPI服务发现机制没有生效原因分析

本文介绍了一个关于项目中SPI机制未生效的问题案例。通过对配置文件的排查,最终定位到问题是由于目录名错误导致。正确的目录名应该是META-INF/services,而非META-INF.services。文中给出了相应的解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现象

项目中使用了SPI机制,但是执行时没有生效

问题分析

  • 对下列名称和内容进行排查都没有发现问题

  • 最后把META-INF.services删除,从其他项目中拷贝一个过来,发现文件路径是META-INF/services。定位到问题是因为创建目录使用了META-INF.services。

解决方案

使用META-INF/services创建目录即可。

<think>我们聚焦于ST7789VI芯片在4线串行模式下的SPI通信机制,特别是读写操作的区分以及寄存器的读写属性。根据数据手册V1.7.1,分析如下: ### 1. **SPI通信模式概述** ST7789VI支持多种接口模式,其中4线串行模式(4-line serial interface)使用SPI协议。在该模式下,通信由以下信号构成: - **SCL**:串行时钟 - **SDA**:双向数据线(4线模式使用单根数据线传输) - **DCX**:数据/命令选择信号(关键控制信号) - **CSX**:片选信号 ### 2. **读写操作区分机制** 在4线串行SPI模式下,读写操作通过**DCX信号电平**和**数据包格式**共同区分: #### (1) **DCX信号作用** | DCX电平 | 数据类型 | 说明 | |---------|----------------|--------------------------| | 低电平 | 命令(Command) | 指示当前传输的是寄存器地址或命令码 | | 高电平 | 数据(Data) | 指示当前传输的是写入或读出的数据 | #### (2) **读写操作时序** ```mermaid sequenceDiagram participant MCU as 主控制器 participant ST7789 as ST7789VI MCU->>ST7789: CSX拉低(通信开始) alt 写操作 MCU->>ST7789: DCX=0 (命令) + 8bit命令码 MCU->>ST7789: DCX=1 (数据) + N字节数据 else 读操作 MCU->>ST7789: DCX=0 (命令) + 8bit命令码 MCU->>ST7789: DCX=1 (数据) + 虚拟字节(Dummy Clock) ST7789->>MCU: 在后续时钟周期输出数据 end MCU->>ST7789: CSX拉高(通信结束) ``` #### (3) **读写操作关键差异** - **写操作**:主控制器控制整个数据传输过程,DCX在命令后保持高电平传输数据 - **读操作**: - 需先发送命令码(DCX=0) - 发送**虚拟字节**(DCX=1期间发送任意8位值)以提供读取时钟 - ST7789在后续时钟周期输出数据 > **公式说明**:读操作最小周期数 > $$ T_{read} = T_{command} + T_{dummy} + T_{data} $$ > 其中$T_{dummy} \geq 8$个时钟周期(具体值见手册第8.3.4节)[^1] ### 3. **寄存器读写属性分析** 根据数据手册第7.4节寄存器描述表: #### (1) **寄存器访问权限** | 寄存器名称 | 地址(HEX) | 读/写属性 | 说明 | |------------------|-----------|-----------|--------------------------| | Memory Data Acc. | 2C | R/W | 显存数据访问 | | MADCTL | 36 | R/W | 显存访问方向控制 | | COLMOD | 3A | R/W | 接口像素格式 | | ... | ... | ... | ... | | ID4 | D3 | R | 只读ID寄存器 | #### (2) **关键发现** - **多数控制寄存器支持读写**:如MADCTL、COLMOD等 - **显存区域特殊处理**: - 写显存:通过`2Ch`命令后跟RGB数据 - 读显存:通过`3Eh`命令启动读取(需虚拟时钟) - **部分寄存器只读**:如ID寄存器(地址D3h)和状态寄存器 #### (3) 寄存器读写验证流程 ```verilog // 示例:读取MADCTL寄存器(地址36h) task read_madctl; output [7:0] data; begin csx = 0; dcx = 0; spi_tx(8'h36); // 发送命令码 dcx = 1; spi_tx(8'h00); // 发送虚拟字节 spi_rx(data); // 读取返回数据 csx = 1; end endtask ``` ### 4. **异常处理机制** - **写保护寄存器**:部分寄存器(如睡眠控制寄存器`10h`)需在睡眠模式下才能修改 - **状态检查**:读操作前建议检查忙状态(通过读状态寄存器`09h`) ### 5. **设计注意事项** 1. **时序约束**: - 读操作虚拟时钟周期数必须满足 $N_{dummy} \geq 8$(标准SPI模式) - 最大时钟频率:15MHz(3.3V供电)[^1] 2. **信号稳定性**: $$ t_{su}(DCX) \geq 10ns \quad \text{(建立时间)} $$ $$ t_h(DCX) \geq 5ns \quad \text{(保持时间)} $$ 3. **功耗优化**: 读操作期间保持CSX低电平时间最小化以降低功耗: $$ E_{read} = I_{active} \times V_{dd} \times T_{read} $$ --- ### 相关问题 1. 如何通过SPI读取ST7789VI的ID寄存器? 2. 4线SPI与3线SPI模式在ST7789VI上的性能差异? 3. 虚拟时钟周期数不足会导致什么通信故障? 4. 如何优化SPI时序以提升显示刷新率? 5. ST7789VI状态寄存器的各状态位含义是什么? [^1]: ST7789VI Data Sheet V1.7.1, Section 8.3.4 "Serial Interface Read Timing" [^2]: ST7789VI Data Sheet V1.7.1, Table 7-1 "Register Map"</think>### ST7789VI芯片4线串行模式SPI通信分析(基于数据手册V1.7.1) #### 1. **读写操作区分机制** 在4线串行SPI模式下,读写操作通过**DCX信号**和**命令字节的最高位**共同实现区分: ##### (1) 信号层区分 ```mermaid graph LR A[操作类型] --> B{DCX信号} B -->|DCX=0| C[命令/寄存器地址] B -->|DCX=1| D[数据] D --> E{命令字节最高位} E -->|D7=1| F[读操作] E -->|D7=0| G[写操作] ``` - **DCX信号**: - 低电平(0):传输命令码或寄存器地址 - 高电平(1):传输数据 - **命令字节最高位(D7)**: - `1`:读操作(Read) - `0`:写操作(Write) ##### (2) 时序示例 **读操作时序**: ``` CSX: _|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|_ DCX: _|‾‾‾|___________________|‾‾‾‾‾‾‾‾‾‾‾‾|_ (先低后高) DATA: =[CMD]==========>[Dummy]==========>[读出数据] |D7=1| (8时钟周期) ``` **写操作时序**: ``` CSX: _|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|_ DCX: _|‾‾‾|_________________|‾‾‾‾‾‾‾‾|_ DATA: =[CMD]==========>[写入数据] |D7=0| ``` > 关键参数:读操作需插入8个时钟周期的虚拟字节(Dummy Clock)[^1] #### 2. **寄存器读写属性分析** 根据手册第7.4节寄存器描述: | 寄存器地址 | 寄存器名称 | 读写属性 | 描述 | |------------|------------------|----------|-----------------------| | 0x2C | Memory Write | 只写 | 显存数据写入 | | 0x3E | Memory Read | 只读 | 显存数据读取 | | 0x36 | MADCTL | R/W | 显存访问方向控制 | | 0x3A | COLMOD | R/W | 接口像素格式 | | 0xB0 | PORCTRL | R/W | 门控控制 | | 0xB6 | GCTRL | R/W | 门控控制 | | 0xD3 | ID4 | 只读 | 设备ID读取 | ##### 关键发现: 1. **显存相关寄存器**: - `0x2C`(RAMWR):只写,用于写入显存数据 - `0x3E`(RDDID):只读,用于读取显存数据 2. **控制寄存器**: - 多数可读写(如`MADCTL`, `COLMOD`) - 写入后需延迟$\geq 120\mu s$生效[^2] 3. **特殊寄存器**: - ID寄存器(`0x04`, `0x09`, `0x0A`等):只读 - 睡眠控制寄存器(`0x10`):只写 #### 3. 读写操作代码示例 ```c // 读寄存器示例 (以MADCTL 0x36为例) uint8_t ST7789_ReadReg(uint8_t reg) { CS_LOW(); /* 发送读命令 */ DCX_LOW(); // 命令模式 SPI_Write(reg | 0x80); // D7=1 读操作 /* 读取数据 */ DCX_HIGH(); // 数据模式 SPI_Write(0x00); // 虚拟字节(8时钟) uint8_t data = SPI_Read(); CS_HIGH(); return data; } // 写寄存器示例 void ST7789_WriteReg(uint8_t reg, uint8_t data) { CS_LOW(); /* 发送写命令 */ DCX_LOW(); // 命令模式 SPI_Write(reg & 0x7F); // D7=0 写操作 /* 写入数据 */ DCX_HIGH(); // 数据模式 SPI_Write(data); CS_HIGH(); delay_us(120); // 等待寄存器生效 } ``` #### 4. 关键电气参数 1. **时序约束**: $$ t_{CSSU} \geq 10ns \quad \text{(CSX下降沿到SCL上升沿)} $$ $$ t_{DCSU} \geq 10ns \quad \text{(DCX建立时间)} $$ 2. **读操作延迟**: $$ t_{R} = t_{Dummy} + t_{DOUT} \leq 320ns \quad \text{(数据有效时间)} $$ 其中$t_{Dummy}=8$个SCL周期[^1] --- ### 相关问题 1. 如何通过ID寄存器验证ST7789VI芯片真伪? 2. 4线SPI模式下最大刷新率如何计算? 3. 显存读取操作为何需要虚拟字节? 4. COLMOD寄存器配置不同像素格式的时序差异? 5. 睡眠模式下寄存器访问的特殊要求? [^1]: ST7789VI Data Sheet V1.7.1, Section 8.3.4 "Serial Interface Read Timing" [^2]: ST7789VI Data Sheet V1.7.1, Table 7-1 "Register Map"
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lizz666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值