計(jì)與實(shí)現(xiàn))
1. 項(xiàng)目緣起與整體設(shè)計(jì)思路搞嵌入式的人都有一個(gè)共識(shí)電源管理是那種平時(shí)沒(méi)人注意、一旦出問(wèn)題就讓人通宵的存在。我手頭這個(gè)項(xiàng)目核心就是用 PCA9422 這顆電源管理芯片搭配 ATmega32A 這顆經(jīng)典 8 位 MCU搭一套完整的電源管理方案。說(shuō)白了就是讓 ATmega32A 通過(guò) I2C 總線去配置和控制 PCA9422實(shí)現(xiàn)多路電壓輸出、上電時(shí)序控制、低功耗模式切換以及電池充放電管理這一整套功能。為什么選這個(gè)組合先說(shuō) PCA9422它是一顆高度集成的電源管理 IC內(nèi)部集成了多個(gè)降壓轉(zhuǎn)換器、LDO、充電器模塊和 ADC支持通過(guò) I2C 接口動(dòng)態(tài)調(diào)節(jié)輸出電壓和讀取系統(tǒng)狀態(tài)。對(duì)于需要多路供電軌的便攜設(shè)備來(lái)說(shuō)一顆芯片就能替代原來(lái)一堆分立電源器件PCB 面積和 BOM 成本都能壓下來(lái)。而 ATmega32A 雖然是一顆老牌 8 位 MCU但它的優(yōu)勢(shì)在于生態(tài)成熟、資料豐富、I2C 硬件外設(shè)穩(wěn)定用來(lái)做電源管理的主控綽綽有余——電源管理本身不需要多強(qiáng)的算力需要的是穩(wěn)定和低功耗。這套方案解決的核心問(wèn)題是在一個(gè)由單節(jié)鋰離子電池供電的便攜設(shè)備中如何用最少的器件實(shí)現(xiàn)多路電壓輸出、精確的上電/掉電時(shí)序、以及智能的功耗模式切換。適合誰(shuí)來(lái)參考我覺(jué)得是那些正在做便攜式數(shù)據(jù)采集設(shè)備、手持儀器、或者電池供電的工業(yè)控制終端的嵌入式工程師。如果你之前只用過(guò)簡(jiǎn)單的 LDO 或者單一的 DC-DC想升級(jí)到一套完整的電源管理架構(gòu)這個(gè)項(xiàng)目會(huì)是一個(gè)很好的起點(diǎn)。整體設(shè)計(jì)思路是這樣的ATmega32A 作為主控負(fù)責(zé)系統(tǒng)的主邏輯同時(shí)通過(guò) I2C 總線與 PCA9422 通信。PCA9422 負(fù)責(zé)所有電源相關(guān)的硬件操作——電池充電、電壓轉(zhuǎn)換、電壓監(jiān)測(cè)。ATmega32A 定期讀取 PCA9422 的狀態(tài)寄存器根據(jù)電池電壓、系統(tǒng)負(fù)載情況動(dòng)態(tài)調(diào)整各路輸出電壓或者在系統(tǒng)空閑時(shí)切換到低功耗模式。兩者分工明確PCA9422 管“電”ATmega32A 管“智”。注意PCA9422 的 I2C 地址和寄存器映射在不同批次或配置下可能有差異動(dòng)手前務(wù)必對(duì)照具體型號(hào)的數(shù)據(jù)手冊(cè)確認(rèn)不要直接照搬網(wǎng)上的例程。這個(gè)架構(gòu)的好處在于電源管理邏輯全部集中在 MCU 固件中硬件電路相對(duì)固定后期如果要調(diào)整上電時(shí)序或者電壓閾值改固件就行不用動(dòng) PCB。對(duì)于產(chǎn)品迭代來(lái)說(shuō)這一點(diǎn)非常關(guān)鍵。2. 核心器件解析與硬件設(shè)計(jì)要點(diǎn)2.1 PCA9422 的關(guān)鍵特性與引腳配置PCA9422 是一顆面向便攜應(yīng)用的電源管理芯片內(nèi)部集成了以下主要模塊兩個(gè)高效降壓轉(zhuǎn)換器Buck輸出電壓可通過(guò) I2C 動(dòng)態(tài)調(diào)節(jié)多個(gè) LDO用于給低噪聲模擬電路供電一個(gè)線性充電器支持單節(jié)鋰離子電池充電一個(gè) 8 位 ADC用于監(jiān)測(cè)電池電壓和各路輸出電壓以及一個(gè) I2C 從機(jī)接口最高支持 400kHz 通信速率。引腳配置上需要重點(diǎn)關(guān)注以下幾組VIN 和 VBAT 是輸入電源引腳VIN 接適配器或 USB 供電VBAT 接電池SW1 和 SW2 是兩路 Buck 的開(kāi)關(guān)節(jié)點(diǎn)需要接電感和電容SDA 和 SCL 是 I2C 通信線需要上拉電阻INT 是中斷輸出引腳可以連接到 MCU 的外部中斷輸入用于事件通知。我在實(shí)際布線時(shí)踩過(guò)一個(gè)坑SW 節(jié)點(diǎn)的走線一定要短而粗電感盡量靠近芯片放置否則開(kāi)關(guān)噪聲會(huì)耦合到 ADC 采樣通道導(dǎo)致電池電壓讀數(shù)跳動(dòng)。這個(gè)細(xì)節(jié)在數(shù)據(jù)手冊(cè)里只是輕描淡寫提了一句但實(shí)際影響很大。2.2 ATmega32A 的 I2C 外設(shè)配置ATmega32A 的 TWITwo-Wire Interface外設(shè)就是它的 I2C 硬件模塊。配置步驟大致如下首先設(shè)置 TWSR 寄存器選擇預(yù)分頻值然后設(shè)置 TWBR 寄存器確定 SCL 頻率。計(jì)算公式是SCL頻率 F_CPU / (16 2 * TWBR * 4^TWPS)假設(shè) F_CPU 為 8MHz想要 100kHz 的 SCL 頻率TWPS 取 0預(yù)分頻 1則 TWBR (8MHz / 100kHz - 16) / 2 32。如果要用 400kHzTWBR (8MHz / 400kHz - 16) / 2 6。實(shí)際配置時(shí)我建議先用 100kHz 調(diào)通通信確認(rèn)讀寫正常后再嘗試提高到 400kHz。因?yàn)?PCA9422 的 I2C 時(shí)序?qū)ι仙赜幸欢ㄒ笕绻侠娮柽x得太大高速通信時(shí)波形會(huì)變緩導(dǎo)致通信失敗。上拉電阻一般選 4.7kΩ 到 10kΩ 之間總線電容大的話選小一些。提示ATmega32A 的 TWI 狀態(tài)碼非常多建議把 TWSR 的高 5 位狀態(tài)碼做成一個(gè)枚舉或者宏定義在代碼里用 switch-case 處理比直接比較十六進(jìn)制數(shù)可讀性好得多。2.3 外圍電路選型與參數(shù)計(jì)算電感選型是 Buck 電路設(shè)計(jì)的核心。PCA9422 的 Buck 開(kāi)關(guān)頻率典型值為 2MHz電感值一般選 1μH 到 2.2μH。計(jì)算電感紋波電流的公式是ΔIL (Vout * (1 - Vout/Vin)) / (fsw * L)假設(shè) Vin 3.7V電池典型電壓Vout 1.8Vfsw 2MHzL 1.5μH則 ΔIL (1.8 * (1 - 1.8/3.7)) / (2e6 * 1.5e-6) 0.31A。一般希望紋波電流在輸出電流的 20% 到 40% 之間如果輸出電流是 1A那 0.31A 的紋波是合理的。輸出電容方面建議用低 ESR 的陶瓷電容容值在 10μF 到 22μF 之間。輸入電容同樣重要要放在 VIN 引腳附近容值建議 10μF 以上用于吸收開(kāi)關(guān)瞬間的電流尖峰。電池充電電流的設(shè)定通過(guò)一個(gè)外部電阻來(lái)完成。PCA9422 的充電電流公式通常是 ICHG K / RISET其中 K 是一個(gè)常數(shù)具體值查數(shù)據(jù)手冊(cè)。假設(shè) K 1500想要 500mA 充電電流則 RISET 1500 / 500 3kΩ。這個(gè)電阻的精度直接影響充電電流的準(zhǔn)確性建議用 1% 精度的電阻。3. 固件架構(gòu)與核心功能實(shí)現(xiàn)3.1 I2C 驅(qū)動(dòng)層封裝固件的第一層是 I2C 驅(qū)動(dòng)。我把它封裝成三個(gè)基本函數(shù)I2C_Init()、I2C_WriteReg()和I2C_ReadReg()。I2C_Init()負(fù)責(zé)配置 TWI 的時(shí)鐘和使能I2C_WriteReg()完成“起始條件 從機(jī)地址 寫 寄存器地址 數(shù)據(jù) 停止條件”的完整流程I2C_ReadReg()則完成“起始條件 從機(jī)地址 寫 寄存器地址 重復(fù)起始條件 從機(jī)地址 讀 數(shù)據(jù) 停止條件”的流程。這里有一個(gè)容易忽略的點(diǎn)ATmega32A 的 TWI 在發(fā)送重復(fù)起始條件時(shí)需要先清除 TWINT 標(biāo)志然后設(shè)置 TWSTA 位再設(shè)置 TWINT 位。順序搞錯(cuò)的話總線會(huì)卡死。我在調(diào)試時(shí)遇到過(guò)這個(gè)問(wèn)題后來(lái)在代碼里加了一個(gè)超時(shí)計(jì)數(shù)器如果某個(gè)狀態(tài)等待超過(guò)一定時(shí)間就復(fù)位 TWI避免死鎖。uint8_t I2C_WriteReg(uint8_t devAddr, uint8_t regAddr, uint8_t data) { uint16_t timeout; // 發(fā)送起始條件 TWCR (1 TWINT) | (1 TWSTA) | (1 TWEN); timeout 0; while (!(TWCR (1 TWINT))) { if (timeout 10000) return 1; // 超時(shí) } // 檢查狀態(tài)碼發(fā)送從機(jī)地址寫 TWDR (devAddr 1) | 0; TWCR (1 TWINT) | (1 TWEN); timeout 0; while (!(TWCR (1 TWINT))) { if (timeout 10000) return 2; } // 發(fā)送寄存器地址 TWDR regAddr; TWCR (1 TWINT) | (1 TWEN); timeout 0; while (!(TWCR (1 TWINT))) { if (timeout 10000) return 3; } // 發(fā)送數(shù)據(jù) TWDR data; TWCR (1 TWINT) | (1 TWEN); timeout 0; while (!(TWCR (1 TWINT))) { if (timeout 10000) return 4; } // 發(fā)送停止條件 TWCR (1 TWINT) | (1 TWSTO) | (1 TWEN); return 0; }3.2 PCA9422 初始化流程上電后ATmega32A 需要按順序初始化 PCA9422。第一步是讀取芯片 ID 寄存器確認(rèn)通信正常。第二步是配置充電器參數(shù)包括充電電流、充電終止電壓、預(yù)充電電流等。第三步是配置各路 Buck 和 LDO 的輸出電壓。第四步是設(shè)置上電時(shí)序確保各路電壓按正確的順序啟動(dòng)。上電時(shí)序?yàn)槭裁粗匾驗(yàn)橛行┴?fù)載芯片要求核心電壓先于 IO 電壓建立如果順序反了可能會(huì)導(dǎo)致芯片內(nèi)部寄生二極管導(dǎo)通產(chǎn)生大電流甚至損壞器件。PCA9422 支持通過(guò)寄存器配置每路輸出的啟動(dòng)延遲我一般把核心電壓設(shè)為最先啟動(dòng)IO 電壓延遲 2ms 到 5ms 再啟動(dòng)。初始化代碼的結(jié)構(gòu)大致如下void PMIC_Init(void) { // 確認(rèn)芯片ID uint8_t chipId I2C_ReadReg(PCA9422_ADDR, PCA9422_REG_CHIP_ID); if (chipId ! PCA9422_EXPECTED_ID) { // 通信異常處理 return; } // 配置充電器 I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_CHG_CURRENT, CHG_CURRENT_500MA); I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_CHG_VTERM, CHG_VTERM_4V2); // 配置Buck1輸出1.8V I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_BUCK1_VOUT, BUCK1_VOUT_1V8); // 配置Buck2輸出3.3V I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_BUCK2_VOUT, BUCK2_VOUT_3V3); // 配置上電時(shí)序 I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_SEQ_DELAY1, SEQ_DELAY_2MS); I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_SEQ_DELAY2, SEQ_DELAY_5MS); // 使能各路輸出 I2C_WriteReg(PCA9422_ADDR, PCA9422_REG_ENABLE, 0x03); }3.3 電池電壓監(jiān)測(cè)與低電量處理PCA9422 內(nèi)部的 ADC 可以測(cè)量電池電壓結(jié)果存放在一個(gè) 8 位寄存器中。ATmega32A 定期讀取這個(gè)寄存器換算成實(shí)際電壓值。換算公式一般是Vbat ADC_CODE * VREF / 255其中 VREF 是 ADC 的參考電壓具體值查數(shù)據(jù)手冊(cè)。假設(shè) VREF 5.0VADC_CODE 180則 Vbat 180 * 5.0 / 255 ≈ 3.53V。根據(jù)電池電壓系統(tǒng)可以做出不同響應(yīng)電壓高于 3.6V 時(shí)正常工作電壓在 3.3V 到 3.6V 之間時(shí)降低屏幕亮度或關(guān)閉非必要外設(shè)電壓低于 3.3V 時(shí)保存關(guān)鍵數(shù)據(jù)并進(jìn)入休眠模式電壓低于 3.0V 時(shí)切斷負(fù)載只保留充電器工作。這里有一個(gè)經(jīng)驗(yàn)電池電壓在帶負(fù)載時(shí)會(huì)比空載時(shí)低不少因?yàn)殡姵赜袃?nèi)阻。如果只看帶載電壓來(lái)判斷電量可能會(huì)提前觸發(fā)低電量保護(hù)。我的做法是在 ADC 讀取前短暫關(guān)閉大電流負(fù)載等 10ms 再采樣這樣讀到的電壓更接近真實(shí)的開(kāi)路電壓。3.4 低功耗模式切換策略ATmega32A 本身支持多種睡眠模式包括 IDLE、ADC Noise Reduction、Power-save、Power-down 等。配合 PCA9422 的低功耗模式可以進(jìn)一步降低系統(tǒng)功耗。具體策略是這樣的當(dāng)系統(tǒng)檢測(cè)到一段時(shí)間內(nèi)沒(méi)有用戶操作時(shí)首先通過(guò) I2C 通知 PCA9422 關(guān)閉不用的電源軌比如傳感器供電、顯示屏背光等。然后 ATmega32A 關(guān)閉不用的外設(shè)時(shí)鐘進(jìn)入 Power-save 模式。此時(shí)系統(tǒng)電流可以從幾十毫安降到幾百微安。如果長(zhǎng)時(shí)間沒(méi)有事件PCA9422 可以進(jìn)入待機(jī)模式進(jìn)一步降低靜態(tài)電流。喚醒方式有兩種一是 PCA9422 的 INT 引腳觸發(fā) ATmega32A 的外部中斷比如充電器插入或者按鍵按下二是 ATmega32A 的看門狗定時(shí)器周期性喚醒檢查系統(tǒng)狀態(tài)。注意進(jìn)入 Power-down 模式前一定要確保 I2C 總線處于空閑狀態(tài)否則喚醒后 TWI 可能無(wú)法正常工作。我遇到過(guò)因?yàn)檫M(jìn)入睡眠時(shí) I2C 傳輸未完成導(dǎo)致喚醒后總線死鎖的情況后來(lái)在睡眠前加了一個(gè)總線空閑檢測(cè)才解決。4. 實(shí)操調(diào)試與問(wèn)題排查實(shí)錄4.1 上電后 I2C 通信失敗這是最常見(jiàn)的問(wèn)題。現(xiàn)象是 ATmega32A 發(fā)送起始條件后一直等不到 TWINT 置位或者狀態(tài)碼顯示從機(jī)沒(méi)有應(yīng)答。排查思路按以下順序來(lái)第一用示波器看 SDA 和 SCL 是否有波形如果沒(méi)有檢查上拉電阻是否焊接、MCU 的 TWI 是否使能。第二如果有波形但從機(jī)不應(yīng)答檢查 PCA9422 的供電是否正常VIN 和 VBAT 是否都有電壓。第三確認(rèn) I2C 地址是否正確PCA9422 的地址可能由某個(gè)引腳的電平?jīng)Q定讀一下數(shù)據(jù)手冊(cè)確認(rèn)。第四檢查 SCL 頻率是否過(guò)高先把 TWBR 設(shè)大一些降到 50kHz 試試。我遇到過(guò)一次是因?yàn)?PCA9422 的使能引腳沒(méi)有拉高芯片根本沒(méi)工作自然不應(yīng)答。這個(gè)引腳在原理圖上很容易被忽略建議在 PCB 上留一個(gè)測(cè)試點(diǎn)方便調(diào)試時(shí)測(cè)量。4.2 輸出電壓不穩(wěn)定或紋波過(guò)大如果示波器測(cè)量輸出電壓發(fā)現(xiàn)紋波超過(guò) 50mV可以從以下幾個(gè)方面排查電感值是否合適飽和電流是否足夠輸出電容的 ESR 是否過(guò)大建議換低 ESR 的陶瓷電容SW 節(jié)點(diǎn)的走線是否太長(zhǎng)導(dǎo)致輻射噪聲負(fù)載電流是否超過(guò)了 Buck 的最大輸出能力。有一次我用的電感飽和電流只有 500mA而實(shí)際負(fù)載峰值到了 800mA結(jié)果電感飽和輸出電壓直接掉下來(lái)。后來(lái)?yè)Q了一個(gè)飽和電流 1.5A 的電感問(wèn)題解決。所以選電感時(shí)飽和電流至少要是最大負(fù)載電流的 1.5 倍。4.3 電池充電異常充電異常的表現(xiàn)有多種完全不充電、充電電流偏小、充電指示燈不亮等。排查時(shí)先測(cè)量 RISET 電阻的阻值是否正確然后讀取 PCA9422 的充電狀態(tài)寄存器看芯片是否進(jìn)入了充電模式。如果芯片溫度過(guò)高可能會(huì)觸發(fā)過(guò)熱保護(hù)暫停充電。另外電池電壓過(guò)低時(shí)芯片會(huì)先進(jìn)入預(yù)充電模式用小電流把電池電壓抬升到安全范圍再切換到恒流充電。如果電池過(guò)放預(yù)充電階段可能會(huì)持續(xù)較長(zhǎng)時(shí)間這是正?,F(xiàn)象。4.4 常見(jiàn)問(wèn)題速查表問(wèn)題現(xiàn)象可能原因排查方法解決措施I2C 無(wú)應(yīng)答從機(jī)地址錯(cuò)誤用邏輯分析儀抓包核對(duì)數(shù)據(jù)手冊(cè)地址I2C 無(wú)應(yīng)答上拉電阻缺失萬(wàn)用表測(cè) SDA/SCL 對(duì) VCC 阻值補(bǔ)焊 4.7kΩ 上拉輸出電壓偏低電感飽和測(cè) SW 波形是否畸變換大飽和電流電感紋波過(guò)大輸出電容 ESR 高換電容對(duì)比測(cè)試改用陶瓷電容充電電流小RISET 阻值偏大測(cè)量電阻值換正確阻值電阻系統(tǒng)功耗高未關(guān)閉外設(shè)時(shí)鐘逐個(gè)關(guān)閉外設(shè)測(cè)電流優(yōu)化睡眠前配置喚醒后死機(jī)I2C 總線未空閑睡眠前讀 TWSR加總線空閑檢測(cè)ADC 讀數(shù)跳動(dòng)開(kāi)關(guān)噪聲耦合示波器看電源紋波加 RC 濾波或遠(yuǎn)離 SW 節(jié)點(diǎn)4.5 幾個(gè)實(shí)用的調(diào)試技巧第一個(gè)技巧在 I2C 總線上掛一個(gè)邏輯分析儀比用示波器看波形方便得多。邏輯分析儀可以直接解碼出地址、數(shù)據(jù)和 ACK/NACK一眼就能看出問(wèn)題出在哪一幀。第二個(gè)技巧PCA9422 的寄存器很多建議做一個(gè)寄存器配置表把每個(gè)寄存器的地址、位定義、默認(rèn)值、配置值都列出來(lái)調(diào)試時(shí)對(duì)照檢查避免漏配或錯(cuò)配。第三個(gè)技巧測(cè)量系統(tǒng)功耗時(shí)用高精度的電流表或者帶電流測(cè)量功能的電源不要用萬(wàn)用表的電流檔因?yàn)槿f(wàn)用表的采樣率太低測(cè)不到瞬態(tài)電流變化。第四個(gè)技巧如果系統(tǒng)中有多個(gè) I2C 從機(jī)確保它們的地址不沖突。PCA9422 的地址通??梢酝ㄟ^(guò) ADDR 引腳調(diào)整如果和其他器件沖突改一下引腳電平就行。5. 方案優(yōu)化與擴(kuò)展思路5.1 提高電壓調(diào)節(jié)精度PCA9422 的輸出電壓通過(guò)寄存器調(diào)節(jié)步進(jìn)通常是 25mV 或 50mV。如果應(yīng)用對(duì)電壓精度要求更高可以在輸出端加一個(gè)高精度的 LDO 進(jìn)行二次穩(wěn)壓或者用外部電阻分壓網(wǎng)絡(luò)配合 ADC 做閉環(huán)調(diào)節(jié)。不過(guò)對(duì)于大多數(shù)數(shù)字電路來(lái)說(shuō)PCA9422 本身的精度已經(jīng)足夠了。5.2 增加溫度監(jiān)測(cè)與保護(hù)PCA9422 內(nèi)部有溫度傳感器可以讀取芯片溫度。在固件中增加溫度監(jiān)測(cè)邏輯當(dāng)溫度超過(guò)閾值時(shí)主動(dòng)降低充電電流或者關(guān)閉部分電源軌可以提升系統(tǒng)的可靠性。這個(gè)功能在密閉外殼或者高溫環(huán)境下特別有用。5.3 固件升級(jí)與參數(shù)存儲(chǔ)電源管理的參數(shù)比如各路輸出電壓、充電電流、保護(hù)閾值可以存儲(chǔ)在 ATmega32A 的 EEPROM 中。這樣即使固件升級(jí)參數(shù)也不會(huì)丟失。更進(jìn)一步可以通過(guò)通信接口接收新的參數(shù)配置實(shí)現(xiàn)遠(yuǎn)程調(diào)整電源策略。5.4 多節(jié)電池串聯(lián)的擴(kuò)展如果需要更高的系統(tǒng)電壓可以考慮多節(jié)電池串聯(lián)的方案。不過(guò) PCA9422 主要面向單節(jié)電池應(yīng)用多節(jié)方案需要選擇支持更高輸入電壓的 PMIC或者外加平衡充電電路。這個(gè)擴(kuò)展方向需要重新選型和設(shè)計(jì)不在當(dāng)前方案的直接覆蓋范圍內(nèi)。我在實(shí)際使用中發(fā)現(xiàn)這套 PCA9422 加 ATmega32A 的組合最大的優(yōu)勢(shì)是靈活。硬件一旦定型后續(xù)所有的電源策略調(diào)整都可以通過(guò)固件完成。對(duì)于小批量、多品種的產(chǎn)品線來(lái)說(shuō)這意味著可以用同一套硬件平臺(tái)覆蓋不同的產(chǎn)品需求庫(kù)存管理和生產(chǎn)切換都簡(jiǎn)單很多。踩過(guò)幾次坑之后我養(yǎng)成了一個(gè)習(xí)慣每次修改電源配置后都用邏輯分析儀抓一遍 I2C 波形確認(rèn)所有寄存器都按預(yù)期寫入然后再進(jìn)行下一步測(cè)試。這個(gè)習(xí)慣幫我避免了很多因?yàn)榕渲眠z漏導(dǎo)致的奇怪問(wèn)題。