“詳解串行外設(shè)接口及其與存儲(chǔ)器、顯示屏、Wi-Fi模塊和SD卡的通信應(yīng)用。”
在先前文章中,我探討了現(xiàn)代 OLED 顯示屏與裸機(jī)微控制器對(duì)接的驚人便捷性。我的觀點(diǎn)很簡單:多數(shù)嵌入式應(yīng)用中,采用完整 Linux SoC 平臺(tái)(如樹莓派)不僅冗余,反而會(huì)引發(fā)更多待解難題。
可能會(huì)有人反駁:OLED 模塊或許是個(gè)特例。比如為 MCU 添加無線連接或外部閃存模塊,工程復(fù)雜度必定陡增。
雖無普適答案,但我認(rèn)為 OLED 相關(guān)的練習(xí)比大多數(shù)練習(xí)都要更難。在無需千兆級(jí)傳輸速率的場(chǎng)景中,嵌入式外設(shè)多采用串行外設(shè)接口(SPI):這種極其簡單的全雙工總線輕松實(shí)現(xiàn)超 50 Mbps 傳輸速率,且通常規(guī)避了 OLED 內(nèi)存排序邏輯等異常設(shè)計(jì)。
SPI 的基本原理和操作方式很容易理解:由 MCU 主導(dǎo)通信流程。當(dāng)需傳輸數(shù)據(jù)時(shí),MCU 將對(duì)應(yīng)外設(shè)的「片選」(CS-)引腳拉低,并向總線 SCK(串行時(shí)鐘)線輸出時(shí)鐘信號(hào)。MCU 通過 MOSI(主出從入)逐位發(fā)送數(shù)據(jù)(通常在時(shí)鐘上升沿觸發(fā)),外設(shè)則通過 MISO(主入從出)并行回應(yīng)。
常用(“模式 0”)的 SPI 協(xié)議要點(diǎn)
時(shí)鐘信號(hào)在傳輸單個(gè)字節(jié)或其整數(shù)倍后自動(dòng)停止。當(dāng) MCU 需單向接收數(shù)據(jù)時(shí),可通過 MOSI 發(fā)送虛擬字節(jié)以激活總線時(shí)鐘,同時(shí)讀取 MISO 數(shù)據(jù);同理,外設(shè)亦可借此機(jī)制保持通信同步。
盡管從某種角度來說,為 SPI 總線提供硬件驅(qū)動(dòng)可能并不是絕對(duì)必要的,但很多微控制器還是會(huì)提供一個(gè)針對(duì) SPI 總線的硬件驅(qū)動(dòng)。以 ATmega328P 為例,其 SPI 數(shù)據(jù)寄存器(SPDR)具備自動(dòng)收發(fā)功能:當(dāng)向該寄存器寫入字節(jié)時(shí),系統(tǒng)自動(dòng)執(zhí)行 SPI 總線傳輸,發(fā)送數(shù)據(jù)的同時(shí),該寄存器還會(huì)被來自 MISO(Master In Slave Out)的數(shù)據(jù)替換。傳輸完成時(shí),微控制器就會(huì)在 SPI 狀態(tài)寄存器(SPSR)中設(shè)置“SPI 完成”(SPIF)標(biāo)志位。
假設(shè)我需要將 ATmega328P 與一款 128kB SRAM模塊(型號(hào)23LC1024)對(duì)接。該模塊僅有 8 個(gè)引腳:2 個(gè)電源引腳(支持 2.5-5.5V 輸入),4 個(gè)基礎(chǔ) SPI 接口引腳,以及 2 個(gè)無需連接的冗余引腳。具體連接時(shí),需將模塊的"串行輸入"(SI)引腳接至 MCU 的 MOSI 線路,"串行輸出"(SO)引腳接至 MISO 線路,SCK(時(shí)鐘)線需互聯(lián)。最后的"片選"(CS-)引腳可接至 MCU任意輸出線,本例將采用端口B的第 0 位。
完成硬件連接后,需返回微控制器進(jìn)行配置:通過 DDRB 寄存器的位映射設(shè)置 MOSI 和 SCK 引腳為輸出模式,MISO 為輸入模式(如先前所述)。接著在 SPI 配置寄存器(SPCR)中激活兩個(gè)標(biāo)志位:"SPI 使能"(SPE)與"主控模式"(MSTR):
DDRB=0b11101111;SPCR= (1<< SPE) | (1?<< MSTR);除基本配置外,SPCR 寄存器還支持總線速率分頻設(shè)置(如SPI2X、SPR1/SPR0位),但實(shí)驗(yàn)階段默認(rèn)速率(通常為系統(tǒng)時(shí)鐘的1/4)已能滿足需求。完成寄存器初始化后,可通過以下函數(shù)實(shí)現(xiàn)與存儲(chǔ)控制器的單字節(jié)雙向通信:
uint8_tspi_rxtx_byte(uint8_tval){ SPDR = val;while(!(SPSR & (1<< SPIF)));??return?SPDR;}
應(yīng)用層協(xié)議也很簡單,寫入流程如下:
發(fā)送寫指令碼 0x02
發(fā)送 3 個(gè)字節(jié)的寫入地址
連續(xù)發(fā)送待寫入數(shù)據(jù)流
拉高 CS- 引腳結(jié)束操作
雖然圖表看似復(fù)雜,但實(shí)現(xiàn)這一功能的代碼卻簡單而貼心:
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 */}讀取存儲(chǔ)器的工作原理大致相同,MCU 會(huì)發(fā)送一條 “讀取 ”命令 (0x03),然后不斷發(fā)送虛字節(jié),同時(shí)保存從存儲(chǔ)器芯片收到的響應(yīng):
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芯片通信、對(duì)接非易失性閃存控制器、驅(qū)動(dòng)SD存儲(chǔ)卡,還是操作樂鑫(Espressif)等廠商推出的低成本W(wǎng)iFi+TCP/IP模組,SPI總線協(xié)議棧的核心交互邏輯均高度統(tǒng)一。
值得關(guān)注的是,當(dāng)前主流WiFi模組的應(yīng)用層協(xié)議竟沿用了1980年代Hayes調(diào)制解調(diào)器的指令體系(經(jīng)適度現(xiàn)代化改造)。例如,開發(fā)者仍可通過經(jīng)典"AT"指令集發(fā)起HTTP請(qǐng)求——這種將復(fù)古命令行與現(xiàn)代物聯(lián)網(wǎng)技術(shù)深度融合的設(shè)計(jì),堪稱嵌入式領(lǐng)域的"復(fù)古科技彩蛋"。
原文轉(zhuǎn)載自:https://lcamtuf.substack.com/p/mcu-land-part-2-mysteries-of-the,經(jīng)過翻譯及校驗(yàn)
注意:如果想第一時(shí)間收到 KiCad 內(nèi)容推送,請(qǐng)點(diǎn)擊下方的名片,按關(guān)注,再設(shè)為星標(biāo)。
常用合集匯總:
和 Dr Peter 一起學(xué) KiCad
KiCad 8 探秘合集
KiCad 使用經(jīng)驗(yàn)分享
KiCad 設(shè)計(jì)項(xiàng)目(Made with KiCad)
常見問題與解決方法
KiCad 開發(fā)筆記
插件應(yīng)用
發(fā)布記錄
審核編輯 黃宇
-
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7636瀏覽量
166448 -
SPI
+關(guān)注
關(guān)注
17文章
1784瀏覽量
94787 -
總線
+關(guān)注
關(guān)注
10文章
2952瀏覽量
89369
發(fā)布評(píng)論請(qǐng)先 登錄
探秘EtherCAT總線協(xié)議轉(zhuǎn)換網(wǎng)關(guān)

探秘Profibus現(xiàn)場(chǎng)總線協(xié)議轉(zhuǎn)換網(wǎng)關(guān)模塊

看完這篇,SPI其實(shí)也很簡單嘛(可下載)
探秘新能源行業(yè)利器:多串保護(hù)板測(cè)試儀的革新應(yīng)用
對(duì)于一款新的BSP如何添加SPI驅(qū)動(dòng)

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

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

評(píng)論