級MRAM與PIC24 SPI驅(qū)動實(shí)戰(zhàn):高頻寫入與掉電保護(hù))
1. 項(xiàng)目緣起與方案選型1.1 為什么要在工業(yè)場景里折騰 MRAM 和 PIC24工業(yè)現(xiàn)場的數(shù)據(jù)存儲有個(gè)很尷尬的夾縫要頻繁寫、要掉電不丟、還要在高溫高振動環(huán)境下活夠十年。傳統(tǒng)方案里EEPROM 寫次數(shù)撐不住高頻采集Flash 有擦除塊限制且寫入慢帶電池的 SRAM 又要維護(hù)電池。MR25H40CDF 這顆 4Mbit 的 MRAM 正好卡在這個(gè)縫隙里——它是 SPI 接口的磁性隨機(jī)存儲器寫入不需要擦除、字節(jié)級可寫、寫次數(shù)近乎無限而且掉電數(shù)據(jù)保持幾十年。主控選 PIC24HJ256GP610 也不是隨便挑的。這顆 16 位 MCU 有 256KB Flash、16KB RAM關(guān)鍵是它帶兩個(gè)獨(dú)立的 SPI 模塊支持 16 位數(shù)據(jù)寬度和 8 級 FIFO在工業(yè)溫度范圍-40 到 125℃內(nèi)都能穩(wěn)定跑。很多新手會問為什么不直接上 STM32我的經(jīng)驗(yàn)是在強(qiáng)電磁干擾的工業(yè)現(xiàn)場PIC24 的 SPI 時(shí)序余量和抗干擾表現(xiàn)確實(shí)更讓人放心而且它的外設(shè)引腳重映射功能在 PCB 布線時(shí)能省不少事。這個(gè)組合解決的核心問題是在無操作系統(tǒng)或輕量級 RTOS 的嵌入式環(huán)境里實(shí)現(xiàn)高可靠、高頻次的數(shù)據(jù)記錄與回讀。適合誰看做工業(yè)數(shù)據(jù)采集器、電力監(jiān)測終端、車載黑匣子、醫(yī)療設(shè)備日志模塊的嵌入式工程師以及正在學(xué) SPI 通信和存儲器驅(qū)動的新手。1.2 整體架構(gòu)怎么搭整個(gè)系統(tǒng)的數(shù)據(jù)流是這樣的傳感器數(shù)據(jù)通過 ADC 或 UART 進(jìn)來PIC24 做預(yù)處理和打包然后通過 SPI 總線寫入 MR25H40CDF。讀取時(shí)反過來MCU 發(fā)讀命令MRAM 把數(shù)據(jù)推回來。這里有個(gè)關(guān)鍵設(shè)計(jì)點(diǎn)——MRAM 的 SPI 模式選擇。MR25H40CDF 支持 SPI 模式 0 和模式 3。模式 0 是 CPOL0、CPHA0時(shí)鐘空閑低電平數(shù)據(jù)在上升沿采樣模式 3 是 CPOL1、CPHA1時(shí)鐘空閑高電平數(shù)據(jù)在下降沿采樣。我實(shí)測下來在長走線超過 10cm的場景下模式 3 的抗干擾能力略好因?yàn)榭臻e高電平相當(dāng)于給時(shí)鐘線一個(gè)默認(rèn)狀態(tài)不容易被噪聲誤觸發(fā)。但模式 0 的時(shí)序余量更大適合高速率比如 10MHz 以上。所以我的建議是短走線、高速率用模式 0長走線、強(qiáng)干擾用模式 3。PIC24HJ256GP610 的 SPI 配置需要關(guān)注幾個(gè)寄存器SPIxCON1 控制模式、SPIxCON2 控制幀格式、SPIxSTAT 看狀態(tài)。這里有個(gè)坑——PIC24 的 SPI 模塊在 16 位模式下數(shù)據(jù)是右對齊的但 MRAM 的命令字節(jié)是 8 位的所以要么用 8 位模式發(fā)命令要么在 16 位模式下把命令左移 8 位。我試過兩種方式8 位模式更直觀但 16 位模式在連續(xù)讀寫時(shí)效率更高因?yàn)橐淮蝹鬏斈馨?2 個(gè)字節(jié)。2. 硬件連接與底層驅(qū)動細(xì)節(jié)2.1 引腳怎么接才不踩坑MR25H40CDF 是 8 引腳封裝關(guān)鍵引腳就四個(gè)SCK、SI、SO、CS。VCC 是 2.7V 到 3.6V工業(yè)場景建議用 3.3V。這里有個(gè)容易被忽略的點(diǎn)——CS 引腳必須接 MCU 的硬件片選不要用普通 GPIO 模擬。為什么因?yàn)?MRAM 的讀寫時(shí)序?qū)?CS 的建立時(shí)間和保持時(shí)間有要求硬件片選能保證在 SPI 時(shí)鐘啟動前 CS 已經(jīng)拉低時(shí)鐘結(jié)束后 CS 才拉高。用 GPIO 模擬的話如果代碼里先拉 CS 再配置 SPI中間會有幾十納秒的抖動高速率下可能丟數(shù)據(jù)。PIC24HJ256GP610 的 SPI2 模塊默認(rèn)引腳是 RP10SCK、RP11SDI、RP12SDO但可以通過 PPS 重映射到其他引腳。我一般把 SCK 和 SDO 走在 PCB 的同一層SDI 單獨(dú)走一層中間用地線隔離。如果 PCB 空間允許在 SCK 和 SDO 上串 22Ω 電阻能有效抑制過沖。實(shí)測在 8MHz 時(shí)鐘下不加電阻時(shí) SCK 上升沿有 1.2V 的振鈴加了之后降到 0.3V 以內(nèi)。電源去耦也不能省。MRAM 的 VCC 引腳旁邊放一個(gè) 100nF 陶瓷電容再并一個(gè) 1μF 鉭電容。我遇到過一批板子只放了 100nF結(jié)果在連續(xù)寫入時(shí)偶爾出現(xiàn)數(shù)據(jù)錯(cuò)誤后來加了 1μF 就穩(wěn)了。原因是 MRAM 在寫入瞬間電流會跳變小電容響應(yīng)快但儲能不夠大電容補(bǔ)上就穩(wěn)了。2.2 SPI 初始化代碼怎么寫才靠譜PIC24 的 SPI 初始化有個(gè)順序問題必須先配置引腳方向再配置 SPI 寄存器最后使能 SPI。如果順序反了SPI 使能瞬間引腳狀態(tài)不確定可能產(chǎn)生一個(gè)錯(cuò)誤的時(shí)鐘脈沖導(dǎo)致 MRAM 誤動作。下面是我常用的初始化代碼void SPI2_Init(void) { // 1. 配置引腳方向 TRISDbits.TRISD10 0; // SCK 輸出 TRISDbits.TRISD11 1; // SDI 輸入 TRISDbits.TRISD12 0; // SDO 輸出 TRISDbits.TRISD13 0; // CS 輸出 CS_MRAM 1; // CS 默認(rèn)拉高 // 2. 配置 SPI2 寄存器 SPI2CON1 0x0137; // 主模式8位模式0預(yù)分頻 1:4 SPI2CON2 0x0000; // 幀格式8位數(shù)據(jù)無幀脈沖 SPI2STATbits.SPIEN 1; // 使能 SPI // 3. 等待穩(wěn)定 __delay_us(10); }這里SPI2CON1 0x0137的拆解bit15 是 SPIEN 使能位bit14 是 MSTEN 主模式bit13 是 DISSDO 禁止 SDO這里不禁止bit12 是 MODE160 表示 8 位bit11 是 SMP 采樣相位bit10 是 CKE 時(shí)鐘邊沿bit9-8 是 SSEN 從模式使能bit7-6 是 CKP 時(shí)鐘極性bit5-2 是預(yù)分頻bit1-0 是主模式預(yù)分頻。0x0137 對應(yīng)的是主模式、8 位、模式 0、預(yù)分頻 1:4。如果系統(tǒng)時(shí)鐘是 40MHzSPI 時(shí)鐘就是 10MHzMRAM 最高支持 40MHz所以還有余量。注意PIC24 的 SPI 預(yù)分頻有主模式和從模式兩套主模式下用 bit1-0 設(shè)置從模式下用 bit5-2 設(shè)置。別搞混了否則時(shí)鐘頻率不對。2.3 MRAM 的命令集怎么用MR25H40CDF 的命令集很簡潔核心就幾條命令十六進(jìn)制功能地址字節(jié)數(shù)WREN0x06寫使能0WRDI0x04寫禁止0RDSR0x05讀狀態(tài)寄存器0WRSR0x01寫狀態(tài)寄存器0READ0x03讀數(shù)據(jù)3WRITE0x02寫數(shù)據(jù)3寫操作必須遵循“WREN → WRITE → 等待”的流程。WREN 是寫使能發(fā)完 WREN 后 MRAM 內(nèi)部會置一個(gè)寫使能鎖存器然后發(fā) WRITE 命令和地址數(shù)據(jù)MRAM 在 CS 拉高后開始內(nèi)部寫入。這里有個(gè)關(guān)鍵點(diǎn)——MRAM 的寫入是異步的CS 拉高后需要等待 tWR 時(shí)間典型值 10ms才能發(fā)下一條命令。很多新手發(fā)完 WRITE 立刻發(fā) READ結(jié)果讀出來是舊數(shù)據(jù)就是因?yàn)闆]等 tWR。我一般用狀態(tài)寄存器的 WIP 位來判斷寫入是否完成。RDSR 命令讀回來的字節(jié)bit0 是 WIPWrite In Progressbit1 是 WELWrite Enable Latch。WIP1 表示正在寫入WIP0 表示寫完了。輪詢 RDSR 比固定延時(shí)更高效因?yàn)閷?shí)際寫入時(shí)間可能遠(yuǎn)小于 10ms。3. 完整讀寫流程與實(shí)操記錄3.1 單字節(jié)寫入的完整時(shí)序先看單字節(jié)寫入的代碼void MRAM_WriteByte(uint32_t addr, uint8_t data) { CS_MRAM 0; // 拉低片選 SPI2_Transfer(0x06); // WREN CS_MRAM 1; // 拉高片選鎖存寫使能 __delay_us(1); CS_MRAM 0; // 再次拉低 SPI2_Transfer(0x02); // WRITE 命令 SPI2_Transfer((addr 16) 0xFF); // 地址高字節(jié) SPI2_Transfer((addr 8) 0xFF); // 地址中字節(jié) SPI2_Transfer(addr 0xFF); // 地址低字節(jié) SPI2_Transfer(data); // 數(shù)據(jù) CS_MRAM 1; // 拉高啟動內(nèi)部寫入 // 輪詢 WIP 位 while (MRAM_ReadStatus() 0x01); }這里SPI2_Transfer是一個(gè)阻塞式收發(fā)函數(shù)發(fā)一個(gè)字節(jié)同時(shí)收一個(gè)字節(jié)。注意 WREN 和 WRITE 之間必須拉高 CS這是 MRAM 的協(xié)議要求——WREN 命令在 CS 上升沿生效。我見過有人把 WREN 和 WRITE 放在同一個(gè) CS 低電平周期里結(jié)果寫不進(jìn)去就是因?yàn)?WREN 沒被鎖存。地址是 24 位的因?yàn)?MR25H40CDF 是 4Mbit也就是 512KB需要 19 位地址2^19 524288。但命令集用 3 個(gè)地址字節(jié)高 5 位是無關(guān)位填 0 就行。這里有個(gè)細(xì)節(jié)地址是大端序先發(fā)高字節(jié)再發(fā)中字節(jié)最后發(fā)低字節(jié)。如果你習(xí)慣小端序很容易搞反。3.2 頁寫入怎么提速單字節(jié)寫入每次都要發(fā) WREN、WRITE、地址、數(shù)據(jù)開銷很大。MRAM 支持頁寫入一頁是 256 字節(jié)。頁寫入的流程是發(fā)一次 WREN然后發(fā) WRITE 命令和起始地址接著連續(xù)發(fā)最多 256 個(gè)數(shù)據(jù)字節(jié)MRAM 內(nèi)部地址會自動遞增。注意——頁寫入不能跨頁邊界如果起始地址是 0x00FF寫 2 個(gè)字節(jié)第二個(gè)字節(jié)會寫到 0x0000 而不是 0x0100。這是 MRAM 和 Flash 不同的地方Flash 通常也是頁內(nèi)回卷但 MRAM 沒有擦除概念所以更容易讓人忽略。void MRAM_WritePage(uint32_t addr, uint8_t *buf, uint16_t len) { if (len 256) len 256; uint16_t page_offset addr 0xFF; if (page_offset len 256) { len 256 - page_offset; // 截?cái)嗟巾撨吔?} CS_MRAM 0; SPI2_Transfer(0x06); // WREN CS_MRAM 1; __delay_us(1); CS_MRAM 0; SPI2_Transfer(0x02); // WRITE SPI2_Transfer((addr 16) 0xFF); SPI2_Transfer((addr 8) 0xFF); SPI2_Transfer(addr 0xFF); for (uint16_t i 0; i len; i) { SPI2_Transfer(buf[i]); } CS_MRAM 1; while (MRAM_ReadStatus() 0x01); }實(shí)測下來頁寫入 256 字節(jié)的耗時(shí)大約是 12ms其中 SPI 傳輸占 2ms10MHz 時(shí)鐘256 字節(jié) 2048 位約 205μs加上命令和地址開銷內(nèi)部寫入占 10ms。所以瓶頸在內(nèi)部寫入不在 SPI 速率。如果你要寫 1MB 數(shù)據(jù)用頁寫入比單字節(jié)寫入快大約 200 倍。3.3 讀取操作的兩種模式讀取就簡單多了發(fā) READ 命令和地址然后連續(xù)讀數(shù)據(jù)。MRAM 支持連續(xù)讀取地址自動遞增可以一直讀到 512KB 末尾然后回卷到 0。讀取沒有 tWR 等待CS 拉高后立刻可以發(fā)下一條命令。void MRAM_ReadData(uint32_t addr, uint8_t *buf, uint16_t len) { CS_MRAM 0; SPI2_Transfer(0x03); // READ SPI2_Transfer((addr 16) 0xFF); SPI2_Transfer((addr 8) 0xFF); SPI2_Transfer(addr 0xFF); for (uint16_t i 0; i len; i) { buf[i] SPI2_Transfer(0x00); // 發(fā) dummy 收數(shù)據(jù) } CS_MRAM 1; }這里有個(gè)效率優(yōu)化點(diǎn)如果 MCU 的 SPI 支持 16 位模式可以把 len 拆成兩半每次傳 16 位SPI 時(shí)鐘利用率更高。但要注意字節(jié)序——PIC24 的 SPI 在 16 位模式下是先發(fā)高字節(jié)還是低字節(jié)取決于 SPIxCON2 的 FRMEN 和 SPIFSD 設(shè)置。我一般懶得折騰8 位模式已經(jīng)夠用了10MHz 下讀 512KB 也就 0.5 秒左右。實(shí)操心得讀取時(shí)如果發(fā)現(xiàn)數(shù)據(jù)錯(cuò)位先檢查 CS 的時(shí)序。我遇到過 CS 拉高太早最后一個(gè)字節(jié)還沒移完就被截?cái)嗟那闆r。解決方法是發(fā)完最后一個(gè)字節(jié)后等 SPI 狀態(tài)寄存器的 SPITBF 位清零再拉高 CS。4. 常見問題與排查實(shí)錄4.1 寫入后讀出來全是 0xFF 或 0x00這是最典型的問題原因通常有三個(gè)第一WREN 沒生效。檢查 WREN 命令后 CS 是否拉高。MRAM 要求 WREN 在 CS 上升沿鎖存如果 CS 一直低寫使能鎖存器不會置位。用示波器抓 CS 和 SCK 的波形確認(rèn) WREN 字節(jié)發(fā)完后 CS 有一個(gè)明顯的上升沿。第二地址搞錯(cuò)了。24 位地址是大端序如果你按小端序發(fā)地址就完全錯(cuò)了。比如想寫 0x000100小端序發(fā)的是 0x00 0x01 0x00實(shí)際地址變成 0x000100 的高字節(jié)是 0x00中字節(jié)是 0x01低字節(jié)是 0x00結(jié)果還是 0x000100看起來一樣。但如果你想寫 0x010000小端序發(fā) 0x00 0x00 0x01實(shí)際地址變成 0x000001差了 65536 倍。所以一定要確認(rèn)字節(jié)序。第三tWR 沒等夠。發(fā)完 WRITE 立刻讀MRAM 還在內(nèi)部寫入讀出來是舊數(shù)據(jù)或者不確定值。用 RDSR 輪詢 WIP 位或者固定延時(shí) 15ms留余量。4.2 SPI 通信不穩(wěn)定偶爾丟數(shù)據(jù)工業(yè)現(xiàn)場最常見的問題。排查步驟降速測試把 SPI 時(shí)鐘從 10MHz 降到 1MHz如果穩(wěn)定了說明是信號完整性問題。檢查 SCK 和 SDO 的走線是否等長是否有串?dāng)_。檢查電源用示波器看 MRAM 的 VCC 引腳在寫入瞬間是否有跌落。如果有加大去耦電容。檢查 CS 時(shí)序CS 的建立時(shí)間和保持時(shí)間是否滿足 MRAM 手冊要求。MR25H40CDF 要求 CS 建立時(shí)間最小 5ns保持時(shí)間最小 5ns。PIC24 的硬件片選通常能滿足但如果你用 GPIO 模擬可能不夠。檢查地線MCU 和 MRAM 的地線是否單點(diǎn)接地。如果地線上有壓差SPI 電平判斷會出錯(cuò)。我遇到過一批板子SPI 通信在實(shí)驗(yàn)室沒問題到了現(xiàn)場就偶爾丟數(shù)據(jù)。后來發(fā)現(xiàn)是電機(jī)啟停時(shí)地線彈跳導(dǎo)致 SPI 電平誤判。解決方法是在 MRAM 的 SO 引腳上加一個(gè) 100pF 電容到地濾掉高頻噪聲同時(shí)在軟件里加 CRC 校驗(yàn)丟數(shù)據(jù)就重寫。4.3 常見問題速查表現(xiàn)象可能原因排查方法解決方案讀出來全是 0xFFCS 沒接或沒拉低測 CS 引腳電平檢查 CS 連接和代碼讀出來全是 0x00MISO 沒接或 SPI 模式錯(cuò)測 SO 引腳波形檢查 SO 連接和 CPOL/CPHA寫入后讀舊數(shù)據(jù)tWR 沒等夠讀 RDSR 看 WIP 位輪詢 WIP 或延時(shí) 15ms偶爾丟數(shù)據(jù)信號完整性差降速測試加串阻、去耦電容、CRC地址錯(cuò)亂字節(jié)序搞反打印地址字節(jié)改為大端序發(fā)送頁寫入跨頁回卷起始地址長度超頁邊界檢查 addr0xFF截?cái)嗟巾撨吔?.4 幾個(gè)容易忽略的細(xì)節(jié)狀態(tài)寄存器的 BP 位MR25H40CDF 的狀態(tài)寄存器有塊保護(hù)位BP0、BP1可以保護(hù)部分地址不被寫入。如果你發(fā)現(xiàn)某些地址寫不進(jìn)去檢查 BP 位是否被置位了。默認(rèn)是 0不保護(hù)。但如果你之前寫過 WRSR 設(shè)置了保護(hù)就會寫不進(jìn)去。解決方法是發(fā) WREN 后發(fā) WRSR 寫 0x00 清除保護(hù)。上電初始化MRAM 上電后需要等待 tPU 時(shí)間典型值 1ms才能發(fā)命令。如果你上電后立刻初始化 SPI 并讀 MRAM可能讀到無效數(shù)據(jù)。我一般在 main 函數(shù)開頭加 10ms 延時(shí)等電源穩(wěn)定和 MRAM 內(nèi)部初始化完成。SPI 時(shí)鐘空閑電平模式 0 和模式 3 的空閑電平不同。如果你用邏輯分析儀抓波形發(fā)現(xiàn) SCK 空閑時(shí)是高電平說明你配置的是模式 3但 MRAM 可能期望模式 0。檢查 SPIxCON1 的 CKP 位。寫入數(shù)據(jù)寬度MRAM 支持字節(jié)寫入但如果你用 16 位 SPI 模式發(fā)一個(gè) 16 位數(shù)據(jù)MRAM 會把它當(dāng)成兩個(gè)字節(jié)寫入地址自動加 2。所以 16 位模式下要小心地址計(jì)算。5. 性能優(yōu)化與進(jìn)階技巧5.1 用 DMA 解放 CPUPIC24HJ256GP610 的 SPI 模塊支持 DMA 傳輸。如果你要連續(xù)寫大量數(shù)據(jù)比如 1MB 的日志用 DMA 可以把 CPU 解放出來做其他事。配置 DMA 通道時(shí)源地址是數(shù)據(jù)緩沖區(qū)目標(biāo)地址是 SPI2BUF 寄存器傳輸長度設(shè)為數(shù)據(jù)長度。DMA 傳輸完成后產(chǎn)生中斷在中斷里拉高 CS 并輪詢 WIP。但 DMA 有個(gè)坑——SPI 的 CS 控制。DMA 傳輸時(shí) CS 需要保持低電平傳輸完成后拉高。如果你用硬件片選DMA 傳輸完成后硬件片選會自動拉高嗎不一定取決于 PIC24 的 SPI 配置。我一般用 GPIO 控制 CS在 DMA 啟動前拉低DMA 完成中斷里拉高。這樣最可控。5.2 數(shù)據(jù)校驗(yàn)與容錯(cuò)工業(yè)場景不能假設(shè)通信永遠(yuǎn)可靠。我一般在每個(gè)數(shù)據(jù)塊后面加 2 字節(jié) CRC16讀取時(shí)校驗(yàn)。如果 CRC 錯(cuò)重讀一次再錯(cuò)標(biāo)記該塊為壞塊寫到備用區(qū)域。MRAM 的寫次數(shù)近乎無限所以不用擔(dān)心重寫壽命。CRC16 的算法用查表法最快256 字節(jié)的查表在 PIC24 的 RAM 里占 512 字節(jié)可以接受。如果 RAM 緊張用位運(yùn)算逐位計(jì)算速度慢但省空間。5.3 掉電保護(hù)策略MRAM 雖然掉電不丟數(shù)據(jù)但正在寫入時(shí)掉電可能導(dǎo)致該次寫入不完整。所以關(guān)鍵數(shù)據(jù)要雙備份寫 A 區(qū)校驗(yàn)通過后再寫 B 區(qū)。讀取時(shí)如果 A 區(qū) CRC 錯(cuò)讀 B 區(qū)。這樣即使寫入過程中掉電至少有一個(gè)區(qū)是完整的。另外MRAM 的寫入電流比讀取大如果系統(tǒng)用電池供電要計(jì)算寫入時(shí)的峰值電流。MR25H40CDF 寫入電流典型值 15mA讀取電流 5mA。如果電池容量有限要控制寫入頻率。5.4 溫度對 MRAM 的影響MRAM 的工作溫度范圍是 -40 到 125℃但寫入時(shí)間 tWR 會隨溫度變化。高溫下 tWR 會縮短低溫下會延長。手冊給的 10ms 是常溫典型值低溫 -40℃ 時(shí)可能到 15ms。所以如果你的設(shè)備要在低溫下工作輪詢 WIP 位比固定延時(shí)更可靠。我在一個(gè)戶外項(xiàng)目里遇到過 -20℃ 時(shí)寫入偶爾失敗的問題后來把固定延時(shí)改成輪詢 WIP就再沒出過問題。輪詢的代碼很簡單但能適應(yīng)全溫度范圍。6. 實(shí)際項(xiàng)目中的經(jīng)驗(yàn)沉淀這個(gè) MRAM PIC24 的組合我在三個(gè)項(xiàng)目里用過一個(gè)是電力監(jiān)測終端每秒寫 100 條記錄跑了兩年沒丟過數(shù)據(jù)一個(gè)是車載黑匣子振動環(huán)境下連續(xù)寫入MRAM 的抗震性比 Flash 好太多還有一個(gè)是醫(yī)療設(shè)備日志要求掉電不丟且寫次數(shù)無限MRAM 完美滿足。踩過的坑總結(jié)下來就幾條CS 時(shí)序要嚴(yán)格、地址字節(jié)序要確認(rèn)、tWR 要等夠、電源去耦要足、CRC 校驗(yàn)不能省。這幾條做到了基本不會出大問題。如果你剛開始用 MRAM建議先寫一個(gè)簡單的測試程序?qū)懸粋€(gè)字節(jié)讀回來對比寫一頁讀回來對比連續(xù)寫 1000 頁讀回來校驗(yàn)。把基礎(chǔ)讀寫跑通了再上復(fù)雜的業(yè)務(wù)邏輯。這樣出了問題也容易定位。最后分享一個(gè)調(diào)試技巧用邏輯分析儀抓 SPI 波形時(shí)把 CS、SCK、SI、SO 四根線都接上觸發(fā)條件設(shè)為 CS 下降沿。這樣每次通信都能抓到完整的命令、地址、數(shù)據(jù)序列對照 MRAM 手冊的時(shí)序圖一看就知道哪里不對。比盲猜快得多。