SPI通信:从原理到工程实践

文章目录

  • 1、概述
  • 2、什么是SPI?
    • [2.1 SPI的特点是什么?](#2.1 SPI的特点是什么?)
  • 3、SPI的历史发展
    • [3.1 SPI诞生](#3.1 SPI诞生)
    • [3.2 为什么是SPI?](#3.2 为什么是SPI?)
    • [3.3 SPI的一路升级](#3.3 SPI的一路升级)
      • [3.3.1 标准 SPI (Standard SPI)](#3.3.1 标准 SPI (Standard SPI))
      • [3.3.2 Dual SPI & Quad SPI (QSPI)](#3.3.2 Dual SPI & Quad SPI (QSPI))
      • [3.3.3 Octal SPI (OSPI) / xSPI](#3.3.3 Octal SPI (OSPI) / xSPI)
      • [3.3.4 eSPI (Enhanced SPI)](#3.3.4 eSPI (Enhanced SPI))
  • 4、协议架构及通信原理
    • [4.1 SPI功能层级划分(非官方,但实用便于理解)](#4.1 SPI功能层级划分(非官方,但实用便于理解))
      • [4.1.1 物理层 :四线制结构](#4.1.1 物理层 :四线制结构)
      • [4.1.2 传输层 / 链路控制层](#4.1.2 传输层 / 链路控制层)
      • [4.1.3 数据链路层 / 协议层](#4.1.3 数据链路层 / 协议层)
      • [4.1.4. 应用层](#4.1.4. 应用层)
      • [4.1.5 SPI的通俗结构解密:](#4.1.5 SPI的通俗结构解密:)
    • [4.2 SPI通信规则](#4.2 SPI通信规则)
      • [4.2.1 数据传输机制--交换的"魔术":](#4.2.1 数据传输机制--交换的“魔术”:)
      • [4.2.2 关键的"约定"--时钟极性与相位 (CPOL & CPHA)](#4.2.2 关键的“约定”--时钟极性与相位 (CPOL & CPHA))
      • [4.2.3 数据传输顺序:](#4.2.3 数据传输顺序:)
    • [4.3 具体时序图解析](#4.3 具体时序图解析)
  • 5、驱动代码示例
    • [5.1 抽象层定义 (spi_interface.h)](#5.1 抽象层定义 (spi_interface.h))
    • [5.2 设备驱动实现示例 (sensor_driver.c)](#5.2 设备驱动实现示例 (sensor_driver.c))
    • [5.3 适配层 (port_stm32.c)](#5.3 适配层 (port_stm32.c))
  • 6、总结展望
  • 7、激励自己学习的话
  • 8、相关参考

1、概述

在嵌入式系统设计的世界里,各种芯片之间的高效沟通是系统流畅运行的基石。作为一名嵌入式工程师,深知选择合适的通信协议至关重要。而SPISerial Peripheral Interface,串行外围接口)正是这样一位"高速传声筒",它以其卓越的性能和简洁的特性,成为短距离、高效率芯片间通信的优选方案。

2、什么是SPI?

想象一下,你(主设备)是小组长,要和几个同学(从设备)交换秘密纸条。SPI就是这个小组的交流规则:

  • 同步 (Synchronous): 所有的交流都步调一致。你喊"1、2、3!",大家就同时传,节奏统一。这意味着主设备会生成一个共享的时钟信号(SCLK),所有连接的设备都遵循这个时钟节拍,确保数据在精确的时间点传输和接收,避免了异步通信中常见的波特率匹配问题。
  • 串行 (Serial): 信息一位一位地传送。一次只传一个字,排队发送。与并行通信相比,这显著减少了所需的物理连接线数量。
  • 全双工 (Full-Duplex): 可以同时发送和接收。你给我纸条的同时,我也可以给你纸条,信息交换不耽误。这是SPI的一个显著优势,它极大地提高了通信的吞吐量和效率。
  • 主从架构 (Master-Slave Architecture): 你是唯一的发令者,指定和谁交换,什么时候开始/结束。主设备(通常是微控制器)发起并控制整个通信过程,它生成时钟信号并选择特定的从设备进行通信。从设备(如传感器、显示器、存储芯片)则响应主设备的指令。

    官方定义:SPI是由摩托罗拉提出的一种同步、全双工、串行、主从式的短距离高速通信总线标准,采用主设备控制时钟和四线制(SCLK, MOSI, MISO, SS)实现设备间数据交换。

2.1 SPI的特点是什么?

SPI之所以如此受欢迎,正是因为它具备多项"超能力":

  • 速度快得像闪电: SPI以其高速数据传输能力而闻名,通常可以达到每秒数兆位(Mbps),在普通 MCU 中,标准 SPI 时钟通常为 10--50 MHz;在 QSPI/OSPI 等扩展模式下,结合多数据线与 DDR,可实现等效百 MHz 级吞吐。实现芯片间秒级反应,远超I²C或UART等协议。
  • 线路简单: 典型的SPI通信只需要四根线,不搞复杂排场。这简化了硬件设计,降低了布线复杂度和成本。
  • 效率超高: 全双工通信允许主从设备在同一时钟周期内同时发送和接收数据,效率倍增,非常适合需要快速数据采集或实时控制的应用。
  • 连续数据传输: SPI支持连续的数据流传输,不需要像基于数据包的协议那样引入额外的开销或复杂的握手机制,简化了数据处理。

由于其高吞吐量和硬件实现简单的特性,SPI 已成为嵌入式系统中的事实标准(De facto Standard),广泛应用于微控制器(MCU)与外设(如传感器、Flash 存储、ADC/DAC、显示屏)之间的高速短距离通信。与 I2C 相比,SPI 没有复杂的寻址机制和确认位(ACK),更适合对实时性要求高的数据流传输。

3、SPI的历史发展

每一个伟大的技术背后,都有其特定的历史背景和需求驱动。SPI的诞生,正是为了解决上世纪80年代嵌入式系统发展中遇到的芯片间通信瓶颈。

3.1 SPI诞生

大约在20世纪80年代中期,一个叫摩托罗拉(Motorola)的公司,为了让自家68000系列微控制器(就像是芯片的大脑)能更高效地和各种"小配件"(如EEPROM、传感器、数据转换器)交流,发明了SPI。摩托罗拉M68HC11微控制器(1984年推出)是早期集成SPI硬件支持的芯片典范。

3.2 为什么是SPI?

那时候,芯片间的沟通方式要么慢得像蜗牛,比如早期的并行总线需要大量引脚,或者串行协议如UART速度受限;要么需要一大堆线路(像一堆电话线),增加了硬件复杂度和成本。SPI的出现,就像给芯片们找到了一条"高速专线",用四根线就解决了高速、同步对话的难题。它的全双工特性在当时也是一个重要的创新,允许数据双向并行流动,显著提升了通信效率。

3.3 SPI的一路升级

SPI凭借其简单高效的特点,迅速在电子界"C位出道"。它无需复杂的地址寻址,也没有协议开销,使得其在实现上更加轻量。随着对带宽需求的爆炸式增长(特别是 Flash 存储器和 FPGA 配置),从最初的"单车道"四线标准,发展出"双车道"DSPI、"四车道"QSPI,甚至"八车道"OSPI等超级加速版,简直是通信协议界的"进化狂魔",目的只有一个------让数据传输更快!

3.3.1 标准 SPI (Standard SPI)

带宽:x1 (单线数据)

应用:传感器、低速 ADC、传统 EEPROM。

3.3.2 Dual SPI & Quad SPI (QSPI)

为了在不增加时钟频率的情况下提高吞吐量,业界引入了并行数据线概念。

Quad SPI (QSPI):使用 4 条数据线 (IO0 - IO3) 进行半双工传输。

改进点:在传输地址和数据阶段,4 条线同时工作,理论速度是标准 SPI 的 4 倍。

现状:目前是外置 NOR Flash 的主流接口,STM32、ESP32 等芯片均标配 QSPI 接口。

3.3.3 Octal SPI (OSPI) / xSPI

带宽:x8 (8 条数据线)

DDR (Double Data Rate):在时钟的上升沿和下降沿都传输数据。

性能:8 线 + DDR 技术使得 OSPI 的吞吐量可达标准 SPI 的 16 倍,常用于大容量 PSRAM 和高性能 Flash。

3.3.4 eSPI (Enhanced SPI)

由 Intel 提出,旨在取代老旧的 LPC (Low Pin Count) 总线。

核心变革:eSPI 不仅传输数据,还通过"虚拟线 (Virtual Wires)"通道传输边带信号(如中断、复位、GPIO状态),大幅减少了主板上的布线数量。

架构:支持 1.8V 电平,频率高达 66MHz,包含四个通道:外设通道、虚拟线通道、带外通道 (OOB)、Flash 通道。

4、协议架构及通信原理

SPI的核心特点。与TCP/IP、USB或CAN等复杂协议不同,SPI本身没有一个标准化的、正式的分层架构(如OSI七层模型)。SPI的设计哲学是极简主义和高度灵活性 ,将大部分复杂性留给了硬件实现和软件驱动开发者。我们可以将其理解为一种主要在物理层和链路层交界处运行的"硬协议"。

尽管如此,为了更好地理解和设计SPI系统,我们可以从功能上将其划分为以下几个层级,但这是一种分析性/概念性的划分,而非协议标准的一部分

不同协议设计的简单对比

协议/总线 分层架构 特点
SPI 无标准分层 ,可视为 "物理层 + 极简链路控制" 灵活、高效、简单。协议开销几乎为零,但所有高层功能(寻址、命令、数据含义)需外接定义。
I²C 有较清晰的链路层(7/10位地址、开始/停止条件、ACK位) 内置寻址和确认机制,总线管理更复杂。
UART 有简单的链路层(定义起始位、停止位、奇偶校验位) 异步点对点,帧结构简单。
USB/CAN 有完整、严格的分层协议栈(物理层、数据链路层、协议层等) 复杂、功能强大(支持热插拔、错误恢复、多主机仲裁等),协议开销大。

4.1 SPI功能层级划分(非官方,但实用便于理解)

便于理解类比记忆:

4.1.1 物理层 :四线制结构

这是SPI最明确的一层,定义了电气和物理连接。

  • 信号线:明确规定了SCLK、MOSI、MISO、SS这四条基础信号线的电气特性(电压、驱动能力)和物理连接方式。
  • 时序参数:严格定义了时钟频率、建立时间、保持时间、上升/下降时间等。这些参数决定了SPI的最高工作速度。
  • 物理接口:包括引脚定义、PCB布线规则(如长度匹配、阻抗控制)等。

SPI 通常被称为"四线串口",其核心信号线如下:

信号名称 别名 (常见) 方向 (主 -> 从) 描述
SCLK SCK, CLK 输出 时钟信号:由主机产生,决定通信速率。
MOSI SDI, DO 输出 主机输出/从机输入:数据从主机发送到从机。
MISO SDO, DI 输入 主机输入/从机输出:数据从从机返回主机。
CS/SS nCS, CS# 输出 片选信号:通常为低电平有效。拉低时激活特定的从机。

4.1.2 传输层 / 链路控制层

这一层是SPI的核心,但它非常简单,几乎完全由硬件状态机实现。

  • 帧定义:一个最基本的"帧"通常就是一个8位或16位的移位寄存器传输过程。从SS下降沿开始,到SS上升沿结束。
  • 时钟模式:定义了CPOL和CPHA,即数据与时钟的相位关系。
  • 寻址机制:没有复杂的地址帧。寻址通过唯一的片选信号(SS) 在物理层实现。拉低某个SS线,即选中对应的从设备。
  • 流控:无硬件流控。主设备完全控制时钟节奏,从设备必须跟得上。
  • 错误检测:无CRC校验、无应答(ACK/NACK)机制。数据传输的可靠性依赖稳定的电源、时钟和短距离布线。

4.1.3 数据链路层 / 协议层

这是SPI缺失的一环,也是其灵活性的来源。 SPI标准在此处戛然而止,由应用开发者或从设备制造商来定义

  • 命令-响应结构:绝大多数SPI设备(如传感器、Flash芯片)都会定义一套自己的寄存器映射和命令集。例如,主设备先发送一个8位的"读寄存器"命令(0x03),再发送一个地址,然后开始接收数据。这套规则是设备特定的,不属于SPI总线本身。
  • 数据含义:总线上传输的原始比特流的具体含义(是配置、是温度数据还是像素值)完全由应用层解释。
  • 多字节传输:对于超过寄存器长度的传输(如读写Flash的一个扇区),需要定义如何分帧、如何维持SS有效等规则,这些通常也在设备数据手册中说明。

4.1.4. 应用层

这是最终使用数据的软件或固件。它负责:

  • 调用底层驱动,发起符合设备特定命令集的SPI传输。
  • 解释接收到的原始字节数据,并将其转换为有意义的物理量(如摄氏度、压力值)。
  • 处理高级逻辑,如文件系统(对于SPI Flash)、图形显示(对于SPI屏幕)等。

4.1.5 SPI的通俗结构解密:

从工程架构的角度看,SPI的简洁而强大的结构设计是其成功的关键。它将复杂的通信拆解成几个清晰的功能块,通过四根核心信号线,构建了一个高效的"班长与同学"通信模式。

"班长与同学"模式:

SPI通信的核心在于其严格的"主从架构"。

  • 主设备 (Master): 永远的"班长",掌控一切。它通常是微控制器(Microcontroller Unit, MCU),负责启动和终止通信,产生唯一的时钟信号(SCLK),并决定和哪个从设备对话。一个SPI总线上只能有一个主设备。
  • 从设备 (Slave): 听话的"同学",只有被班长选中后才能响应。从设备可以是各种外设,如传感器、存储器、显示屏等。当其片选线(SS/CS)被主设备激活时,从设备才开始参与数据交换。

四根"线"的秘密 (核心信号线,就像四条不同的高速公路):

为了实现全双工的同步串行通信,SPI协议通常使用以下四根逻辑信号线:

  1. SCLK (Serial Clock - 序列时钟线): 这是"指挥棒"!主设备挥舞它,通过连续的高低电平交替,为所有设备提供一个统一的节奏,确保数据传输的同步性。时钟频率由主设备控制,可以达到很高的速度(例如,高达100 MHz或更高)。
  2. MOSI (Master Out Slave In - 主发从收线): 这是"班长的喇叭"!主设备通过这条线向从设备喊话(发送数据)。数据位从主设备串行输出,并被选定的从设备串行输入。
  3. MISO (Master In Slave Out - 主收从发线): 这是"同学的回音"!从设备通过这条线向主设备回应(发送数据)。数据位从选定的从设备串行输出,并被主设备串行输入。为了避免多个从设备同时向主设备发送数据造成冲突,未被选中的从设备会将其MISO引脚置于高阻态。
  4. SS/CS (Slave Select / Chip Select - 从机选择线/片选线): 这是"点名器"!主设备用这条线"点名"要和哪个从设备交流。SS/CS通常是低电平有效的信号,意味着当某条SS/CS线被拉低时,对应的从设备就被激活。当有多达四个从设备时,主设备可以使用独立的CS线来选择它们。没点到的(电平拉高)就安静待机。

多个从设备怎么排队?

SPI支持多从设备连接,主要有两种配置方式:

  • 独立点名(Independent Slave Selects): 这是最常见的配置方式。就像每个同学都有个专属名字牌,班长想和谁说话就点谁的名字。主设备为每个从设备提供一根独立的SS/CS线。当主设备需要与某个从设备通信时,它会将该从设备的SS/CS线拉低,同时保持其他从设备的SS/CS线为高电平。所有从设备共享SCLK、MOSI和MISO线。这种方式灵活,但随着从设备数量增加,主设备所需的引脚数量也会增加。

  • "击鼓传花"(菊花链 Daisy-Chain Configuration): 所有的从设备手拉手排成一队,班长把数据给第一个,第一个传给第二个,直到最后一个再传回班长。在这种模式下,多个从设备串联连接。主设备的MOSI连接到第一个从设备的输入,第一个从设备的输出连接到第二个从设备的输入,依此类推,直到最后一个从设备的输出连接回主设备的MISO。所有从设备共享一根SCLK线和一根SS/CS线(这根SS/CS线通常用于激活整个链)。这种方式节省了主设备的引脚数量,但数据传输的时延会随着链中从设备数量的增加而增加,因为数据需要依次通过每个从设备。

4.2 SPI通信规则

4.2.1 数据传输机制--交换的"魔术":

SPI 的通信本质是移位寄存器(Shift Register)的交换 。这两个移位寄存器以环形方式连接在一起,一个寄存器的输出到另一个寄存器的输入,反之亦然。主设备控制共同的时钟信号,确保每个寄存器在另一个寄存器移出一个比特时,正好移入一个比特。

简单理解如下:

  • "你传纸条,我抄答案": SPI最迷人的地方在于其全双工操作。在每个时钟节拍(SCLK的一次跳动)中,主设备会通过MOSI线发一个数据比特给从设备,同时,选定的从设备也会通过MISO线发一个数据比特给主设备。这种同步、双向的数据流使得通信效率极高,双方数据交换互不影响!
  • 内部"传送带": 芯片内部都有"移位寄存器"(Shift Registers),这就像一条传送带。数据比特一个接一个地被移入(从MOSI线)或移出(到MISO线)。主从设备的移位寄存器长度通常相同(例如8位或16位),在一个数据帧内同步完成移位和采样。

4.2.2 关键的"约定"--时钟极性与相位 (CPOL & CPHA)

为了确保主从设备能够正确地"理解"对方的数据,它们在通信前必须约定好"暗号"------即时钟极性(CPOL)和时钟相位(CPHA)。这两个参数共同定义了四种SPI通信模式(Mode 0、1、2、3)。主从设备必须采用相同的模式才能成功通信。

  • CPOL (Clock Polarity - 时钟极性): 规定了"休息时钟是站着(高电平)还是坐着(低电平)"。
    • CPOL = 0: SCLK在空闲时为低电平(Idle low)。
    • CPOL = 1: SCLK在空闲时为高电平(Idle high)。
  • CPHA (Clock Phase - 时钟相位): 规定了"数据是在时钟跳动的'开始'瞬间读,还是在'结束'瞬间读"。
    • CPHA = 0: 数据在时钟的第一个有效边沿(leading edge)被采样,并在第二个有效边沿(trailing edge)改变。
    • CPHA = 1: 数据在时钟的第二个有效边沿(trailing edge)被采样,并在第一个有效边沿(leading edge)改变。

CPOL 和 CPHA 的组合产生了四种不同的 SPI 模式 :

模式 CPOL (时钟极性) CPHA (时钟相位) 空闲时时钟电平 数据采样边沿 数据移位边沿
Mode 0 0 0 低电平 第一个时钟边沿(上升沿) 第二个时钟边沿(下降沿)
Mode 1 0 1 低电平 第二个时钟边沿(下降沿) 第一个时钟边沿(上升沿)
Mode 2 1 0 高电平 第一个时钟边沿(下降沿) 第二个时钟边沿(上升沿)
Mode 3 1 1 高电平 第二个时钟边沿(上升沿) 第一个时钟边沿(下降沿)

4.2.3 数据传输顺序:

虽然不是所有设备都严格遵循,但大部分SPI设备都遵循"高位在前"(MSB first - Most Significant Bit first)的规则,就像我们写数字从左到右一样,即先发送字节的最高位。然而,也有少数设备支持或默认"低位在前"(LSB first)的传输顺序。因此,在集成新设备时,务必查阅其数据手册,确认数据传输顺序,以免出现"鸡同鸭讲"的局面。

4.3 具体时序图解析

一句话总结者张图:"CS下降沿开始对话,SCK节拍控制节奏,MOSI和MISO同时双向传输,CS上升沿结束对话。"

通信阶段分解

  • 阶段①:通信开始

    CS(片选)线从高电平变为低电平(下降沿)

    这相当于"敲门"告诉从设备:"注意,我要和你说话了!"

    注意:CS低电平期间,整个SPI通信过程持续进行

  • 阶段②:数据传输

    SCK(时钟)开始有规律的跳动(方波)

    每个时钟周期传输1位数据(1bit)

    同步传输:

    MOSI:主设备在SCK的某个边沿发送数据

    MISO:从设备在SCK的某个边沿返回数据

    同时进行!这就是"全双工"的特点

  • 阶段③:通信结束

    CS线从低电平恢复为高电平(上升沿)

    表示:"我说完了,对话结束"

    从设备知道传输完成,可以处理接收到的数据

5、驱动代码示例

为了实现硬件无关性(Hardware Abstraction),企业级代码通常使用结构体 + 函数指针的方式来封装 SPI 驱动。以下是一个标准的 C 语言驱动模板:

5.1 抽象层定义 (spi_interface.h)

这是驱动的核心接口,不依赖具体硬件(STM32, NXP, Linux 均可通用)。

c 复制代码
#include <stdint.h>
#include <stdbool.h>

// 定义标准 SPI 错误码
typedef enum {
    SPI_OK = 0,
    SPI_ERROR_TIMEOUT,
    SPI_ERROR_BUSY
} spi_status_t;

// 定义 SPI 配置结构体
typedef struct {
    uint32_t speed_hz;
    uint8_t cpol;       // 0 or 1
    uint8_t cpha;       // 0 or 1
    bool msb_first;
} spi_config_t;

// 定义 SPI 驱动接口 (V-Table 思想)
typedef struct {
    // 初始化 SPI 硬件
    spi_status_t (*init)(spi_config_t *config);
    
    // 控制片选引脚 (true=拉低选中, false=拉高释放)
    void (*cs_control)(bool select);
    
    // 核心传输函数:全双工交换数据
    // tx_data: 发送缓冲区 (可为 NULL, 发送 0xFF)
    // rx_data: 接收缓冲区 (可为 NULL, 丢弃数据)
    // len: 数据长度
    spi_status_t (*transfer)(const uint8_t *tx_data, uint8_t *rx_data, uint16_t len);
    
} spi_driver_t;

5.2 设备驱动实现示例 (sensor_driver.c)

上层业务逻辑只需调用 spi_driver_t 中的函数,无需关心底层寄存器。

c 复制代码
// 假设这是某个温度传感器的驱动
typedef struct {
    spi_driver_t *spi; // 持有底层 SPI 接口的指针
} temp_sensor_t;

// 读取传感器寄存器
uint8_t sensor_read_reg(temp_sensor_t *dev, uint8_t reg_addr) {
    uint8_t tx_buf[2];
    uint8_t rx_buf[2];
    
    // 准备数据:第一字节是地址,第二字节是空字节(用于产生时钟)
    tx_buf[0] = reg_addr | 0x80; // 假设最高位 1 代表读
    tx_buf[1] = 0x00;            // Dummy byte
    
    // 1. 选中芯片
    dev->spi->cs_control(true);
    
    // 2. 交换数据
    dev->spi->transfer(tx_buf, rx_buf, 2);
    
    // 3. 释放芯片
    dev->spi->cs_control(false);
    
    // 返回第二个字节(有效数据)
    return rx_buf[1]; 
}

5.3 适配层 (port_stm32.c)

最后,将具体的硬件操作"绑定"到接口上。

c 复制代码
// 具体的硬件发送函数 (STM32 HAL 风格)
static spi_status_t stm32_spi_transfer(const uint8_t *tx, uint8_t *rx, uint16_t len) {
    // 调用厂商 HAL 库
    if (HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)tx, rx, len, 1000) != HAL_OK) {
        return SPI_ERROR_TIMEOUT;
    }
    return SPI_OK;
}

static void stm32_cs_control(bool select) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, select ? GPIO_PIN_RESET : GPIO_PIN_SET);
}

// 构造驱动实例
spi_driver_t my_spi_driver = {
    .init = stm32_spi_init,
    .cs_control = stm32_cs_control,
    .transfer = stm32_spi_transfer
};

6、总结展望

SPI 协议以其极简的架构统治了嵌入式外设通信四十年。虽然缺乏统一的标准(如无 ACK 机制、无统一寄存器定义)是其劣势,但在追求极致速度和低延迟的场景下,SPI 依然是首选。

SPI的低延迟和高效率特性使其在物联网(IoT)、人工智能(AI)、边缘计算(Edge Computing)以及机器人技术等新兴领域中扮演关键角色。它将继续成为传感器数据采集、无线模块通信、AI加速器与主控芯片交互,以及机器人实时控制的"基石"通信协议。例如,在边缘AI设备中,传感器收集的数据需要通过高速SPI快速传输到本地AI处理器进行实时推理。SPI的持续演进将确保它能够无缝融入这些创新场景,推动智能世界的构建。

7、激励自己学习的话

真正拉开工程师差距的,不是用过多少接口,而是是否理解每一次时钟跳变背后的原理。

8、相关参考

相关推荐
国科安芯1 小时前
核工业机器人电机驱动器CANFD隔离芯片国产替代方案
单片机·嵌入式硬件·性能优化·架构·机器人·安全性测试
Zeku2 小时前
20260102 - Linux驱动设计的思想
stm32·freertos·linux驱动开发·linux应用开发
星空真迷人2 小时前
低功耗赋能:智能设备为何持久 “存活”?
stm32·单片机·mcu·物联网·iot
松涛和鸣2 小时前
45、无依赖信息查询系统(C语言+SQLite3+HTML)
c语言·开发语言·数据库·单片机·sqlite·html
拓端研究室2 小时前
2025医疗人工智能报告:AI应用、IVD市场、健康科技|附240+份报告PDF、数据、可视化模板汇总下载
大数据·人工智能·物联网
清风6666662 小时前
基于单片机控制的多模式智能冰箱设计—冷藏、速冷、省电与自动化霜功能实现
单片机·自动化·毕业设计·nosql·课程设计·期末大作业
中科岩创2 小时前
云南某地光伏站边坡自动化监测服务项目
运维·人工智能·物联网·自动化
d111111111d3 小时前
STM32 USART接收中断:如何判断数据接收完成?
stm32·单片机·嵌入式硬件·学习·模块测试
Joshua-a3 小时前
慢时钟域到快时钟域问题(打拍法)(自用)
单片机·嵌入式硬件
benjiangliu3 小时前
STM32教程-03-STM32总线矩阵和系统框图
stm32·嵌入式硬件·矩阵