Bank 切換
什麼是 Bank(頁)
有些晶片的暫存器數量比位移能表示的還多,會用一個特別的暫存器當作「頁碼」: 先把頁碼寫進那個暫存器,之後同一個位移讀到的內容就會依照目前的頁碼而不同,好像 同一個書架格子放著好幾本不同的書,要先決定翻開哪一本。這個「先設頁碼再存取」的 機制就叫做 Bank。(這裡的「頁」跟畫面上的「分頁 / Tab」是兩件不相干的事, 不要搞混。)
先設定好 Bank 選擇暫存器:i2c.bank_reg()
除了I2C 讀寫教過的 i2c.addr(),用 Bank 之前還多一步:告訴
程式哪一個位移是頁碼暫存器。用 i2c.bank_reg(reg, mask [, slot]):
i2c.addr(0x58) -- 先設定位址
i2c.bank_reg(0xF0, 0xFF) -- 再設定頁碼暫存器:位移 0xF0、遮罩 0xFFreg(0x000xFF)是頁碼暫存器的位移;mask(0x010xFF)是遮罩,
代表哪些位元參與頁碼——這裡的 0xFF 代表整個位元組都拿來放頁碼用(8 個位元全部
參與)。效果等同指令列的 bank reg F0 FF,設定好之後 i2c.bank()/dump_all()
才能用。
⚠ 遮罩 0xFF 這種全遮罩下,dump_all() 得顯式給一個 count:0xFF
代表整個位元組都是頁碼,光看遮罩本身推不出共有幾頁,dump_all(slot) 省略
count 會直接出錯;改用 dump_all(slot, count) 顯式指定頁數就能正常運作,
細節見記錄與傾印。
⚠ 順序很重要:一定要先 i2c.addr()、再 i2c.bank_reg()。 如果反過來、
在設定好頁碼暫存器之後才呼叫 i2c.addr() 換位址,剛設好的頁碼暫存器設定會被
整組清掉(跟畫面上先 bank reg、後 addr 的行為完全一樣)。
⚠ 這兩個設定只在這次腳本執行期間有效:腳本結束時(不論成功、失敗、
fail()、發生錯誤或被中止)程式會自動把位址與頁碼暫存器設定都改回腳本開始前的
樣子,不會寫進 config.ini。但晶片實際停在哪一頁不會被自動還原——如果
腳本用 i2c.bank() 切換過頁,收尾前記得自己呼叫 i2c.bank(0)(或換回原本
那一頁),下面的範例就是這樣做的。
下面的範例已經自己做好這兩步,不需要再另外下任何指令:
nexus_tui.exe --dongle mock --batch --run bank.lua另一種做法:不想在腳本裡設定,也可以在執行腳本之前先用畫面或指令列
(addr 58、bank reg F0 FF,批次模式是 --cmd "addr 58" --cmd "bank reg F0 FF")設定好——addr 58 會印一行 ADDR: 0x58,bank reg F0 FF 會印一行
BANK REG: 0xF0 (not persisted):後面那句提示代表這個設定不會被記到設定檔,
只在這次程式執行期間有效,關掉程式再重開就要重新下一次。兩種方式的效果相同,
選你順手的就好;但漏了任何一步的失敗方式不一樣:沒設定位址(位址預設是
0x00)會讓 i2c.bank() 真的送出交易、被裝置 NACK,錯誤是「bank switch
failed」;設定了位址、但沒設定頁碼暫存器,i2c.bank() 不會送出任何交易,
直接回報 bank not supported for this tab。
i2c.bank(n):切到第 n 頁
i2c.bank(2) -- 切到第 2 頁:把 2 寫進頁碼暫存器呼叫之後,程式會記住「現在在第 2 頁」,接下來的 i2c.read()/i2c.write()
存取的都是這一頁的內容;下次再呼叫 i2c.bank(其他數字) 才會換頁。跟前面
bank reg 一樣,這也不會被存進設定檔——道理相同,見上一節的說明。
範例:切兩次頁,各自讀回頁碼確認
-- 先設定 slave 位址,再設定 Bank 選擇暫存器——順序很重要:
-- i2c.addr() 若在 i2c.bank_reg() 之後呼叫,會把剛設好的 Bank 設定清掉。
i2c.addr(0x58)
i2c.bank_reg(0xF0, 0xFF) -- 0xF0 是頁碼暫存器,遮罩 0xFF 代表整個位元組都是頁碼
-- Bank(頁)切換:i2c.bank(n) 把頁碼寫進 Bank 選擇暫存器。
i2c.bank(2)
check(i2c.read(0xF0) == 2, "bank register reads back 2 after i2c.bank(2)")
i2c.bank(1)
check(i2c.read(0xF0) == 1, "bank register reads back 1 after i2c.bank(1)")
-- 腳本結束不會自動把晶片切回原本那一頁(只有位址/頁碼暫存器設定本身會還原),
-- 換過頁的腳本收尾前自己切回第 0 頁,避免影響接下來的操作。
i2c.bank(0)
log("info", "bank done")CHECK OK: bank register reads back 2 after i2c.bank(2)
CHECK OK: bank register reads back 1 after i2c.bank(1)
bank done範例讀的剛好就是頁碼暫存器本身(位移 0xF0),所以讀回來的值會等於剛剛切換的
頁碼——這是為了讓範例好驗證才這樣設計,實際使用時你會讀的通常是其他跟頁碼無關的
暫存器。範例結尾多呼叫了一次 i2c.bank(0),對應前面說過的「晶片實際停在哪一頁
不會自動還原」——這一步不影響範例本身的判定,純粹是收尾習慣。
接下來
下一頁介紹 delay_ms:怎麼讓腳本暫停等待,以及執行中怎麼把一支腳本停下來。