用GreenPAK实现低成本高侧电流检测:PWM-DAC与SAR-ADC设计详解
1. 项目概述为什么选择GreenPAK做电流检测在嵌入式硬件开发里电流检测是个既基础又麻烦的活。传统方案要么用专用的电流检测放大器加一颗外置ADC成本高、占地方要么直接用MCU内置的ADC但往往要处理共模电压、噪声和精度问题外围电路也不简单。最近我在一个低功耗电池监测项目里被板子空间和BOM成本卡得头疼于是把目光投向了可编程逻辑器件。GreenPAK这个系列很多人可能用它做过简单的逻辑控制或电源时序但它内部丰富的模拟资源比较器、PWM、计数器其实能玩出很多花样。这次要聊的就是怎么用一颗SLG46855V GreenPAK芯片配合少量外围电阻电容自己搭出一个8位逐次逼近型ADC专门用来做高侧电流检测。这个方案的核心思路很巧妙既然GreenPAK能产生高精度的PWM那用PWM加一个RC滤波网络不就是一个数模转换器吗再用芯片自带的模拟比较器去比较这个“DAC”输出的电压和待测的电流感应电压通过一个数字反馈环路去调整PWM占空比直到两者相等。此时控制PWM的数字码值就是ADC的转换结果。这本质上是一个用数字逻辑“软实现”的逐次逼近寄存器ADC。它的最大好处是灵活——ADC的量程对应电流检测范围和零点偏移完全由外部几个电阻的分压比决定你可以轻松地把它校准到你的传感器输出范围上充分利用8位分辨率。对于监测电池充放电电流、做负载故障检测或者简单的电表应用这种低成本、高集成度的方案非常实用。下面我就把这个从架构设计、外部电路计算到内部GreenPAK逻辑配置、I2C数据读取的全过程结合我实际调试中的坑和技巧详细拆解一遍。2. 核心架构解析PWM如何变身精密DAC2.1 逐次逼近型ADC的基本原理要理解这个设计得先抛开GreenPAK看看一个最经典的逐次逼近型ADC是怎么工作的。它通常包含一个模拟比较器、一个数模转换器、一个逐次逼近寄存器以及一个控制逻辑。转换开始时SAR先输出一个中间量程的数字码给DACDAC产生对应的模拟电压V_DAC比较器将其与输入电压V_IN比较。如果V_IN V_DAC则SAR保持最高位为1并置位次高位继续比较如果V_IN V_DAC则SAR将最高位清0再置位次高位。这个过程像“天平称重”从最高位到最低位逐位比较最终SAR锁存的数字码就是转换结果。这个原理的关键在于DAC的精度和速度直接决定了ADC的性能。在分立元件方案里你需要一个高精度的DAC芯片而这正是成本所在。我们的GreenPAK方案其创新点就在于用PWM低通滤波的方式在片外构建了一个低成本、可灵活调整的DAC。2.2 PWM-DAC的数学建模与精度分析PWM本质上是一个占空比可调的数字方波。当它通过一个低通滤波器后高频的开关成分被滤除输出的是一个其平均值等于PWM占空比乘以PWM高电平电压的直流电压。对于一个理想的RC低通滤波器其传递函数可以简化看待如果滤波器的截止频率远低于PWM频率那么输出纹波会很小近似于一个干净的直流电压。公式表示为V_DAC D * V_PWM。其中D是占空比0到1V_PWM是PWM信号的高电平电压通常是芯片的VDD。那么一个8位分辨率的PWM其占空比最小变化量是1/256因此理论上这个PWM-DAC也能达到8位的分辨率。但是这里有几个实际工程上的坑PWM频率的选择频率不能太低否则即使经过滤波纹波仍然很大会影响比较器的判决引入噪声。频率也不能太高否则GreenPAK内部数字逻辑的开关损耗会增加也可能因为输出级上升/下降时间限制导致波形畸变。通常需要折中。RC滤波器的设计这是影响DAC建立时间和纹波的关键。时间常数τ R*C需要足够大以有效滤除PWM基频及其谐波。一个经验法则是滤波器的-3dB截止频率f_c应至少低于PWM频率的1/10最好能达到1/50或更低。例如PWM频率为100kHz那么f_c最好设计在2kHz以下。建立时间与ADC速度的权衡RC滤波器是个惯性环节当PWM占空比改变时V_DAC需要一定时间通常认为是5τ才能稳定到新值的99%以上。这个建立时间直接限制了ADC的转换速率更新率。我们的ADC控制逻辑必须在两次更新之间留出足够的时间让PWM-DAC的输出稳定下来。在原设计里他们选择了较高的内部时钟12.5MHz来驱动计数器并精心匹配了PWM频率和ADC更新周期1.3312 ms就是为了在速度、精度和稳定性之间取得平衡。这是整个方案能否成功的关键决策点。2.3 GreenPAK内部逻辑实现框图在SLG46855V内部我们主要用到了以下资源计数器作为核心的“逐次逼近寄存器”。它根据比较器的输出进行递增或递减计数其当前计数值即作为PWM的占空比控制字同时也作为最终的ADC输出码。数字比较器与逻辑用于生成PWM波形。通常用一个计数器生成三角波或锯齿波再用一个数值比较器将三角波与ADC计数器的值进行比较产生对应占空比的PWM信号。模拟比较器这是ADC的“裁判”。一端接外部输入的、代表电流的电压信号V_SENSE另一端接PWM-DAC滤波后的电压V_DAC。输出结果直接反馈给ADC计数器决定其计数方向。时钟与分频器提供整个系统所需的各类时钟包括ADC计数器的工作时钟、PWM的时基时钟等。I2C接口与寄存器用于将ADC计数器的值读出到外部MCU。整个逻辑闭合形成一个负反馈环路V_SENSE升高 - 比较器输出高 - 计数器递增 - PWM占空比增大 - V_DAC升高 - 直至V_DAC ≈ V_SENSE系统达到平衡。这个过程是连续自动进行的只要V_SENSE变化环路就会自动追踪计数器锁定的就是当前ADC码值。3. 外部电路设计与参数计算实战光有芯片内部的数字逻辑还不够外部电路的精度直接决定了整个电流检测系统的性能。这部分是硬件工程师的舞台也是容易出错的地方。3.1 高侧电流检测与电平移位我们要检测的是负载电流I_LOAD通常会在电源V_BAT和负载之间串联一个毫欧级的小阻值检测电阻R_SENSE。根据欧姆定律V_SENSE I_LOAD * R_SENSE。但这里V_SENSE是以电源正极为参考点的是一个“高侧”电压其值接近V_BAT。而GreenPAK的比较器输入端其共模输入电压范围通常无法承受这么高的电压可能接近甚至超过其电源电压VDD。因此必须进行电平移位将V_SENSE衰减到一个适合比较器输入的范围内比如0V到VDD之间。这就是电路中使用R1和R2电阻分压网络的核心目的。此外为了灵活调整ADC的零点和满量程还引入了连接到VDD和GND的电阻与分压网络并联共同设定比较器反相输入端的电压范围。3.2 电阻网络计算与量程校准这是整个设计的精华也是最具灵活性的地方。参考原文档的示意图外部电路通常包含R1, R2, R3, R4等多个电阻。它们共同决定了两个关键电压点零点对应的V_DAC电压当待测电流I_LOAD为0时V_SENSE理论上为0。但此时比较器反相输入端的电压由R1, R2, R3, R4网络对V_BAT和VDD的分压决定并不为零。我们通过调整电阻值使得当ADC输出码为0时PWM占空比0%V_DAC恰好等于这个电压。这样ADC的“0”代码就精确对应了0电流。满量程对应的V_DAC电压当I_LOAD达到最大值I_MAX时V_SENSE达到最大。同样我们调整电阻网络使得当ADC输出码为255时PWM占空比100%V_DAC恰好等于此时比较器同相输入端的电压即衰减后的V_SENSE。计算过程需要一些电路分析知识。本质上这是一个求解电阻网络使其戴维南等效电压与V_SENSE衰减后的范围匹配的问题。原文档给出了一个关键公式对应其公式1用于计算在最小V_BAT下达到最大检测电流时所需的分压比系数。实操心得使用仿真工具强烈建议在确定电阻值前使用LTspice、TINA-TI等电路仿真软件搭建这个电阻网络。你可以轻松地扫描V_BAT和I_LOAD观察比较器两端的电压是否始终落在安全且合理的范围内并且留有一定的裕量。优先使用标准阻值计算出的理论电阻值可能是12.34kΩ这种非标值。务必将其就近取整为E24或E96系列的标准值如12.4kΩ或12.1kΩ并重新验算关键点的电压。关注电阻精度和温漂这个网络的精度直接决定了ADC的增益误差和偏移误差。至少选择1%精度的薄膜电阻对于要求高的应用0.1%甚至更高精度的电阻是必要的。同时要注意电阻的温漂系数TCR避免温度变化导致测量漂移。3.3 RC滤波器参数设计与PCB布局要点为PWM-DAC设计RC低通滤波器。假设我们GreenPAK产生的PWM频率为f_pwm。确定截止频率f_c根据前文选择f_c f_pwm / 50 或更低。例如f_pwm200kHz则f_c选择4kHz以下。选择电容C通常先选择一个容易获取的电容值如1nF、10nF、100nF。较小的电容体积小但可能需要较大的电阻来获得同样的时间常数。计算电阻R根据公式 f_c 1 / (2π * R * C)推导出 R 1 / (2π * f_c * C)。例如选择C10nF目标f_c3kHz则R ≈ 1 / (2 * 3.1416 * 3000 * 10e-9) ≈ 5.3kΩ。取标准值5.1kΩ或5.6kΩ。验证建立时间时间常数τ R*C 5.1kΩ * 10nF 51μs。建立到99%需要5τ 255μs。这个时间必须远小于你设定的ADC更新周期1.3312ms否则DAC输出未稳定就进行比较会导致线性度变差。这里255μs 1.3312ms条件满足且留有充足余量。PCB布局注意事项滤波电容务必靠近GreenPAK的PWM输出引脚放置走线尽可能短粗回流路径清晰以减少高频噪声。RC滤波器的接地点必须是一个干净的、低噪声的模拟地。最好单独走线连接到系统的模拟地平面或星型接地单点。电流检测电阻R_SENSE的两端采样走线必须采用开尔文连接方式即用单独的一对细线直接连接到电阻的金属焊盘上避免将大电流路径上的压降引入测量信号。将GreenPAK的模拟电源AVDD和数字电源DVDD用磁珠或0Ω电阻隔离并在靠近芯片引脚处分别放置一个10μF的钽电容和一个100nF的陶瓷电容进行去耦。4. GreenPAK内部逻辑配置详解有了外部电路接下来就是在GreenPAK Designer软件里“画”出ADC的逻辑。这个过程就像在画一个数字电路图。4.1 时钟树与计数器配置SLG46855V有一个25MHz的RC振荡器。我们首先需要用它衍生出几个不同频率的时钟ADC计数器时钟这是决定ADC逐次逼近速度的主时钟。原设计使用了12.5MHz25MHz分频。这个时钟越快ADC跟踪输入信号变化的能力越强但功耗也会增加。你可以根据系统对速度和功耗的要求调整比如降到6.25MHz或3.125MHz。PWM时基时钟这是生成PWM三角波所需的时钟。它的频率决定了PWM的频率。例如如果我们想要一个8位分辨率、频率约为200kHz的PWM那么PWM时基时钟频率应为 200kHz * 256 51.2MHz。这超过了芯片内部时钟上限。因此实际做法是使用一个位数较低的计数器比如7位来产生PWM或者接受一个更低频率的PWM。原设计可能采用了更复杂的逻辑来优化这一点。你需要根据之前计算的DAC建立时间来反推可接受的最低PWM频率。在软件中使用分频器模块对25MHz时钟进行分频产生上述时钟信号并连接到相应模块的时钟输入端。4.2 PWM生成模块搭建GreenPAK内部没有硬件PWM模块但我们可以用计数器和比较器轻松搭建一个。放置一个计数器配置为“重复计数”模式设置其模值为255对应8位。它的时钟输入接PWM时基时钟。这个计数器会从0循环计数到255产生一个锯齿波。放置一个数字比较器。将上述锯齿波计数器的实时计数值连接到比较器的一端A。将ADC计数器的输出即当前的ADC数字码连接到比较器的另一端B。配置比较器为“A B”模式。那么当锯齿波计数值小于ADC码值时比较器输出高电平否则输出低电平。这样比较器的输出就是一个占空比 (ADC码值 / 256) * 100% 的PWM波。这个PWM信号需要连接到芯片的一个GPIO引脚并通过外部RC滤波器转换为模拟电压V_DAC。4.3 逐次逼近逻辑与状态机这是最核心的控制逻辑。我们需要实现“如果V_IN V_DAC则ADC计数器加1如果V_IN V_DAC则ADC计数器减1”。放置一个8位计数器作为ADC结果寄存器。将其配置为“上下计数”模式。将芯片模拟比较器的输出COMP_OUT引入数字域。假设比较器正端接V_SENSE负端接V_DAC那么当V_SENSE V_DAC时COMP_OUT为高电平。我们需要用COMP_OUT来控制ADC计数器的计数方向。这里需要一个控制逻辑当COMP_OUT为高V_IN V_DAC我们希望计数器向上计数当COMP_OUT为低则向下计数。在GreenPAK中可以通过查找表或DFF来构建这个逻辑控制计数器的“Up/Down”方向引脚。ADC更新时钟我们不能让计数器在每个系统时钟沿都根据比较器结果动作那样会引入噪声和振荡。需要用一个较慢的时钟比如由12.5MHz分频而来来同步更新。将这个时钟连接到ADC计数器的时钟输入端。这样在每个“更新时钟”的上升沿计数器会根据当前比较器的输出状态进行一次递增或递减操作逐步逼近最终值。这个逻辑闭合后就形成了一个自适应的跟踪型ADC。其跟踪速度由“更新时钟”的频率决定。原设计中的1.3312ms更新周期就是由这个时钟决定的。4.4 I2C接口配置与数据输出SLG46855V带有I2C从机接口。我们需要将ADC计数器的值映射到I2C可访问的寄存器上。在GreenPAK Designer中找到“I2C/SPI”模块将其配置为I2C从机模式并设置一个7位从机地址例如0x08。我们需要将ADC计数器的输出值连接到I2C模块的数据输入上。通常ADC计数器本身可能就是一个可以被I2C读取的寄存器或者我们需要用一个“管道”寄存器Pipe Latch在每个ADC转换完成后锁存计数值再将这个锁存器的输出连接到I2C。配置I2C的寄存器映射表。例如我们可以定义寄存器地址0x00存放ADC结果的高8位如果ADC是8位则可能只占用低8位。确保读写时序正确。重要提示仔细阅读数据手册中关于I2C读写的时序图。GreenPAK的I2C模块在收到读命令后需要一定的时间几个微秒从内部寄存器中准备好数据。在MCU的I2C驱动程序中在发送读指令和真正读取数据字节之间需要插入一个微小的延迟或者处理可能出现的NACK否则可能读到错误数据。5. 固件开发MCU如何读取与处理数据GreenPAK配置好并编程后它就作为一个独立的ADC从设备运行了。主控MCU通过I2C总线定期读取其转换结果。5.1 I2C通信协议实现原文档给出了一个示例命令帧[0x10 0xA5] [0x11 R]。我们需要解析它0x10很可能是包含了写操作和从机地址的控制字节。I2C标准中控制字节的格式是(7位从机地址 1) | R/W位。R/W位为0表示写为1表示读。假设从机地址是0x08那么写控制字节就是(0x08 1) | 0 0x10。这吻合。0xA5这是要写入的寄存器地址告诉GreenPAK接下来要操作哪个寄存器。这里0xA5对应的是存放ADC值的计数器CNT0的地址。然后是一个重复起始条件接着发送读控制字节0x11。0x11就是(0x08 1) | 1 0x11。最后从设备GreenPAK会返回一个字节的数据即ADC计数值。在MCU端以STM32 HAL库为例代码可能如下所示#define GREENPAK_ADDR 0x08 #define ADC_REG_ADDR 0xA5 uint8_t read_greenpak_adc(I2C_HandleTypeDef *hi2c) { uint8_t reg_addr ADC_REG_ADDR; uint8_t adc_value 0; // 1. 发送寄存器地址写操作 if (HAL_I2C_Master_Transmit(hi2c, GREENPAK_ADDR 1, reg_addr, 1, HAL_MAX_DELAY) ! HAL_OK) { Error_Handler(); } // 2. 重新发起起始条件并读取一个字节数据 if (HAL_I2C_Master_Receive(hi2c, (GREENPAK_ADDR 1) | 0x01, adc_value, 1, HAL_MAX_DELAY) ! HAL_OK) { Error_Handler(); } // 可选增加一个小延迟确保GreenPAK内部数据稳定 // HAL_Delay(1); return adc_value; }5.2 数据校准与电流值换算读回来的adc_value是一个0-255的数字。我们需要通过校准公式将其转换为真实的电流值。根据文档中的公式3并结合我们的电路参数进行推导。假设我们的电路参数如下V_BAT电源电压假设为恒定值或通过另一路ADC测量得到。R_SENSE电流检测电阻例如0.1Ω。R1, R2, R3, R4电平移位和量程设置电阻其值已知。ADC_Code读取到的ADC码值0-255。换算步骤计算PWM-DAC的输出电压V_DACV_DAC (ADC_Code / 255) * VDD。其中VDD是GreenPAK的工作电压也是PWM的高电平。根据电阻网络反推比较器正端电压V_IN由于比较器负端接V_DAC且环路稳定时V_IN ≈ V_DAC。但V_IN是V_SENSE经过电阻网络衰减后的电压。我们需要建立V_IN与V_SENSE的关系模型。这个模型由电阻网络决定通常是一个线性关系V_IN k * V_SENSE b。其中k是衰减系数b是偏移电压由连接到VDD和GND的电阻产生。计算V_SENSEV_SENSE (V_IN - b) / k。计算负载电流I_LOADI_LOAD V_SENSE / R_SENSE。实操心得两点校准法在实际生产中我们很难精确知道所有电阻的精确值和VDD的精确值。更实用的方法是进行系统级的两点校准零点校准在I_LOAD 0的条件下读取ADC码值记为ADC_ZERO。理论上它应该是一个固定值但受电阻偏差和VDD影响。满量程校准施加一个已知的、精确的满量程电流I_FULL例如使用精密电流源读取ADC码值记为ADC_FULL。线性换算对于任何一次测量值ADC_X其对应的电流I_X可以用以下公式计算I_X (ADC_X - ADC_ZERO) * (I_FULL / (ADC_FULL - ADC_ZERO))这个方法消除了电阻精度、VDD波动、运放偏移等绝大多数系统误差只依赖于标准电流源的精度是工程上最可靠的做法。可以将ADC_ZERO、ADC_FULL和计算出的比例系数存储在MCU的Flash中。5.3 滤波与数据处理ADC读回的数据可能含有噪声需要进行软件滤波。移动平均滤波最简单有效。连续采样N次求和后取平均。N越大滤波效果越好但响应速度越慢。对于电池电流监测N8或16通常足够。一阶低通滤波指数加权平均filtered_value α * new_sample (1 - α) * filtered_value。其中α是滤波系数0α1越小滤波越强惯性越大。这种滤波计算量小适合在资源有限的MCU上运行。#define ALPHA 0.1f // 滤波系数可调整 float filtered_adc 0.0f; void update_current_reading(void) { uint8_t raw_adc read_greenpak_adc(hi2c1); // 一阶低通滤波 filtered_adc ALPHA * (float)raw_adc (1.0f - ALPHA) * filtered_adc; // 使用校准参数将滤波后的ADC值转换为电流 float current_ma (filtered_adc - cal_zero) * cal_scale_factor; // cal_scale_factor单位 mA/ADC码 // ... 后续处理 }6. 调试、测试与性能优化实录电路焊好了代码写完了接下来就是上电调试这里才是真正见功力的地方。6.1 上电基础检查电源与地首先用万用表测量GreenPAK的VDD引脚电压是否稳定在预期值如3.3V纹波是否过大。检查所有GND连接是否良好。时钟与PWM使用示波器探头测量GreenPAK输出PWM的GPIO引脚。你应该能看到一个频率和占空比随输入电压变化的方波。如果看不到首先检查GreenPAK是否成功编程内部振荡器是否启用。DAC输出用示波器测量RC滤波器后的V_DAC网络。将示波器调到直流耦合并打开高分辨率采集模式。你应该能看到一个相对平稳的直流电压上面叠加着很小的纹波。改变输入电压V_SENSE例如用手持可调电源模拟观察V_DAC是否平滑地跟随变化。6.2 常见问题与排查技巧问题1ADC读数不稳定跳动很大。可能原因A电源噪声。检查电源纹波尤其是给比较器供电的模拟电源。确保去耦电容100nF陶瓷电容紧靠芯片电源引脚。可能原因BPWM频率与RC滤波器不匹配。如果PWM频率太低或RC滤波器截止频率太高V_DAC上的纹波会很大导致比较器在阈值附近反复翻转。用示波器观察V_DAC的纹波峰峰值它应该远小于ADC的1个LSB对应的电压值VDD/256。如果纹波过大尝试增大RC滤波器的电容值例如从10nF增加到100nF或者检查GreenPAK配置提高PWM频率。可能原因CADC更新速率过快。如果ADC更新时钟太快PWM-DAC的输出还没来得及稳定到新值比较器就进行了下一次判决会导致系统在真值附近振荡。尝试在GreenPAK软件中降低ADC更新时钟的频率增大分频比。可能原因D模拟比较器输入端噪声。确保V_SENSE和V_DAC的走线远离数字信号线如时钟、PWM线。可以在比较器输入端对地添加一个小电容如10pF~100pF来滤除高频噪声但注意电容太大会影响响应速度。问题2ADC读数线性度差在量程两端误差大。可能原因A电阻网络计算错误或电阻精度不够。重新核算电阻分压值确保在零电流和满量程电流时计算出的V_SENSE衰减值落在V_DAC的可输出范围0到VDD内并且留有一定裕量例如5%。使用更高精度的电阻0.1%。可能原因BPWM-DAC非线性。在低占空比接近0和高占空比接近100%时由于GPIO输出级的上升/下降时间不对称可能导致实际平均电压与理论值有偏差。尝试避免使用极端占空比可以通过调整电阻网络将ADC的工作范围设置在20%到80%占空比之间。可能原因C比较器输入失调电压。模拟比较器本身存在输入失调电压在测量小信号时影响显著。GreenPAK的数据手册会给出这个参数。如果影响不可接受可以考虑在软件中进行补偿或者在外部用运放搭建一个精密差分放大器来代替直接分压接入比较器。问题3I2C通信失败读回的数据全是0xFF或0x00。可能原因A上拉电阻。I2C总线的SDA和SCL线必须接上拉电阻通常4.7kΩ~10kΩ。检查是否遗漏。可能原因B地址错误。再次确认GreenPAK中配置的I2C从机地址并与MCU代码中使用的地址进行比对。注意7位地址和8位读写字节的区别。可能原因C时序问题。某些MCU的I2C库在发送重复起始条件时可能有问题。尝试用逻辑分析仪或示波器抓取I2C波形与GreenPAK数据手册的时序图对比。确保启动、停止、ACK等信号符合规范。在读写操作间增加一个几微秒的延迟。6.3 性能测试与评估方法静态精度测试使用一台高精度的可编程电压源代替V_SENSE输入。从零到满量程以一定的步进例如每20mV设置电压记录每个点ADC读数的码值。绘制“输入电压-ADC码值”曲线计算积分非线性误差和微分非线性误差。动态响应测试使用信号发生器产生一个阶跃变化的V_SENSE信号例如从零点突然跳到半量程用示波器同时捕捉V_SENSE和V_DAC的波形。观察V_DAC跟踪V_SENSE的建立时间这个时间应该与你设定的ADC更新周期理论值相符。电流测量对比测试使用一个精密万用表如六位半的电流档与你的GreenPAK ADC电路串联在同一个负载回路中。改变负载大小对比两个设备的读数。计算在整个量程内的最大绝对误差和相对误差。温漂测试将整个板子放入温箱在规定的温度范围如0°C到70°C内变化温度。在几个固定的测试电流点记录ADC读数的变化。这可以评估电阻温漂和芯片内部参数变化对系统精度的影响。通过以上系统的调试和测试你就能充分掌握这个基于GreenPAK的ADC电流检测方案的性能边界并能够根据具体应用需求成本、精度、速度、温度范围对其进行优化和调整。这种“用数字逻辑搭建模拟功能”的思路极大地拓展了小型可编程器件的应用场景在需要高度集成和成本控制的场合是一个非常值得收藏的技能。