作者:ZeroGrid 實驗室
前言:這不是讀記憶體,這是「下訂單」
上一篇我們解剖了 SX1262 的內部構造,知道它裡面住了一個「管理員」(協同處理器)。這造成了它與傳統感測器(如加速度計、溫濕度計)在程式寫法上的巨大差異。
- 傳統感測器 (Memory Mapped):你給地址,它馬上把資料吐給你。這叫「讀取」。
- SX1262 (Command Based):你給指令,內部的管理員收到後,要去倉庫找資料,搬運出來,最後才給你。這叫「請求」。
因為這個「找資料」的過程需要時間,所以 Semtech 在 SPI Bus (匯流排) 之外,多設計了一根至關重要的腳位——BUSY。
今天這堂課,我們就要學會看懂這顆晶片的「臉色」。
1. 物理層的紅綠燈:BUSY (Pin 14) 與 NSS (Pin 19)
在 ZeroGrid 的底層設計中,每一筆 SPI 傳輸都被嚴格的時序包覆著。我們要先搞懂兩位主角:BUSY 與 NSS。

BUSY Pin
A. BUSY 腳位:裁判的哨音
想像 SPI 通訊是一場比賽。BUSY 腳位就是裁判口中的哨子。
- BUSY 拉高 (High):哨音響起,比賽暫停。
- 這代表內部的管理員正在忙(可能剛睡醒、正在校正頻率、或正在處理你上一條指令)。
- 這時候,絕對不能去拉動 NSS 腳位,否則晶片會錯亂甚至當機。
- BUSY 拉低 (Low):哨音停止,比賽繼續。
- 這代表管理員現在有空了,你可以隨時開始對話。
⚠️ 技術長劃重點:前後都要等! 很多工程師只知道「發送前」要檢查 BUSY。錯了! 發送後也要檢查!因為當你拉高 NSS 結束通訊的那一瞬間,SX1262 才會開始執行你剛剛給的指令,這時 BUSY 會瞬間拉高。如果你不等待就馬上送下一筆,就會撞車。
B. NSS 腳位:對話的開始
NSS (Not Slave Select),也就是一般說的 CS (Chip Select)。如果 BUSY 是「能不能說話」,NSS 就是「我現在要跟你說話」。
- 平時 (High):MCU 雖然連著線,但 SX1262 當作沒聽到。
- 拉低 (Low):這是「開始」的信號。這就像你拍了一下管理員的肩膀,告訴他:「嘿,接下來的指令是給你的。」

NSS timing
2. 協議層的陷阱:OpCode 與那個消失的 Byte
搞定了時序,我們來看資料格式。SX1262 的所有操作都是以 OpCode (操作碼) 開始。我們以最常用的 「讀取暫存器 (Read Register)」 為例。
假設我們要讀取 Sync Word (同步字),它的地址是 0x0740。
🔍 什麼是 Sync Word (同步字)? 它是 LoRa 的「門禁卡」。接收端只會解碼跟自己 Sync Word 相同的訊號。
0x3444: Public Network (公用網路,如 LoRaWAN)。0x1424: Private Network (私有網路,ZeroGrid 使用此設定以過濾雜訊)。
直覺的寫法 (錯誤示範):
你以為只要送出 [OpCode] [AddrH] [AddrL],然後接收一個 Byte 就可以了嗎?
Plaintext
// ❌ 錯誤的時序
MOSI (主機送): 0x1D (讀指令) -> 0x07 -> 0x40 -> [讀取]
MISO (晶片回): (無效) -> (無效)-> (無效)-> 0x00 (???)
你會讀到 0x00。為什麼?因為你太急了。
正確的寫法 (Datasheet 標準):
當你送完地址 0x40 的最後一個 bit 時,內部的管理員才剛知道你要讀哪裡,他還沒來得及把資料搬到 SPI 的門口。你需要多送 8 個時鐘週期(Dummy)給他一點時間準備。這個空訊號就叫 NOP (No Operation) 或 Dummy Byte。
Plaintext
// ✅ 正確的時序
MOSI (主機送): 0x1D (讀指令) -> 0x07 -> 0x40 -> 0x00 (NOP) -> [讀取]
MISO (晶片回): (無效) -> (無效)-> (無效)-> (狀態) -> 0x14 (資料!)
⚠️ 新手坑: 只有 讀取模式 (Read Register, Read Buffer) 需要這個 Dummy Byte。 寫入模式 (Write Register) 則不需要,因為是你把資料塞給他,他不需要時間準備。

