一块新出的 Nucleo 板(Zephyr 官方还没有支持)+ MPS 的 140W 升降压评估板,摇杆调压、LCD 数显、I2C 全数字控制——从 BSP 移植到成品电源的全过程记录。
一、EVL4248-QV-00A 评估板简介
EVL4248-QV-00A 是 MPS 的数字电源评估板,核心是一片 MP4248GQV:四开关 Buck-Boost 变换器 + I2C(PMBus)数字接口。
| 拓扑 | 四开关 Buck-Boost(集成下管 MOSFET) |
| 输入 VIN | 3.6V ~ 36V |
| 输出 VOUT | 1V ~ 36V(±1%),出厂默认 5V |
| 电流 | 默认 CC 限流 5.4A(改采样电阻可到 7A) |
| 峰值功率 | 140W(VIN>19V 时可 28V/5A) |
| 开关频率 | 280/420/580kHz 可选(默认 420kHz) |
| 峰值效率 | 97.97%(12V→15V@2.5A) |
| 数字接口 | I2C(PMBus),从机地址 0x67,带 ALT 告警脚 |
| 尺寸 | 60×60×10mm,4 层板 |
一个重要特性(决定整机设计):芯片 OTP 配置"上电即输出"——VIN 一接上就自动输出约 5V,软件拦不住。所以"配置好再输出"要在输出级加开关(本文用 OPERATION 寄存器软开关 + 预留 EN 硬关断)。
二、控制引脚与反馈引脚
| CN2: SCL/SDA/GND | MCU⇄芯片 | I2C(PMBus)控制通道 | 地址 0x67,板载 2.2kΩ 上拉,3.3V 电平兼容,最高 1MHz。注意:VIN+EN 都有效时 I2C 才工作 |
| EN | MCU→芯片 | 硬使能(阈值 1.22V) | 板上 100kΩ 上拉到 VIN(默认自启动);EN 低时 I2C 也失效 |
| ALT(CN1-1) | 芯片→MCU | 开漏告警输出 | 事件可经 0xD8 掩码配置,接 MCU 中断 |
| IMON | 芯片→MCU | 输出电流模拟反馈 | IOUT = V_IMON ÷ 0.34(5mΩ 采样 × 68V/V,±3%),5A 时约 1.7V;板上带 RC 滤波 |
I2C 关键寄存器(PMBus):
| 0x01 | OPERATION | 软开关(0x80 开/0x00 关),EN 优先级更高 |
| 0x03 | CLEAR_FAULTS | 清故障锁存(PMBus 状态位是锁存的,必须主动清) |
| 0x21 | VOUT_COMMAND | 调压,Linear16 低字节先发,V=ceil(VOUT×1024×10/FB_RATIO) |
| 0x79 | STATUS_WORD | 故障汇总(OV/OC/OT/PG 等) |
| 0xD1 | MFR_CURRENT_LIMIT | CC 限流点:IOUT_OC = 寄存器值 × 0.05A,最大 5.4A |
调压公式(评估板实测分压比 10.09,别用手册理想值 10):
VOUT_COMMAND = ceil(VOUT × 1024 × 10 / 10.09)
三、与开发板的接法
| CN2 SCL(pin 1/2) | Arduino D15 = PF5(I2C4_SCL) | LCD 扩展板的传感器(AHT20/LIS2DH12)同总线共存,地址不冲突 |
| CN2 SDA(pin 5/6) | Arduino D14 = PG6(I2C4_SDA) | |
| CN2 GND | GND | 共地是必须的 |
| IMON | CN7 pin35 = PC2(ADC1_INP12) | 电流反馈,走 ST morpho 避开 Arduino 排针负载 |
| VOUT 端子 → 101.1kΩ/5.05kΩ 分压中点 | CN7 pin37 = PC3(ADC1_INP13) | 分压比 21.02,36V 输出时 ADC 端 1.71V,安全 |
| VIN/GND | 直流电源 3.6~36V | 功率输入 |
四、系统框图


功率通路:直流输入 → EVL4248(MP4248 升降压)→ 输出端子 → 负载。 控制/反馈通路:I2C4 下发调压限流;IMON(电流)与 VOUT 分压(电压)进 ADC 实测回读;摇杆+LCD 做人机交互。
五、LCD 界面组成
界面用 lcd_bare 裸驱动文本渲染(不用 LVGL,轻量直接),160×128 屏按行组织,按行覆盖刷新(无整屏闪烁):
DPS MP4248 I2C:OK ← 标题 + I2C 在线状态
--------------------
>SET: 5.10 V ← 目标电压(> 为当前编辑项)
ILIM:0.60/0.60A ← 限流 设定值/读回值
VCMD: 5.10 V ← VOUT_COMMAND 寄存器读回(目标)
VOUT: 5.05 V ← 分压实测(真实输出!)
IOUT: 0.24 A ← IMON 实测电流
OUT:ON ST:0000 ← 输出开关 + STATUS_WORD 故障字
LR:item UD:adj OK:out ← 操作提示
三个电压/电流值各司其职:VCMD 是目标、VOUT 是实测、IOUT 是实测电流——负载超限导致输出打嗝时,VCMD 不变、VOUT 掉 0、IOUT 顶在限流值,一目了然。
LCD 界面实拍

