资讯动态

STM32双ADC同步采样实现Boost升压电路电压电流监测与效率计算

发布时间:2026/9/11 20:13:33 来源:尧图企业网站定制
简介一套基于STM32与C语言实现的DC-DC高效升压电路工程包面向嵌入式电源开发者与电子工程学习者适合电池供电、太阳能系统等需要把低压直流提升至较高电压的应用场景重点解决输入输出电压同步采样与精确稳压控制问题。工程基于Keil uVision5开发完整覆盖STM32底层驱动、ADC双通道采样、PID调节、PWM波生成等核心模块通过占空比控制与反馈机制维持输出电压稳定代码结构清晰便于理解Boost拓扑中电感储能、开关管通断与能量转移过程。压缩包共239个文件约8.28MB包含43个.h头文件、41个.c源文件以及一批编译中间文件、调试备份与工程配置信息从源码到可执行文件一应俱全可直接打开工程进行实验或二次修改。已有904人学习下载适合需要参考完整升压控制实现、学习STM32电源管理程序框架或进行电源实验的开发者。1. 一块Boost升压电路要同时采样要的不只是电压表把3.7V锂电池升到5V给4G模组供电这活儿很多工程师都干过。板子焊完上电用万用表量输出5.0V挺正常可一旦模组以最大功率发射电流从几十毫安瞬间跳到2A输出电压立刻往下掉万用表只给一个平均值根本看不出掉到哪、掉了多久。更麻烦的是算效率想验证Boost电路是不是“高效”手上得同时有输出电压和输出电流采样时刻相差几百微秒算出来的功率连参考价值都没有。这个标题里的“同时采样”说的就是让电压和电流在同一个触发沿上被采集再拿C语言在STM32上做滤波、标定、效率计算。这套做法适合给便携设备、电池供电的模组做供电链路验证也适合把固定电压输出的Boost改成带监控、带保护的可控电源。下面按Boost参数、STM32双ADC同步采集、C语言处理、Keil调试的顺序讲一遍完整落地方案。2. 从占空比到效率Boost升压电路原理与关键元件的选型计算2.1 电感储能与占空比把3.7V抬高到12V的第一步Boost拓扑的核心是电感储能。开关管导通时输入电压直接加在电感两端电感电流线性上升把能量存在磁场里开关管关断时电感电流不能突变电感两端极性反转和输入电压串联后共同给输出电容和负载供电。输出电压高于输入电压靠的就是这个“串联”过程。在连续导通模式CCM下理想占空比公式是[ D 1 - \frac{V_{in}}{V_{out}} ]拿3.7V锂电升5VD≈0.26升12VD≈0.69。占空比直接决定了电感两端电压的施加时间也就决定了储能多少。但这个公式有个前提效率100%。实际Boost芯片效率在85%~95%之间考虑损耗后更接近[ D \approx 1 - \frac{\eta \cdot V_{in}}{V_{out}} ]效率越低占空比越大因为需要更多能量补给损耗。设计时先用理想公式算初值再用实际效率修正。这个修正值会影响电感电流峰值计算不能省。2.2 电感选型与饱和电流同步Boost下还要防电流负向电感是Boost电路里最不能拍脑袋选的元件。选小了纹波电流大输出纹波和开关管应力都升高选大了响应慢体积也大。纹波电流按这个公式估算[ \Delta I_L \frac{V_{in} \cdot D}{f_{sw} \cdot L} ]其中(f_{sw})是开关频率。电感平均电流等于输入电流[ I_{in} \frac{V_{out} \cdot I_{out}}{V_{in} \cdot \eta} ]峰值电流是两者之和的一半。以3.7V升5V、1.2MHz开关频率为例按上面公式估算不同输出电流下电感参数大致如下输出电流建议电感量实际峰值电流电感饱和电流建议值1A10μH约1.6A2.5A以上2A4.7μH约3.2A5A以上3A3.3μH约4.8A7.5A以上电感饱和电流一定要按峰值电流留出至少30%余量。电感一旦饱和感值骤降纹波电流暴增轻则发热重则烧开关管。饱和电流的标识在规格书里叫Isat不是额定电流选型时最容易看错。这里多说一句标题里的“同步Boost”。同步整流Boost把续流二极管换成功率MOSFET导通损耗低效率能到95%以上但代价是轻载时电感电流会反向电路从输出侧抽能量回输入侧。用同步Boost芯片时要确认它有没有PFM轻载模式避免在待机时反而更耗电。2.3 反馈电阻、输出电容与PCB布局稳定性的最后一道关口输出电压由反馈电阻分压决定。绝大多数Boost芯片内部基准(V_{ref})是0.6V或0.8V输出电压满足[ V_{out} V_{ref} \times (1 \frac{R_1}{R_2}) ]以Vref0.6V为例常用输出电压的电阻组合目标输出电压R1上分压R2下分压5V73.2kΩ10kΩ9V140kΩ10kΩ12V190kΩ10kΩ反馈电阻取值不要太高FB引脚输入漏电流会在高阻值下引入误差也不要太低分压电阻本身就成了额外的负载。10kΩ级别的下分压是比较实用的起点。输出电容决定输出纹波陶瓷电容首选低ESR对纹波抑制明显。12V输出建议22μF和47μF并联兼顾瞬态响应和纹波。PCB布局上开关节点SW的铜皮要短而粗反馈电阻和FB走线要远离SW节点否则高频开关噪声会耦合进反馈环造成输出电压抖动。3. 输出电压与电流同时采样STM32 ADC通道分配与双ADC同步3.1 采样电路电阻分压、采样电阻与电流检测放大器先明确采样对象。要算效率至少需要输出电压、输出电流、输入电压、输入电流四路信号如果只验证Boost输出特性电压和电流两路就够。STM32F103有ADC1、ADC2、ADC3三个ADC其中ADC1和ADC2可以组成双ADC同步模式天然适合“电压电流同一时刻采样”这个需求。电压通道用电阻分压把12V降到ADC量程内。以12V输出为例上分压330kΩ、下分压100kΩADC引脚电压约2.79V留出过压保护余量。分压电阻后面并联一个10nF~100nF电容滤掉高频噪声同时给ADC采样电容提供电荷源。电流通道用低边采样电阻加电流检测放大器。采样电阻放在输出负载的低边一端接地一端接负载地。0.02Ω采样电阻在3A电流下产生60mV压降经INA180A3放大50倍后是3.0V正好贴近ADC满量程。没有INA180时用普通运放搭差分放大器也能工作但要注意输入共模范围和失调电压。4G模组发射阶段电流变化速度很快电流放大器带宽至少要有100kHz级别否则采到的电流已经被“削平”了。3.2 ADC1/ADC2同步规则模式让电压电流落在同一个触发沿为什么不用一个ADC轮流采两个通道规则通道是顺序转换通道0采完再采通道1中间差几十微秒。对静态负载没影响但4G模组发射时电流以毫秒级变化电压电流不在同一时刻算出来的功率曲线是“错位”的效率自然也不准。双ADC同步规则模式解决的就是这个问题ADC1作为主ADC2作为从两个ADC在同一个外部触发沿同时启动转换。ADC1采电压ADC2采电流得到的就是真正同一时刻的样本。下面是以STM32F103标准外设库为例的初始化代码// 双ADC同步规则模式初始化STM32F103标准外设库 // 电压采样PA0电流采样PA1 void ADC_Sync_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; // 开启ADC1/ADC2、GPIOA、DMA1时钟ADC时钟72MHz/612MHz RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div6); // PA0、PA1配置为模拟输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, GPIO_InitStructure); // ADC1为主设备规则同步模式ADC2为从设备跟随ADC1触发 ADC_DeInit(ADC1); ADC_DeInit(ADC2); ADC_InitStructure.ADC_Mode ADC_Mode_RegSimult; // 双ADC规则同步模式 ADC_InitStructure.ADC_ScanConvMode DISABLE; // 每个ADC只转换1个通道 ADC_InitStructure.ADC_ContinuousConvMode DISABLE; // 不连续转换等外部触发 ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_T1_CC2; ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); ADC_Init(ADC2, ADC_InitStructure); // ADC1采PA0上的输出电压ADC2采PA1上的输出电流 ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5); // 采样节拍由TIM1_CH2事件触发这里先把定时器配置为10kHz RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); // 72MHz/(71991)10kHzPulse3600使触发点落在计数周期中部 TIM1-ARR 7199; TIM1-CCR2 3600; TIM1-CCMR1 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2; // PWM模式1 TIM1-CCER | TIM_CCER_CC2E; TIM1-CR1 | TIM_CR1_CEN; // DMA1通道1搬运ADC1的数据寄存器一次搬运32位数据 DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)adc_buf; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize 1; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Word; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Word; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_InitStructure.DMA_M2M DMA_M2M_Disable; DMA_Init(DMA1_Channel1, DMA_InitStructure); // 开启外部触发和ADC使能DMA ADC_ExternalTrigConvCmd(ADC1, ENABLE); ADC_ExternalTrigConvCmd(ADC2, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_Cmd(ADC2, ENABLE); // 校准ADC1和ADC2 ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); ADC_ResetCalibration(ADC2); while (ADC_GetResetCalibrationStatus(ADC2)); ADC_StartCalibration(ADC2); while (ADC_GetCalibrationStatus(ADC2)); DMA_Cmd(DMA1_Channel1, ENABLE); }几个关键参数值得说明。ADC_Mode_RegSimult让ADC1和ADC2以规则同步模式运行两个ADC在同一边沿启动各自规则通道的转换。外部触发选用ADC_ExternalTrigConv_T1_CC2也就是TIM1的通道2事件这样采样节拍可以用定时器精确控制而不是靠软件轮询。采样时间选了239.5个ADC时钟周期约20μs一次转换对毫秒级的负载变化绰绰有余同时降低信号源内阻对采样精度的影响。DMA搬运的数据宽度是Word这一点在下一节细说。3.3 DMA数据排列为什么读到的ADC2跑到高位去了双ADC同步模式下ADC1和ADC2的结果不是各自进自己的DMA通道而是合并成一个32位数据放在ADC1的数据寄存器里由ADC1的DMA搬走。数据排列是固定的低16位是ADC1的结果高16位是ADC2的结果。取数时代码这样写// 从DMA缓冲区取电压电流原始ADC值 uint16_t adc_v_raw (uint16_t)(adc_buf[0] 0xFFFF); // ADC1 - 电压 uint16_t adc_i_raw (uint16_t)(adc_buf[0] 16); // ADC2 - 电流新手最容易在这里栽跟头DMA只配了ADC1的通道但以为ADC2会把结果送到另一个地址或者DMA数据宽度配了HalfWord结果每次只搬低16位高16位永远读不到。F103的ADC2本身没有DMA接口同步模式下必须通过ADC1的DMA把两个结果一起带走。只要发现电流数据恒为0或偶尔跳变到错误值优先检查DMA数据宽度和ADC_DMACmd是否配置正确。DMA的模式用循环模式配合定时器触发每来一个触发沿就自动搬一次数据CPU只需要在主循环里读adc_buf不需要进中断。如果需要更精确的“采集时刻”记录可以在DMA半传输中断里打个时间戳但基础应用用循环模式已经足够。4. C语言实现标定、滑动平均、效率计算与软件保护4.1 滑动平均滤波丢掉一个最大一个最小ADC原始值不能直接用。Boost的开关噪声会通过地回路串进采样通道偶尔采到一两个尖峰直接参与计算会让效率和保护逻辑都失真。经典做法是滑动平均但工程上用得更稳的是“去掉极值再平均”#define SAMPLE_BUF_SIZE 8 uint16_t v_buf[SAMPLE_BUF_SIZE]; uint16_t i_buf[SAMPLE_BUF_SIZE]; uint8_t sample_index 0; // 每得到一组同步采样值就调用一次 void Sample_Push(uint16_t v_raw, uint16_t i_raw) { v_buf[sample_index] v_raw; i_buf[sample_index] i_raw; sample_index (sample_index 1) % SAMPLE_BUF_SIZE; } // 去掉最大最小后取平均返回滤波后的电压、电流ADC值 void Sample_Filter(uint16_t *v_out, uint16_t *i_out) { uint32_t v_sum 0, i_sum 0; uint16_t v_min 0xFFFF, v_max 0; uint16_t i_min 0xFFFF, i_max 0; uint8_t i; for (i 0; i SAMPLE_BUF_SIZE; i) { v_sum v_buf[i]; v_min (v_buf[i] v_min) ? v_buf[i] : v_min; v_max (v_buf[i] v_max) ? v_buf[i] : v_max; i_sum i_buf[i]; i_min (i_buf[i] i_min) ? i_buf[i] : i_min; i_max (i_buf[i] i_max) ? i_buf[i] : i_max; } *v_out (uint16_t)((v_sum - v_min - v_max) / (SAMPLE_BUF_SIZE - 2)); *i_out (uint16_t)((i_sum - i_min - i_max) / (SAMPLE_BUF_SIZE - 2)); }窗口长度8个点10kHz采样率下每0.8ms输出一个滤波值动态跟踪快又能去掉单点尖峰。如果负载是4G模组这种突发型窗口长度不要超过16个点否则发射上升沿会被拉平保护反应也跟着变慢。这里有个可以抬杠的点去掉最大最小会让数据少两个样本数学上不是“标准平均”。但实际工程里开关噪声尖峰通常只影响一个点保留它会让平均值偏大去掉它代价极小。这个取舍在Boost采样场景里是划算的。4.2 增益标定与效率计算把ADC码值换算成功率ADC值换算成物理量核心是线性标定。理想情况下用公式(y k \cdot x b)但增益k和偏置b不能只靠理论算——电阻精度、运放失调、基准电压误差都会让实际值与理论值偏离。标定做法空载状态下读电压ADC值用万用表同时测实际输出电压接一个固定电阻负载读第二组电压ADC值和万用表实测值两组数据解出k和b保存到Flash。电流通道同理用电子负载或者精密电阻做负载记录两到三个电流点。标定完成后写入固件参数。换算和效率计算的C代码// 标定参数来自两段式标定单位V/ADC码、A/ADC码 #define V_GAIN (3.30f / 4095.0f) // 理论值实际用标定后的k #define I_GAIN (3.00f / 4095.0f) #define V_DIV (430.0f / 100.0f) // 分压比反推(330k100k)/100k #define I_SENSE (1.0f / 50.0f / 0.02f) // 放大50倍、0.02Ω电阻 // 计算电压电流和效率单位保留3位小数 void Power_Compute(uint16_t v_raw, uint16_t i_raw) { float v_out (float)v_raw * V_GAIN * V_DIV; float i_out (float)i_raw * I_GAIN / I_SENSE; // 输入功率按电池电压估算实际项目需补一路输入采样 float v_in 3.70f; float p_out v_out * i_out; float p_in p_out / 0.90f; // 估算输入功率精确需实测Iin float eta p_out / p_in * 100.0f; printf(Vout%.2fV Iout%.3fA Pout%.3fW Eta%.1f%%\r\n, v_out, i_out, p_out, eta); }注意Power_Compute里用了float。STM32F103没有硬件浮点单元float运算是用软件库模拟的每次效率计算多花几十微秒。10kHz采样频率下每秒算10000次float乘除会占掉不少CPU时间。实际工程中要么降低计算频率每100ms算一次要么全部改定点数。定点做法是把电压电流先放大1000倍存成int32效率用整数除法算。精度足够CPU占用几乎为零。4.3 过流保护与软启动采样结果参与闭环同时采样的价值不只为了显示还在于让采样结果直接参与保护和闭环控制。过流保护最简单的做法是软件比较连续N次检测到电流超过阈值才动作防止单点噪声误触发#define OVERCURRENT_MA 3000 // 过流阈值单位mA #define OVERCURRENT_CNT 5 // 连续5次判定过流 uint8_t overcurrent_count 0; uint8_t overcurrent_flag 0; void Overcurrent_Detect(uint16_t i_raw) { uint16_t i_ma (uint16_t)((float)i_raw * I_GAIN / I_SENSE * 1000.0f); if (i_ma OVERCURRENT_MA) { if (overcurrent_count OVERCURRENT_CNT) { overcurrent_flag 1; // 拉低Boost芯片EN脚或关闭PWM输出 GPIO_ResetBits(GPIOB, GPIO_Pin_5); } } else { overcurrent_count 0; } }阈值和去抖次数要按实际负载特性调。4G模组发射时电流短时间超过平均值是正常的阈值设太低会导致误保护保护恢复逻辑也要设计好常见做法是限制恢复次数比如30秒内只允许恢复3次超过后锁定断电。软启动方面如果Boost芯片没有内置软启动可以在软件里控制EN引脚上电后先输出一个低占空比的PWM信号给负载开关让输出电容缓慢充电避免冲击电流拉低输入电压。配合ADC采样能看到启动瞬间电压电流波形确认没有过冲后再切换到正常运行状态。5. 用Keil调试Boost采样SWV波形、printf与采样时刻校准5.1 把printf重定向到调试串口Keil下最直接的观察手段是重定向printf到USART1再配合串口助手看数据。使用Keil自带的MicroLIB重定向只需要一个函数int fputc(int ch, FILE *f) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); USART_SendData(USART1, (uint8_t)ch); return ch; }在Keil工程里勾选“Use MicroLIB”否则fputc的重定向会因为半主机模式卡死。串口波特率1152001ms打印一次电压电流效率观察4G模组发射周期内的动态响应。如果不想占用串口Keil的SWV功能可以直接看变量波形。在调试模式下打开“Trace”设置配置内核时钟为72MHz然后在“Logic Analyzer”窗口添加需要观察的全局变量例如adc_v_raw和adc_i_raw。SWV的优点是几乎不侵入代码缺点是F103的SWO引脚带宽有限变量刷新率太高时数据会丢。5.2 用SW节点波形校准ADC采样时刻Boost电路的采样精度问题一半在硬件布局一半在采样时刻。用示波器看Boost芯片的SW引脚能看到周期性开关方波方波的上升沿和下降沿都有振铃。如果ADC触发时刻正好落在边沿上采样结果会被开关噪声污染。解决方法有两种。一种是用固定频率定时器触发确保触发时刻避开实际开关边沿更彻底的做法是用SW信号本身去同步ADC触发——SW引脚经反相器整形后接到STM32定时器的外部触发输入把触发点配到开关管关断的中间位置这正好是电感续流最平稳的时间窗口。校准后用固定负载记录一组实测数据负载电流万用表输出电压固件采样电压误差0A12.02V12.01V-0.08%0.5A11.98V11.96V-0.17%1.0A11.93V11.90V-0.25%2.0A11.81V11.76V-0.42%误差随电流增大而增大说明采样时刻还是偏向了功率开关噪声区域或者电流检测放大器的带宽限制了峰值跟随能力。把这一组数据代回标定公式重新计算增益和偏置下一轮固件的误差通常能压到1%以内。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价