Extra NOP is needed
3. 核心邏輯解密:把理論變成程式
現在我們來看看在 ZeroGrid 的核心驅動層中,這段邏輯是如何被實作出來的:
C
uint8_t SX1262_ReadRegSingle(uint16_t reg) {
uint8_t val = 0;
// 1. [前檢查] 確保裁判沒吹哨 (Wait BUSY Low)
SX1262_WaitBusy();
// 2. 拍肩膀,對話開始 (NSS Low)
gpio_put(PIN_CS, 0);
// 3. 組合指令包:OpCode + Addr + NOP (Dummy)
// 注意最後那個 0x00,這就是我們給晶片的喘息空間
uint8_t cmd[] = {CMD_READ_REGISTER, (reg >> 8) & 0xFF, reg & 0xFF, 0x00};
// 4. 發送指令頭
spi_write_blocking(SX_SPI_PORT, cmd, 4);
// 5. 讀取真正的資料
spi_read_blocking(SX_SPI_PORT, 0, &val, 1);
// 6. 對話結束 (NSS High)
gpio_put(PIN_CS, 1);
// 7. [後檢查] 這點最重要!
// 指令結束後,晶片可能開始內部處理,BUSY 會再次拉高。
// 必須在這裡擋住,保護下一次通訊。
SX1262_WaitBusy();
return val;
}
這段程式碼嚴格遵守了「前後檢查 (Double Check)」與「給空間 (Dummy)」兩大原則。如果你的程式碼讀出來都是 0,請回頭檢查第 3 步的 Dummy Byte 是否被遺漏了。
4. ZeroGrid 實驗室:親手驗證
理論講完了,我們用 ZeroGrid v1.4.0 的 實驗室指令 (/reg) 來驗證我們的 SPI 驅動是不是真的活著。
我們來讀取 Sync Word (暫存器 0x0740)。
實驗步驟:
- 將 ZeroGrid 接上電腦,開啟終端機。
- 輸入
/reg read 0740(讀取高位)。 - 輸入
/reg read 0741(讀取低位)。
終端機畫面:
Plaintext
> /reg read 0740
[SX1262] Reg 0x0740 = 0x14 <-- 成功讀到!
> /reg read 0741
[SX1262] Reg 0x0741 = 0x24 <-- 成功讀到!
發生了什麼事? 當你看到 0x14 出現在螢幕上時,代表:
- MCU 成功等待了 BUSY 釋放。
- 正確發送了
0x1D指令與地址。 - 正確插入了 Dummy Byte,避開了讀到
0x00的坑。 - SX1262 活著,而且聽懂了你的話。
進階挑戰:修改暫存器 我們試著把同步字的高位改成 0x34 (Public Network)。
Plaintext
> /reg write 0740 34
[SX1262] Write Reg 0x0740 <= 0x34
> /reg read 0740
[SX1262] Reg 0x0740 = 0x34 <-- 寫入成功!
這個簡單的「讀 -> 改 -> 讀」實驗,證明了我們對這顆晶片擁有了完全的控制權。
下一課預告
恭喜!你已經打通了任督二脈(SPI Bus)。 但你會發現,晶片現在還是「呆滯」的。它雖然醒了,但還沒開始工作。 SX1262 擁有複雜的狀態機 (State Machine):它有睡眠模式、待機模式、接收模式、發射模式。
下一篇 #3 狀態機的藝術,我們將教你如何指揮這位管理員切換工作崗位,以及為什麼我們必須在 Standby 模式下才能進行參數設定。