六、系统控制逻辑
上电 → LCD/ADC/I2C 初始化 → probe MP4248(失败每 2s 自动重试)
→ 读回芯片当前限流作为初值
主循环(50ms 节拍):
摇杆事件 → 左右切编辑项(SET/ILIM) / 上下调整(0.1V/0.1A 步进)
→ 按下 = 输出 ON/OFF(开前自动 CLEAR_FAULTS)
500ms 周期 → VCMD 读回 / ILIM 读回 / STATUS_WORD / IMON / VOUT 实测
→ 有变化才重绘对应行(行级刷新,无闪烁)
设计要点:
写后即读:SET/ILIM 行显示"设定值/读回值",写没生效一眼看出;
故障锁存语义:PMBus 状态位锁存,CLEAR_FAULTS 在开输出时自动发——历史故障与当前状态分离;
CC 是调节不是故障:进恒流时芯片降压维持电流,VOUT 实测会掉,ST 记录 OC 事件,这些都如实上屏。
七、Zephyr 主要代码
7.1 prj.conf
CONFIG_GPIO=y
CONFIG_SPI=y # LCD(ST7735,SPI4)
CONFIG_ADC=y # IMON + VOUT 实测
CONFIG_INPUT=y # 摇杆(adc-keys 输入驱动)
CONFIG_I2C=y # MP4248 PMBus
板级 CONFIG_FPU=y + CONFIG_FPU_SHARING=y(BSP 里已开,调压计算用浮点)。
7.2 设备树 overlay(boards/nucleo_h5e5zj.overlay,节选)
/* MP4248:Arduino I2C(D15=SCL=PF5 / D14=SDA=PG6),从机地址 0x67 */
&i2c4 {
pinctrl-0 = <&i2c4_scl_pf5 &i2c4_sda_pg6>;
clock-frequency = <I2C_BITRATE_FAST>; /* 400kHz(MP4248 最高 1MHz) */
status = "okay";
};
/* 摇杆:adc-keys 输入驱动(电阻分压式五向摇杆,阈值实测校准) */
joystick: joystick {
compatible = "adc-keys";
io-channels = <&adc1 9>;
sample-period-ms = <50>;
keyup-threshold-mv = <3300>;
key_up { press-thresholds-mv = <595>; zephyr,code = <INPUT_KEY_UP>; };
/* ... 其余方向同理 ... */
};
/* ADC 通道:IMON=PC2(INP12)、VOUT 分压=PC3(INP13)
* ⚠️ 通道号 ≥10 时子节点名必须写十六进制(unit address 按 hex 解析),
* channel@12 会被当成 0x12=18 号!写成 channel@c 才对。 */
&adc1 {
pinctrl-0 = <&adc1_inp9_pb0 &adc1_inp12_pc2 &adc1_inp13_pc3>;
/* ... */
channel@c { reg = <12>; /* IMON */ };
channel@d { reg = <13>; /* VOUT */ };
};
7.3 MP4248 驱动核心(src/mp4248.c)
/* V = ceil(VOUT × 1024 × 10 / FB_RATIO),手册要求非整数向上取整 */
int mp4248_set_vout(float vout_v)
{
uint16_t reg = (uint16_t)ceilf(vout_v * 1024.0f * 10.0f / MP4248_FB_RATIO);
uint8_t buf[3] = { MP4248_CMD_VOUT, (uint8_t)(reg & 0xFF), (uint8_t)(reg >> 8) };
return i2c_write(i2c_dev, buf, sizeof(buf), MP4248_ADDR);
}
/* IOUT_OC(A) = IOUT_LIM × 0.05,读改写保留 bit7(LDC_DISABLE) */
int mp4248_set_ilimit(float amps)
{
/* ...钳位 0.05~5.4A... */
uint8_t reg = (uint8_t)(amps / 0.05f + 0.5f);
uint8_t buf[2] = { MP4248_CMD_ILIMIT, (uint8_t)((cur & 0x80) | reg) };
/* ... */
}
7.4 实测反馈回路(src/main.c,节选)
/* 500ms 周期:寄存器读回 + 实测双通道 */
(void)mp4248_status_word(&status_word);
(void)mp4248_get_ilimit(&rb_ilim);
if (adc_read_mv(&imon_adc, &mv) == 0) {
iout_amps = (float)mv / 1000.0f / 0.34f; /* IMON: 5mΩ×68V/V */
}
if (adc_read_mv(&vout_adc, &mv) == 0) {
vout_volts = (float)mv / 1000.0f * 21.02f; /* 101.1k/5.05k 分压 */
}
八、测试环境
| 主控 | NUCLEO-H5E5ZJ(STM32H5E5ZJ,Zephyr 4.4 自移植 BSP,FPU 开启) |
| 功率板 | EVL4248-QV-00A(MP4248GQV-0000) |
| 输入电源 | 可调直流源(VIN 3.6~36V) |
| 负载 | 可编程电子负载(CC 模式,0~5A) |
| 显示/交互 | LCD 扩展板(ST7735 160×128 + 五向摇杆) |
| 测量 | 万用表(IMON 电压校准)、串口日志(ST-LINK VCP 115200) |
| 调试器 | pyOCD + ST-LINK(RAM 变量直读 / PC 采样定位,不用等串口) |

九、踩坑速记
ADC 通道节点名要 hex:channel@12 会被按十六进制解析成 18 号——ADC_DT_SPEC 找不到节点,adc_channel_setup_dt 静默 -ENOTSUP。≥10 的通道写 channel@c;
VOUT_COMMAND 读回 ≠ 实测:寄存器是目标值,输出被拉垮时它纹丝不动,实测必须靠分压 ADC;
PMBus 故障位是锁存的:不清不归零,开输出时自动 CLEAR_FAULTS 才是好习惯;
MP4248 的 I2C 有上电前提:VIN+EN 都有效才工作,probe 要做自动重试。
我要赚赏金
