电子产业一站式赋能平台

PCB联盟网

搜索
查看: 38|回复: 0
收起左侧

探秘 SPI 总线

[复制链接]

1001

主题

1001

帖子

8807

积分

高级会员

Rank: 5Rank: 5

积分
8807
发表于 2025-3-27 07:31:00 | 显示全部楼层 |阅读模式
详解串行外设接口及其与存储器、显示屏、Wi-Fi模块和SD卡的通信应用。
8 v$ i" `- D2 l% K
* k! T2 Z) ]: G$ R7 w

3kcr2j3rf0i640200049.png

3kcr2j3rf0i640200049.png

+ [! E3 c; B. n( g' C+ v, w" J' D! K% R# G6 v7 U5 R8 N5 u3 D+ m% F
在先前文章中,我探讨了现代 OLED 显示屏与裸机微控制器对接的惊人便捷性。我的观点很简单:多数嵌入式应用中,采用完整 Linux SoC 平台(如树莓派)不仅冗余,反而会引发更多待解难题。可能会有人反驳:OLED 模块或许是个特例。比如为 MCU 添加无线连接或外部闪存模块,工程复杂度必定陡增。* C) l7 [0 O0 r8 t) l/ z. f5 k
虽无普适答案,但我认为 OLED 相关的练习比大多数练习都要更难。在无需千兆级传输速率的场景中,嵌入式外设多采用串行外设接口(SPI):这种极其简单的全双工总线轻松实现超 50 Mbps 传输速率,且通常规避了 OLED 内存排序逻辑等异常设计。
) C; j* h2 k8 L) q  HSPI 的基本原理和操作方式很容易理解:由 MCU 主导通信流程。当需传输数据时,MCU 将对应外设的「片选」(CS-)引脚拉低,并向总线 SCK(串行时钟)线输出时钟信号。MCU 通过 MOSI(主出从入)逐位发送数据(通常在时钟上升沿触发),外设则通过 MISO(主入从出)并行回应。( x  d8 T4 v+ i9 T7 s4 _" X% v- S# f

4upcgo0uwxv640200149.jpg

4upcgo0uwxv640200149.jpg
" @! Q4 @. E( \+ k" |
常用(“模式 0”)的 SPI 协议要点1 F, @" ]) N+ v7 C
时钟信号在传输单个字节或其整数倍后自动停止。当 MCU 需单向接收数据时,可通过 MOSI 发送虚拟字节以激活总线时钟,同时读取 MISO 数据;同理,外设亦可借此机制保持通信同步。
! A% M1 \; D" n尽管从某种角度来说,为 SPI 总线提供硬件驱动可能并不是绝对必要的,但很多微控制器还是会提供一个针对 SPI 总线的硬件驱动。以 ATmega328P 为例,其 SPI 数据寄存器(SPDR)具备自动收发功能:当向该寄存器写入字节时,系统自动执行 SPI 总线传输,发送数据的同时,该寄存器还会被来自 MISO(Master In Slave Out)的数据替换。传输完成时,微控制器就会在 SPI 状态寄存器(SPSR)中设置“SPI 完成”(SPIF)标志位。假设我需要将 ATmega328P 与一款 128kB SRAM模块(型号23LC1024)对接。该模块仅有 8 个引脚:2 个电源引脚(支持 2.5-5.5V 输入),4 个基础 SPI 接口引脚,以及 2 个无需连接的冗余引脚。具体连接时,需将模块的"串行输入"(SI)引脚接至 MCU 的 MOSI 线路,"串行输出"(SO)引脚接至 MISO 线路,SCK(时钟)线需互联。最后的"片选"(CS-)引脚可接至 MCU任意输出线,本例将采用端口B的第 0 位。' @, f4 O1 G7 x" g" v
完成硬件连接后,需返回微控制器进行配置:通过 DDRB 寄存器的位映射设置 MOSI 和 SCK 引脚为输出模式,MISO 为输入模式(如先前所述)。接着在 SPI 配置寄存器(SPCR)中激活两个标志位:"SPI 使能"(SPE)与"主控模式"(MSTR):
+ {, s8 p" d8 P4 r
  • DDRB = 0b11101111;SPCR = (1 1 ;除基本配置外,SPCR 寄存器还支持总线速率分频设置(如SPI2X、SPR1/SPR0位),但实验阶段默认速率(通常为系统时钟的1/4)已能满足需求。完成寄存器初始化后,可通过以下函数实现与存储控制器的单字节双向通信:
    $ N. A3 ^5 ?; Y, E% ?" @) z
  • uint8_t spi_rxtx_byte(uint8_t val) {  SPDR = val;  while (!(SPSR & (1   return SPDR;}应用层协议也很简单,写入流程如下:
  • 发送写指令码 0x02
  • 发送 3 个字节的写入地址
  • 连续发送待写入数据流
  • 拉高 CS- 引脚结束操作[/ol]6 C8 Z% z% \! _5 G! Z' b. h! }

    xoppyqeiftg640200250.png

    xoppyqeiftg640200250.png
    9 ~" h2 `+ k5 Y+ S1 g' f
    虽然图表看似复杂,但实现这一功能的代码却简单而贴心:
  • void write_ext_ram_bytes(uint32_t addr, const uint8_t* ptr, uint16_t len) {  PORTB &= ~1; /* CS- down */  spi_rxtx_byte(0x02);  spi_rxtx_byte(addr >> 16);  spi_rxtx_byte(addr >> 8);  spi_rxtx_byte(ext_addr);  while (len--) spi_rxtx_byte(*(ptr++));  PORTB |= 1; /* CS- up */}读取存储器的工作原理大致相同,MCU 会发送一条 “读取 ”命令 (0x03),然后不断发送虚字节,同时保存从存储器芯片收到的响应:
  • void read_ext_ram_bytes(uint32_t addr, uint8_t* ptr, uint16_t len) {  PORTB &= ~1; /* -CS down */  spi_rxtx_byte(0x03);  spi_rxtx_byte(addr >> 16);  spi_rxtx_byte(addr >> 8);  spi_rxtx_byte(addr);  while (len--) *(ptr++) = spi_rxtx_byte(0);  PORTB |= 1; /* -CS up */}无论是与SRAM芯片通信、对接非易失性闪存控制器、驱动SD存储卡,还是操作乐鑫(Espressif)等厂商推出的低成本WiFi+TCP/IP模组,SPI总线协议栈的核心交互逻辑均高度统一。
    1 w1 v/ T1 K# q) f+ D! c值得关注的是,当前主流WiFi模组的应用层协议竟沿用了1980年代Hayes调制解调器的指令体系(经适度现代化改造)。例如,开发者仍可通过经典"AT"指令集发起HTTP请求——这种将复古命令行与现代物联网技术深度融合的设计,堪称嵌入式领域的"复古科技彩蛋"。
    ! l( v' f5 l- }; t  V: ^; `8 N' m* L8 ?. h
    原文转载自:https://lcamtuf.substack.com/p/mcu-land-part-2-mysteries-of-the,经过翻译及校验7 M6 M3 R1 B. M: t9 A/ l7 S  \
    声明:" i# S/ |" o8 X4 Q9 b, l6 Q  r" C
    本文转载自KiCad公众号,如涉及作品内容、版权和其它问题,请联系工作人员微(13237418207),我们将在第一时间和您对接删除处理!投稿/招聘/广告/课程合作/资源置换请加微信:13237418207, u8 `+ g8 a4 V4 ~! z  M
    ; _; p7 r, t1 A( s

    l2zpji3nqm1640200350.jpg

    l2zpji3nqm1640200350.jpg

    , u, t# C$ X4 A直观感受电路信号波形:钳位削峰电路
    2 f& j: H: ?9 Z: G4 y
    0 m3 J! g1 \7 {0 k

    1hemlkpivfb640200450.jpg

    1hemlkpivfb640200450.jpg

    / J2 i7 ^3 Z0 q5 D0 ]8 T- y2 y【资料推荐】emc大揭秘!85页pcb设计必备指南) f/ G/ C9 E$ B" m8 ^3 a$ r
    ' H. \6 O; |. C" {7 T

    q5lqwcbrqob640200550.jpg

    q5lqwcbrqob640200550.jpg

    $ N2 ?- i- F2 [' a/ `4 N认识SSD与HDD
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表