“詳解串行外設接口及其與存儲器、顯示屏、Wi-Fi模塊和SD卡的通信應用。”
在先前文章中,我探討了現代 OLED 顯示屏與裸機微控制器對接的驚人便捷性。我的觀點很簡單:多數嵌入式應用中,采用完整 Linux SoC 平臺(如樹莓派)不僅冗余,反而會引發更多待解難題。
可能會有人反駁:OLED 模塊或許是個特例。比如為 MCU 添加無線連接或外部閃存模塊,工程復雜度必定陡增。
雖無普適答案,但我認為 OLED 相關的練習比大多數練習都要更難。在無需千兆級傳輸速率的場景中,嵌入式外設多采用串行外設接口(SPI):這種極其簡單的全雙工總線輕松實現超 50 Mbps 傳輸速率,且通常規避了 OLED 內存排序邏輯等異常設計。
SPI 的基本原理和操作方式很容易理解:由 MCU 主導通信流程。當需傳輸數據時,MCU 將對應外設的「片選」(CS-)引腳拉低,并向總線 SCK(串行時鐘)線輸出時鐘信號。MCU 通過 MOSI(主出從入)逐位發送數據(通常在時鐘上升沿觸發),外設則通過 MISO(主入從出)并行回應。
常用(“模式 0”)的 SPI 協議要點
時鐘信號在傳輸單個字節或其整數倍后自動停止。當 MCU 需單向接收數據時,可通過 MOSI 發送虛擬字節以激活總線時鐘,同時讀取 MISO 數據;同理,外設亦可借此機制保持通信同步。
盡管從某種角度來說,為 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 位。
完成硬件連接后,需返回微控制器進行配置:通過 DDRB 寄存器的位映射設置 MOSI 和 SCK 引腳為輸出模式,MISO 為輸入模式(如先前所述)。接著在 SPI 配置寄存器(SPCR)中激活兩個標志位:"SPI 使能"(SPE)與"主控模式"(MSTR):
DDRB=0b11101111;SPCR= (1<< SPE) | (1?<< MSTR);除基本配置外,SPCR 寄存器還支持總線速率分頻設置(如SPI2X、SPR1/SPR0位),但實驗階段默認速率(通常為系統時鐘的1/4)已能滿足需求。完成寄存器初始化后,可通過以下函數實現與存儲控制器的單字節雙向通信:
uint8_tspi_rxtx_byte(uint8_tval){ SPDR = val;while(!(SPSR & (1<< SPIF)));??return?SPDR;}
應用層協議也很簡單,寫入流程如下:
發送寫指令碼 0x02
發送 3 個字節的寫入地址
連續發送待寫入數據流
拉高 CS- 引腳結束操作
雖然圖表看似復雜,但實現這一功能的代碼卻簡單而貼心:
voidwrite_ext_ram_bytes(uint32_taddr,constuint8_t* ptr,uint16_tlen){ 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),然后不斷發送虛字節,同時保存從存儲器芯片收到的響應:
voidread_ext_ram_bytes(uint32_taddr,uint8_t* ptr,uint16_tlen){ 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總線協議棧的核心交互邏輯均高度統一。
值得關注的是,當前主流WiFi模組的應用層協議竟沿用了1980年代Hayes調制解調器的指令體系(經適度現代化改造)。例如,開發者仍可通過經典"AT"指令集發起HTTP請求——這種將復古命令行與現代物聯網技術深度融合的設計,堪稱嵌入式領域的"復古科技彩蛋"。
原文轉載自:https://lcamtuf.substack.com/p/mcu-land-part-2-mysteries-of-the,經過翻譯及校驗
注意:如果想第一時間收到 KiCad 內容推送,請點擊下方的名片,按關注,再設為星標。
常用合集匯總:
和 Dr Peter 一起學 KiCad
KiCad 8 探秘合集
KiCad 使用經驗分享
KiCad 設計項目(Made with KiCad)
常見問題與解決方法
KiCad 開發筆記
插件應用
發布記錄
審核編輯 黃宇
-
存儲器
+關注
關注
38文章
7573瀏覽量
165283 -
SPI
+關注
關注
17文章
1736瀏覽量
93292 -
總線
+關注
關注
10文章
2922瀏覽量
88845
發布評論請先 登錄
相關推薦
看完這篇,SPI其實也很簡單嘛(可下載)
對于一款新的BSP如何添加SPI驅動

I2C總線與SPI總線的比較
LMP91200評估板上的兩組spi可以掛在同一spi總線上嗎?
通信協議之SPI總線硬件篇

請問DAC80508M的SPI總線支持三線模式嗎?如果SPI總線上面只掛了一個DAC80508M,CS腳可以直接接地嗎?
瀚海微SD NAND之SD 協議(37)SPI總線保護和讀寫

SPI總線的定義和特點
ESP32S3為什么無法使用GPIO32/31/30初始化SPI2總線?
SPI總線學習:連接的方式和SPI傳輸模式

評論