備電源管理實(shí)戰(zhàn))
做電池供電的便攜設(shè)備最煩人的往往不是業(yè)務(wù)代碼而是電源那一攤子事。以前我做一個(gè)小型手持項(xiàng)目光電源部分就用了三顆LDO、一顆升壓、一顆充電管理芯片再加上一堆分立MOS和RC延時(shí)電路PCB上密密麻麻全是電源布線(xiàn)的影子。后來(lái)?yè)Q成 PCA9422 和 PIC18F4610 這套組合——一顆多通道PMIC負(fù)責(zé)把電變出來(lái)、把電池充進(jìn)去一顆8位單片機(jī)負(fù)責(zé)說(shuō)“現(xiàn)在該用多少伏、該關(guān)哪一路”——電源板面積直接縮小一半待機(jī)功耗也更好控了。這篇文章就把這次完整電源管理項(xiàng)目的選型思路、硬件接法、固件狀態(tài)機(jī)和實(shí)測(cè)踩坑一次講透適合正在做手持表、便攜儀表、小型物聯(lián)網(wǎng)設(shè)備的開(kāi)發(fā)者。1. 先想清楚這對(duì)組合各負(fù)責(zé)哪塊供電活1.1 為什么不用一堆分立芯片拼很多人一提到電源管理第一反應(yīng)是“我需要幾路就放幾路電源芯片”。思路沒(méi)有錯(cuò)但等你真正做系統(tǒng)級(jí)設(shè)計(jì)問(wèn)題就來(lái)了。三路DCDC要三套電感、三個(gè)反饋分壓電阻還要考慮每一路的啟動(dòng)順序。充電部分單獨(dú)一顆芯片快充、恒流、截止邏輯全得靠MCU或比較器盯著。想給負(fù)載動(dòng)態(tài)調(diào)壓那基本是重新畫(huà)一塊板。分立方案的另一個(gè)痛點(diǎn)是待機(jī)功耗。普通DCDC在輕載下的靜態(tài)電流經(jīng)常到幾十上百微安幾路加起來(lái)一個(gè)本來(lái)設(shè)計(jì)成500uA待機(jī)的系統(tǒng)光電源芯片就吃掉一半預(yù)算。PCA9422這類(lèi)集成PMIC的好處在于內(nèi)部有多路BUCK和LDO還有專(zhuān)門(mén)的低功耗工作模式輕載時(shí)自動(dòng)進(jìn)入PFM整顆芯片的靜態(tài)功耗可以壓到比較低的水平系統(tǒng)級(jí)待機(jī)就很好做。再加上集成PMIC通常自帶充電管理、ADC采樣、中斷輸出和I2C寄存器控制面。供電、充電、電壓監(jiān)測(cè)、動(dòng)態(tài)調(diào)壓這些原本要靠五六顆芯片加一堆邏輯才能做的事現(xiàn)在一顆芯片加一個(gè)單片機(jī)就能全部覆蓋。硬件BOM減少組裝和測(cè)試成本也跟著降量產(chǎn)一致性比手工拼出來(lái)的方案好一截。1.2 兩者的分工硬件執(zhí)行 vs 策略大腦PCA9422負(fù)責(zé)的是“電力的物理變換”把電池電壓變成穩(wěn)定的多路電源軌給電池充電監(jiān)測(cè)電壓電流和溫度在出現(xiàn)過(guò)流、過(guò)溫時(shí)做硬件級(jí)保護(hù)。但這些行為具體怎么執(zhí)行給哪一路設(shè)定多少伏什么時(shí)候充電、什么時(shí)候切到低功耗需要一個(gè)大腦來(lái)決策。PIC18F4610在這里就是那個(gè)大腦。有人會(huì)覺(jué)得奇怪做個(gè)電源管理怎么還要上單片機(jī)其實(shí)不是“上單片機(jī)”而是很多系統(tǒng)本來(lái)就有一顆主控只是大多數(shù)時(shí)候它只顧著跑業(yè)務(wù)邏輯沒(méi)有把供電策略當(dāng)回事。把電源管理職責(zé)放到一顆老資格的8位單片機(jī)身上性?xún)r(jià)比很高。PIC18F4610有MSSP模塊可以做I2C主模式有10位ADC可以備份采樣電池電壓有EEPROM可以存校準(zhǔn)參數(shù)和日志有外部中斷引腳接PMIC的中斷輸出還有多種休眠模式配合低功耗。這些能力做電源策略完全夠用沒(méi)必要為了一個(gè)寄存器配置功能去上更高端的平臺(tái)。下面是這套系統(tǒng)里兩者的典型分工功能由誰(shuí)執(zhí)行說(shuō)明多路電壓輸出PCA9422三路Buck加一路LDO輸出由寄存器設(shè)定動(dòng)態(tài)調(diào)壓DVSPCA9422執(zhí)行PIC決策PIC寫(xiě)目標(biāo)電壓PMIC完成調(diào)壓電池充電PCA9422CC/CV過(guò)程由PMIC內(nèi)部邏輯完成充電策略PIC18F4610根據(jù)供電來(lái)源、電量、溫度決定充電電流和門(mén)限狀態(tài)切換PIC18F4610運(yùn)行、空閑、休眠、關(guān)斷的狀態(tài)機(jī)故障保護(hù)PCA9422硬件過(guò)流、過(guò)壓、過(guò)溫觸發(fā)硬件保動(dòng)同時(shí)中斷通知PIC電壓電流監(jiān)測(cè)PCA9422內(nèi)部ADCPIC可讀PIC讀取結(jié)果做軟件策略1.3 什么場(chǎng)景下這套方案才值得上不是說(shuō)所有項(xiàng)目都要用PMIC加MCU的組合。如果產(chǎn)品只需要一路3.3V降壓、負(fù)載固定、沒(méi)有電池一顆簡(jiǎn)單的LDO或DCDC反而是最優(yōu)解。但下面幾種情況我強(qiáng)烈建議直接參考這套架構(gòu)系統(tǒng)需要三路以上電源軌且不同運(yùn)行狀態(tài)下電壓要求不同產(chǎn)品帶單節(jié)鋰電池需要充電管理、電量監(jiān)測(cè)和充電狀態(tài)上報(bào)待機(jī)電流要求嚴(yán)格需要把部分電源軌在睡眠時(shí)關(guān)掉主核降到低電壓運(yùn)行需要遠(yuǎn)程或本地配置供電參數(shù)比如產(chǎn)線(xiàn)校準(zhǔn)、固件升級(jí)后修改電壓配置。我這次做的設(shè)備四條全占所以當(dāng)時(shí)基本沒(méi)猶豫就定了這個(gè)架構(gòu)。2. PCA9422硬件底細(xì)三路Buck、充電與I2C控制面2.1 一顆芯片里的“供電五臟”把PCA9422的框圖展開(kāi)看它基本就是一塊小型開(kāi)發(fā)板該有的電源系統(tǒng)全集。芯片內(nèi)部集成了三路同步降壓Buck轉(zhuǎn)換器每一路都可以通過(guò)I2C寄存器調(diào)節(jié)輸出電壓適合給主控核心、內(nèi)存、外設(shè)等不同功耗的負(fù)載供電。同步整流結(jié)構(gòu)讓輕載和滿(mǎn)載效率都能維持在比較高的水平不需要像非同步方案那樣外掛續(xù)流二極管。除了三路Buck芯片還有一路LDO輸出。這部分我一般用作“常電域”也就是關(guān)機(jī)后仍然需要保持供電的RTC或者是喚醒邏輯。LDO靜態(tài)電流小雖然效率不如Buck但它干凈、便宜、響應(yīng)快專(zhuān)門(mén)給低功耗的常開(kāi)電路供電很合適。充電部分支持單節(jié)鋰離子或鋰聚合物電池采用典型的恒流恒壓兩段式充電。芯片內(nèi)部可以設(shè)置充電電流、終止電流、充滿(mǎn)電壓以及輸入限流。比較關(guān)鍵的是芯片內(nèi)置了電源路徑管理適配器插入時(shí)系統(tǒng)優(yōu)先從適配器取電同時(shí)給電池充電適配器移除后自動(dòng)切到電池供電。這個(gè)功能在便攜設(shè)備里非常實(shí)用因?yàn)橛脩?hù)插拔充電器的瞬間系統(tǒng)不能斷電不能復(fù)位。I2C控制面是整套設(shè)計(jì)的核心。PCA9422作為I2C從機(jī)PIC作為主機(jī)通過(guò)讀寫(xiě)寄存器完成電壓設(shè)置、狀態(tài)查詢(xún)、中斷處理和充電參數(shù)配置。芯片還帶一個(gè)中斷輸出腳接PIC的外部中斷輸入這樣PMIC這邊一旦出現(xiàn)充電完成、電池低、過(guò)溫等事件PIC可以立刻得到通知不用輪詢(xún)。2.2 原理圖階段就要定下來(lái)的幾件事硬件設(shè)計(jì)里我吃過(guò)不少虧這里把踩坑總結(jié)成幾條經(jīng)驗(yàn)都是畫(huà)原理圖時(shí)就要確定的第一I2C上拉電阻和上拉電壓源的選擇。PCA9422的I2C引腳一般在1.2V到3.3V范圍內(nèi)工作上拉電阻要接到芯片允許的I/O電壓上而不是直接接到電池電壓??偩€(xiàn)速度按400kHz設(shè)計(jì)時(shí)常用的上拉值在2.2k到4.7k之間具體看總線(xiàn)上掛了多少器件、走線(xiàn)有多長(zhǎng)。如果總線(xiàn)上接了多顆芯片走線(xiàn)又長(zhǎng)4.7k往往不夠改用2.2k更穩(wěn)。第二中斷引腳一定要留出來(lái)。PCA9422的中斷腳通常是開(kāi)漏輸出需要外部上拉到合適的電平然后接到PIC的INT0或INT1。千萬(wàn)別省這根線(xiàn)否則后面所有狀態(tài)都靠輪詢(xún)系統(tǒng)響應(yīng)和低功耗都會(huì)很被動(dòng)。第三DVS控制引腳的設(shè)計(jì)。PCA9422支持通過(guò)I2C改電壓也支持通過(guò)外部引腳快速切換預(yù)置電壓檔。我的習(xí)慣是預(yù)留兩顆GPIO連到PIC方便以后做硬件級(jí)快速調(diào)壓。即使初期只在軟件里調(diào)壓原理圖上也把這兩個(gè)引腳引出來(lái)板子拿回來(lái)再想加就麻煩了。第四供電軌規(guī)劃。我給這套系統(tǒng)定的分配是Buck1給主控核心Buck2給存儲(chǔ)器和其他數(shù)字外設(shè)Buck3給模擬前端或者射頻部分LDO專(zhuān)門(mén)給RTC和喚醒邏輯。這樣分的好處是各路的負(fù)載相對(duì)固定調(diào)試時(shí)某一路電壓異常能立刻定位到具體功能模塊。布局布線(xiàn)方面Buck的電感屬于開(kāi)關(guān)節(jié)點(diǎn)要離I2C走線(xiàn)遠(yuǎn)一點(diǎn)反饋?zhàn)呔€(xiàn)避開(kāi)電感正下方。PMIC的輸入輸出電容按照數(shù)據(jù)手冊(cè)參考值來(lái)10uF加100nF的組合各軌都別省不然動(dòng)態(tài)響應(yīng)和紋波都會(huì)給你顏色看。3. PIC18F4610側(cè)初始化MSSP走I2C主模式的完整起手式3.1 先把I2C主模式跑起來(lái)PCA9422配置再?gòu)?qiáng)PIC這邊I2C驅(qū)動(dòng)寫(xiě)不好一切都是白搭。PIC18F4610的MSSP模塊配置成I2C主模式的流程比較固定關(guān)鍵是把模式、時(shí)鐘和引腳三件事搞對(duì)。MSSP的寄存器很多人在第一次接觸時(shí)容易暈實(shí)際要?jiǎng)拥木湍敲磶讉€(gè)SSPCON1決定模式和使能SSPADD決定時(shí)鐘頻率SSPCON2處理應(yīng)答和啟停控制SSPIF是中斷標(biāo)志。把模塊配置成I2C主模式SSPCON1的低四位寫(xiě)0b1000SSPEN位置1。時(shí)鐘頻率由振蕩器頻率分頻得到公式是SPADD (FOSC / 4) / I2C_FREQ - 1。下面是我在16MHz主頻、400kHz總線(xiàn)上用的初始化代碼可以直接抄#define FOSC 16000000UL #define I2C_FREQ 400000UL void i2c_master_init(void) { // SCL/SDA分別配置為輸入由MSSP模塊驅(qū)動(dòng) TRISCbits.TRISC3 1; // SCL TRISCbits.TRISC4 1; // SDA SSPCON1 0x28; // I2C主模式SSPEN1SSPM0b1000 SSPCON2 0x01; // ACKEN1允許應(yīng)答位控制 SSPADD (uint8_t)(((FOSC / 4) / I2C_FREQ) - 1); SSPSTAT 0x80; // 常規(guī)速率模式SMBus相關(guān)位保持清零 }寫(xiě)字節(jié)和啟停操作的核心是等SSPIF置位同時(shí)檢查ACKSTAT狀態(tài)。我封裝了一組底層函數(shù)讀寫(xiě)寄存器都靠它static void i2c_wait_until_done(void) { // 用一個(gè)計(jì)數(shù)器做超時(shí)避免總線(xiàn)異常時(shí)程序卡死 uint16_t timeout 0xFFFF; while (!PIR1bits.SSPIF timeout) { timeout--; } if (timeout 0) { // 總線(xiàn)異常做一次復(fù)位或者進(jìn)入錯(cuò)誤處理 i2c_bus_recover(); } PIR1bits.SSPIF 0; } uint8_t i2c_write_reg(uint8_t dev_addr, uint8_t reg, uint8_t val) { uint8_t rc; SSPCON2bits.SEN 1; // 發(fā)送啟動(dòng)條件 i2c_wait_until_done(); rc i2c_write_byte(dev_addr 1); // 7位地址左移一位寫(xiě)方向 if (rc I2C_NACK) return rc; rc i2c_write_byte(reg); if (rc I2C_NACK) return rc; rc i2c_write_byte(val); if (rc I2C_NACK) return rc; SSPCON2bits.PEN 1; // 發(fā)送停止條件 i2c_wait_until_done(); return I2C_OK; }讀寄存器稍微多一步先寫(xiě)寄存器地址然后發(fā)重復(fù)啟動(dòng)條件再切到讀方向讀回?cái)?shù)據(jù)并發(fā)送NACK作為最后一字節(jié)。這樣的讀流程在MSSP里很成熟網(wǎng)上資源也多就不貼完整代碼了。3.2 上電時(shí)序匹配先喂飽大腦再開(kāi)肌肉很多人上電就翻車(chē)問(wèn)題出在PIC和PMIC誰(shuí)先有電這件事上。我在原理圖階段把PIC的VDD接到了PCA9422的LDO輸出LDO由電池或適配器直接供電只要系統(tǒng)有電LDO就輸出穩(wěn)定3.3VPIC先跑起來(lái)。三路Buck默認(rèn)關(guān)閉由PIC在初始化完成后才逐個(gè)打開(kāi)。這樣既保證主控先于大功率負(fù)載就緒又避免了上電瞬間各路電源軌相互競(jìng)爭(zhēng)電流。PIC啟動(dòng)后的初始化流程我建議按這個(gè)順序延時(shí)10ms左右等LDO輸出穩(wěn)定、PMIC內(nèi)部電路完成復(fù)位配置I2C主模式和中斷引腳讀取PCA9422的芯片ID寄存器確認(rèn)通信正常。這個(gè)步驟別省等于握手能過(guò)濾掉一大批硬件虛焊問(wèn)題配置充電相關(guān)參數(shù)輸入限流、充電電流、充滿(mǎn)電壓、終止電流依次配置三路Buck的目標(biāo)電壓先設(shè)電壓再接使能打開(kāi)各電源軌的使能位每打開(kāi)一路延時(shí)一下確認(rèn)讀回的狀態(tài)寄存器正確關(guān)掉這條初始化用的I2C通道或者切換到低速率進(jìn)入正常業(yè)務(wù)。有朋友遇到過(guò)開(kāi)機(jī)瞬間整機(jī)電流特別大的現(xiàn)象后來(lái)發(fā)現(xiàn)是PIC一邊初始化I2C一邊又把大功率外設(shè)的GPIO拉起來(lái)了。正確做法是初始化完成前對(duì)外設(shè)保持復(fù)位狀態(tài)等Buck穩(wěn)定后再釋放復(fù)位。這個(gè)順序在固件里要寫(xiě)死不然每次上電都像在賭運(yùn)氣。4. 固件里的電源狀態(tài)機(jī)與充電流程4.1 我把狀態(tài)機(jī)拆成六檔電源管理固件的核心是一個(gè)狀態(tài)機(jī)不推薦在前臺(tái)循環(huán)里用一堆if去判斷電源狀態(tài)。我這次按運(yùn)行場(chǎng)景拆了六個(gè)狀態(tài)每個(gè)狀態(tài)定義清楚“哪些軌開(kāi)、電壓多少、CPU什么頻率、外設(shè)什么狀態(tài)”切換條件也集中管理。狀態(tài)Buck1Buck2Buck3LDO典型電流BOOT默認(rèn)電壓關(guān)閉關(guān)閉開(kāi)30mARUN1.2V1.8V3.3V開(kāi)80~200mAIDLE0.9V1.8V3.3V開(kāi)20mASLEEP關(guān)閉關(guān)閉3.3V開(kāi)3mAOFF關(guān)閉關(guān)閉關(guān)閉開(kāi)300uACHARGE默認(rèn)電壓按需按需開(kāi)依充電電流而定狀態(tài)切換的核心動(dòng)作就兩類(lèi)改一部份Buck電壓或者關(guān)閉某一路。DVS用得到位的話(huà)IDLE狀態(tài)把核心電壓從1.2V降到0.9V功耗能降不少而切換到RUN也只需一條I2C寫(xiě)指令。下面這個(gè)函數(shù)就是做這件事的void system_set_state(system_state_t next) { switch (next) { case STATE_IDLE: pmic_write_reg(REG_BUCK1_VOUT, 0x??); // 0.9V配置值 // 等待PMIC內(nèi)部調(diào)壓完成再繼續(xù)下一步 while (!pmic_read_reg(REG_STATUS) ST_BUCK1_OK); break; case STATE_RUN: pmic_write_reg(REG_BUCK1_VOUT, 0x??); // 1.2V配置值 while (!pmic_read_reg(REG_STATUS) ST_BUCK1_OK); break; case STATE_SLEEP: pmic_write_reg(REG_BUCK_EN, 0x??); // 關(guān)閉Buck1和Buck2 break; default: break; } current_state next; }寫(xiě)電壓寄存器的時(shí)候有一個(gè)細(xì)節(jié)目標(biāo)電壓值要折算成芯片要求的編碼格式很多PMIC的電壓步進(jìn)是10mV或者25mV不能直接把毫伏數(shù)寫(xiě)進(jìn)去。這個(gè)折算公式在數(shù)據(jù)手冊(cè)里有我會(huì)在頭文件里寫(xiě)一個(gè)宏或者轉(zhuǎn)換函數(shù)統(tǒng)一處理避免在業(yè)務(wù)代碼里到處出現(xiàn)魔法數(shù)字。4.2 充電管理別只寫(xiě)幾個(gè)寄存器就完事PCA9422的充電器硬件上很省心CC/CV過(guò)程由內(nèi)部邏輯完成PIC只需要做三件事配置參數(shù)、監(jiān)測(cè)狀態(tài)、處理異常。配置這塊我根據(jù)設(shè)備電池規(guī)格定了充電電壓4.2V充電電流0.5C終止電流設(shè)為滿(mǎn)充電流的十分之一左右。輸入限流要分場(chǎng)景接適配器時(shí)放高一點(diǎn)接普通電腦USB口時(shí)放低。這塊用一根檢測(cè)腳或者讀PMIC的輸入源狀態(tài)寄存器來(lái)判斷比在固件里硬編碼靠譜。充電過(guò)程中PIC要持續(xù)關(guān)注幾個(gè)中斷事件充電完成、充電失敗、電池低、溫度異常。我把PMIC的中斷輸出接到PIC的INT0引腳中斷服務(wù)函數(shù)里讀一次中斷狀態(tài)寄存器判斷事件類(lèi)型清標(biāo)志后做對(duì)應(yīng)處理void __interrupt() isr(void) { if (INT0IF) { uint8_t st pmic_read_reg(REG_INT_STATUS); if (st ST_CHARGE_DONE) { charge_done_flag 1; } if (st ST_VBAT_LOW) { system_set_state(STATE_SLEEP); } pmic_write_reg(REG_INT_STATUS, 0xFF); // 按手冊(cè)要求清中斷 INT0IF 0; } }有個(gè)細(xì)節(jié)容易被忽略中斷狀態(tài)寄存器讀完之后要主動(dòng)清除而且很多PMIC的清中斷方式是寫(xiě)1清除不能改成寫(xiě)0。如果清不干凈中斷腳會(huì)一直拉低PIC的中斷標(biāo)志也會(huì)反復(fù)觸發(fā)系統(tǒng)就像卡死在隨機(jī)位置。我在調(diào)試時(shí)吃了一次這個(gè)虧排查了半天才發(fā)現(xiàn)是清中斷語(yǔ)句寫(xiě)反了。4.3 低功耗狀態(tài)下輪詢(xún)就是敵人進(jìn)入OFF或SLEEP狀態(tài)后PIC最好進(jìn)入休眠用外部中斷喚醒。這時(shí)候如果繼續(xù)用定時(shí)器輪詢(xún)PMIC狀態(tài)不僅把CPU喚醒功耗吃掉了還讓系統(tǒng)電流憑空多出一截。我的做法是進(jìn)入低功耗狀態(tài)前把所有沒(méi)必要的定時(shí)器關(guān)掉I2C總線(xiàn)保持高電平不釋放PIC執(zhí)行SLEEP指令。喚醒來(lái)源只留三路PMIC中斷腳、喚醒按鍵、RTC定時(shí)喚醒。每次喚醒后用最快的速度讀一下PMIC狀態(tài)寄存器判斷要不要切狀態(tài)不需要處理就立刻再次睡眠。這樣整個(gè)系統(tǒng)在OFF狀態(tài)的實(shí)測(cè)電流能穩(wěn)定在300uA上下比我最初設(shè)計(jì)預(yù)算的500uA還要好。5. 實(shí)測(cè)排坑輸出電壓、I2C應(yīng)答和DVS毛刺5.1 第一個(gè)坑寫(xiě)完電壓寄存器輸出還是默認(rèn)值樣機(jī)第一次上電I2C通信正常芯片ID也讀回來(lái)了但用示波器量Buck1輸出紋絲不動(dòng)是默認(rèn)的1.0V我明明寫(xiě)了0x配置值想讓它輸出1.2V。排查鏈路是這樣的先檢查代碼里配置值是不是算錯(cuò)把寄存器讀回打印出來(lái)發(fā)現(xiàn)寫(xiě)入的值沒(méi)錯(cuò)。然后懷疑是不是使能位沒(méi)置位把使能寄存器整個(gè)讀回來(lái)發(fā)現(xiàn)Buck1的狀態(tài)是“使能但未就緒”。最后定位到原因我在初始化時(shí)先寫(xiě)了輸出電壓寄存器再寫(xiě)的使能寄存器但中間沒(méi)有等電壓穩(wěn)壓完成而PMIC對(duì)于“使能狀態(tài)下修改電壓”有一套影子寄存器機(jī)制某些字段需要在特定條件下才會(huì)更新到硬件。解決辦法是嚴(yán)格按數(shù)據(jù)手冊(cè)的時(shí)序來(lái)先降低寫(xiě)入節(jié)奏每寫(xiě)一個(gè)寄存器后延時(shí)再讀回驗(yàn)證打開(kāi)使能后查詢(xún)電源正常狀態(tài)位確認(rèn)穩(wěn)壓完成再繼續(xù)。從那以后我把“寫(xiě)地址-寫(xiě)數(shù)據(jù)-讀回-比對(duì)”這個(gè)三步校驗(yàn)做成了所有PMIC寄存器寫(xiě)入的標(biāo)準(zhǔn)流程實(shí)測(cè)下來(lái)通信異?;径际怯布?wèn)題而不是代碼問(wèn)題了。5.2 第二個(gè)坑I2C偶發(fā)無(wú)應(yīng)答加1ms延時(shí)又好了系統(tǒng)跑起來(lái)之后出現(xiàn)了一個(gè)特別邪門(mén)的現(xiàn)象I2C通信大部分時(shí)間正常偶爾一次讀充電狀態(tài)時(shí)返回NACK加了1ms延時(shí)之后又好了。這種隨機(jī)故障最折磨人因?yàn)樗粫?huì)穩(wěn)定復(fù)現(xiàn)。我懷疑過(guò)三件事總線(xiàn)電容太大、上拉電阻阻值太高、MSSP速率過(guò)快。先用邏輯分析儀抓波形發(fā)現(xiàn)SDA在啟動(dòng)條件后有一處明顯的邊沿變緩加上總線(xiàn)還掛了另一顆傳感器總電容確實(shí)偏大了。處理辦法是換上拉電阻從4.7k降到2.2k同時(shí)把I2C速率從400kHz降到100kHz壞幀率直接從“偶爾一次”變成“一次都沒(méi)有”。這里也想提醒大家I2C線(xiàn)上跑著多顆芯片、走線(xiàn)又長(zhǎng)時(shí)別迷信400kHz的“標(biāo)準(zhǔn)速率”。對(duì)電源管理這種低頻控制場(chǎng)景100kHz完全夠用穩(wěn)定性卻高一個(gè)數(shù)量級(jí)。我后來(lái)把I2C速率固定在100kHz運(yùn)行幾個(gè)月沒(méi)再出現(xiàn)通信故障。5.3 第三個(gè)坑DVS調(diào)低電壓系統(tǒng)反而復(fù)位數(shù)動(dòng)態(tài)調(diào)壓看起來(lái)很美但我在把核心電壓從1.2V降到0.9V的時(shí)候系統(tǒng)卻偶發(fā)復(fù)位。這位復(fù)位不是掉電引起的因?yàn)長(zhǎng)DO供電的常電域沒(méi)掉復(fù)位的只有主核心域。逐層分析后發(fā)現(xiàn)DVS調(diào)低電壓的瞬間主控還掛著比較重的負(fù)載電壓從一個(gè)臺(tái)階跳到另一個(gè)臺(tái)階如果PMIC的調(diào)壓速度很快而負(fù)載電流還沒(méi)來(lái)得及降下來(lái)瞬時(shí)電壓可能跌到低于主控最低工作電壓觸發(fā)了內(nèi)置的掉電復(fù)位。解決思路分兩步。第一步軟件上先讓負(fù)載進(jìn)入輕載模式再降電壓把主控時(shí)鐘降下來(lái)關(guān)閉不需要的外設(shè)然后再寫(xiě)電壓寄存器。第二步如果PMIC支持調(diào)壓速率配置把調(diào)壓斜率調(diào)緩一點(diǎn)讓電壓平滑過(guò)渡。硬件上我在Buck1的輸出再加了一顆22uF的陶瓷電容增加一點(diǎn)瞬態(tài)裕量從那之后這個(gè)復(fù)位再?zèng)]出現(xiàn)過(guò)。這套“先降負(fù)載、再調(diào)電壓、確認(rèn)完成、再恢復(fù)負(fù)載”的流程現(xiàn)在已經(jīng)成為我所有DVS項(xiàng)目的標(biāo)配。5.4 順帶說(shuō)說(shuō)低功耗實(shí)測(cè)方法很多朋友問(wèn)低功耗怎么測(cè)才能測(cè)準(zhǔn)我的經(jīng)驗(yàn)是不要只看數(shù)據(jù)手冊(cè)要實(shí)際用電流探頭在供電入口測(cè)。開(kāi)機(jī)狀態(tài)下600uA以下用普通萬(wàn)用表串聯(lián)測(cè)是可以的但休眠狀態(tài)300uA左右時(shí)萬(wàn)用表的壓降已經(jīng)會(huì)影響系統(tǒng)供電了最好用電流探頭加示波器或者用專(zhuān)門(mén)的功耗分析儀。測(cè)的時(shí)候還要把I2C訪(fǎng)問(wèn)的頻率降下來(lái)。我最初調(diào)試時(shí),SLEEP狀態(tài)下PIC雖然休眠了,但I(xiàn)2C引腳沒(méi)有完全釋放每一段時(shí)間還有個(gè)泄漏路徑。逐個(gè)外設(shè)排除時(shí)用了一個(gè)簡(jiǎn)單方法把每個(gè)外設(shè)的供電都改成獨(dú)立跳線(xiàn)測(cè)功耗時(shí)一根一根跳線(xiàn)拔掉看電流變化。這套方法雖然土但定位快最終把系統(tǒng)待機(jī)從2mA降到了300uA。最后再分享一個(gè)小技巧整套方案調(diào)通之后建議在固件里加一個(gè)調(diào)試模式通過(guò)PMIC的ADC把各路電壓、充電電流、溫度實(shí)時(shí)上報(bào)。這個(gè)模式平時(shí)不開(kāi)啟但出問(wèn)題時(shí)能幫你少焊很多飛線(xiàn)和少測(cè)很多點(diǎn)。我自己在后續(xù)項(xiàng)目里保留了這套架構(gòu)還打算把DVS的調(diào)壓曲線(xiàn)做成自動(dòng)標(biāo)定讓產(chǎn)線(xiàn)可以根據(jù)每臺(tái)設(shè)備的個(gè)體差異微調(diào)電壓配置真正做到每一臺(tái)都工作在最優(yōu)功耗點(diǎn)上。