【STM32设计】基于STM32的数控电源(硬件+代码+论文) 0-48V输出,BUCK-BOOST自动升降压,带有输出过压、过流保护,输入欠压保护。输入输出电压、电流显示_stm32数控电源
资料下载:
1、实现功能
以12-48V直流电作为输入,通过BUCK-BOOST电路实现0-48V的可调输出电压,最大电流5A。控制方面,采用STM32F334作为控制器,利用内部ADC实现电流和电压检测,GS8552-SR输出模拟信号以控制BUCK-BOOST电路,并利用OLED液晶显示当前输出电压和工作状态。在功能上,用户可通过按键和调节输出电压,每次调节步进为0.1V,并且具有具备多种保护功能,可以在电源板出现异常情况时切断输出。
可增加的功能:
主要元器件:
目录
-
- 资料下载:
- 1、实现功能
- 2、硬件介绍
-
- 1、硬件拓扑介绍
- 2、实物图
- 3、实物演示视频
- 3、代码
-
- 1、PID代码
- 2、输入输出保护代码
- 4、原理图/PCB
- 5、论文、参数计算
-
- 1、电感计算
- 2、电容计算
- 3、信号调理电路
2、硬件介绍
1、硬件拓扑介绍
双向BUCK-BOOST 电路拓扑是由同步 BUCK 电路和同步 BOOST 电路级
联而成。传统的BUCK电路和BOOST电路中由二极管续流,但在低压大电流场
合,由于二极管上存在导通压降,会引起较大的导通损耗。利用MOS管代替传
统的BUCK电路和BOOST电路中的续流二极管,由于MOS管开通时的管压降
相对较低,能够显著降低电路中半导体的导通损耗,这种方式称为同步整流。
硬件拓扑如图所示:
以左侧为输入,右侧为输出为例子,分析电路工作原理。当Q4常闭,Q3常
开,Q1与Q2以特定占空比互补导通,则电路工作于BUCK模式,如图1.2所
示;当 Q1 常闭,Q2 常开,Q3 和 Q4 以特定占空比互补导通,则电路工作于
BOOST 模式,如图1.3所示;当Q1和Q2,Q3和Q4均特定占空比互补导通,
则电路工作于BUCK-BOOST模式(MIX混合模式)
2、实物图
3、实物演示视频
3、代码
1、PID代码
STM32代码采用C语言,HAL库编写,软件是keil5,使用PID算法控制输出电压,200Khz采样率降低纹波,ADC+DMA+定时器触发采样输出输出电压和电流数据。
//环路的参数buck输出-恒压-PID型补偿器#define BUCKPIDb05203//Q8#define BUCKPIDb1-10246//Q8#define BUCKPIDb25044//Q8//环路的参数BOOST输出-恒压-PID型补偿器#define BOOSTPIDb08860//Q8#define BOOSTPIDb1-17445//Q8#define BOOSTPIDb28588//Q8CCMRAM void BuckBoostVLoopCtlPID(void){int32_t VoutTemp=0;//输出电压矫正后//输出电压矫正VoutTemp = ((uint32_t )ADC1_RESULT[2]*CAL_VOUT_K>>12)+CAL_VOUT_B;//计算电压误差量,当参考电压大于输出电压,占空比增加,输出量增加VErr0= CtrValue.Voref - VoutTemp; //当模式切换时,认为降低占空比,确保模式切换不过冲//BBModeChange为模式切换为,不同模式切换时,该位会被置1if(DF.BBModeChange){u1 = 0;DF.BBModeChange =0;}//判断工作模式,BUCK,BOOST,BUCK-BOOSTswitch(DF.BBFlag){case NA ://初始阶段{VErr0=0;VErr1=0;VErr2=0;u0 = 0;u1 = 0;break;}case Buck://BUCK模式{//调用PID环路计算公式u0 = u1 + VErr0*BUCKPIDb0 + VErr1*BUCKPIDb1 + VErr2*BUCKPIDb2;//历史数据幅值VErr2 = VErr1;VErr1 = VErr0;u1 = u0;//环路输出赋值,u0右移8位为BUCKPIDb0-2为人为放大Q8倍的数字量CtrValue.BuckDuty= u0>>8;CtrValue.BoostDuty=MIN_BOOST_DUTY1;//BOOST上管固定占空比93%,下管7%//环路输出最大最小占空比限制if(CtrValue.BuckDuty > CtrValue.BUCKMaxDuty)CtrValue.BuckDuty = CtrValue.BUCKMaxDuty;if(CtrValue.BuckDuty < MIN_BUKC_DUTY)CtrValue.BuckDuty = MIN_BUKC_DUTY;break;}case Boost://Boost模式{//调用PID环路计算公式(参照PID环路计算文档)u0 = u1 + VErr0*BOOSTPIDb0 + VErr1*BOOSTPIDb1 + VErr2*BOOSTPIDb2;//历史数据幅值VErr2 = VErr1;VErr1 = VErr0;u1 = u0;//环路输出赋值,u0右移8位为BUCKPIDb0-2为人为放大Q8倍的数字量CtrValue.BuckDuty = MAX_BUCK_DUTY;//否则固定占空比93%CtrValue.BoostDuty = u0>>8;//环路输出最大最小占空比限制if(CtrValue.BoostDuty > CtrValue.BoostMaxDuty)CtrValue.BoostDuty = CtrValue.BoostMaxDuty;if(CtrValue.BoostDuty < MIN_BOOST_DUTY)CtrValue.BoostDuty = MIN_BOOST_DUTY;break;}case Mix://Mix模式{//调用PID环路计算公式u0 = u1 + VErr0*BOOSTPIDb0 + VErr1*BOOSTPIDb1 + VErr2*BOOSTPIDb2;//历史数据幅值VErr2 = VErr1;VErr1 = VErr0;u1 = u0;//环路输出赋值,u0右移8位为BUCKPIDb0-2为人为放大Q8倍的数字量CtrValue.BuckDuty = MAX_BUCK_DUTY1;//否则固定占空比80%CtrValue.BoostDuty = u0>>8;//环路输出最大最小占空比限制if(CtrValue.BoostDuty > CtrValue.BoostMaxDuty)CtrValue.BoostDuty = CtrValue.BoostMaxDuty;if(CtrValue.BoostDuty < MIN_BOOST_DUTY)CtrValue.BoostDuty = MIN_BOOST_DUTY;break;}}//PWMENFlag是PWM开启标志位,当该位为0时,buck的占空比为0,无输出;if(DF.PWMENFlag==0)CtrValue.BuckDuty = MIN_BUKC_DUTY;//更新对应寄存器HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP1xR = CtrValue.BuckDuty * PERIOD>>12; //buck占空比 HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP3xR = HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP1xR>>1; //ADC触发采样点HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].CMP1xR = PERIOD - (CtrValue.BoostDuty * PERIOD>>12);//Boost占空比}
2、输入输出保护代码
以下为输出模式,输出过压、过流,温度保护。以及输出过压、过流保护实现代码。
程序根据输入输出电压的关系判断模块运行在BUCK模式,BOOST模式还是MIX模式(BUCK-BOOST模式)。 模块上电初始化后默认模式状态为NA,当输出电压参考量小于0.8倍的输入电压时,进入BUCK模式;当输出电压参考量大于1.2倍的输入电压时,进入BOOST 模式;否则输出电压参考量在0.8倍和1.2倍输入电压之间,进入MIX
模式化;
当模块为BUCK模式运行时,输出电压参考量大于1.2倍的输入电压时,进入BOOST模式;为了保证模块运行模式在不同模式之间切换频繁,设置模式切换的滞环效果,模块处于BUCK模式下,当输出电压参考量大于0.85倍的输入
电压时,进入MIX模式。
当模块为BOOST模式运行时,输出电压参考量小于0.8倍的输入电压时,进入 BUCK 模式;为了保证模块运行模式在不同模式之间切换频繁,设置模式切换的滞环效果,模块处于BOOST模式下,当输出电压参考量小于1.15倍的输
入电压时,进入MIX模式。
当模块为MIX模式运行时,输出电压参考量小于0.8倍的输入电压时,进入BUCK模式;当输出电压参考量大于1.2倍的输入电压时,进入BOOST模式。 由于不同工作模式状态下,环路的控制方式不同,当运行模式发生变换时,
需要对环路运算过程变量复位。模式判断函数定义PreBBFlag保存当前模式,当执行完模式判断后,若PreBBFlag保存的模式和新模式不同,则认为模块运行模式发生变化,模式变化标志位DF.BBModeChange置1。
1、初始化状态至空闲状态:上电程序初始化后跳转。
2、空闲状态至软启动状态:等待3S后自动跳转。
3、软启动状态至正常运行状态:正常启动结束后。
4、软启动状态至故障状态:启动过程中发生故障或保护。
5、正常运行状态至故障状态:正常运行过程中发生故障或保护。
6、故障状态至空闲状态:故障消除后自动跳转,模块自动恢复启动。
#include \"function.h\"//功能函数头文件#include \"CtlLoop.h\"//控制环路头文件struct _ADI SADC={0,0,2048,0,0,0,0,2048,0,0,0,0};//输入输出参数采样值和平均值struct _Ctr_value CtrValue={0,0,0,MIN_BUKC_DUTY,0,0,0};//控制参数struct _FLAG DF={0,0,0,0,0,0,0,0};//控制标志位uint16_t ADC1_RESULT[4]={0,0,0,0};//ADC采样外设到内存的DMA数据保存寄存器//软启动状态标志位SState_M STState = SSInit ;//OLED刷新计数 5mS计数一次,在5mS中断里累加uint16_t OLEDShowCnt=0;/*** ===================================================================** Funtion Name : void ADCSample(void)** Description : 采样输出电压、输出电流、输入电压、输入电流** Parameters :** Returns :** ===================================================================*/CCMRAM void ADCSample(void){//输入输出采样参数求和,用以计算平均值static uint32_t VinAvgSum=0,IinAvgSum=0,VoutAvgSum=0,IoutAvgSum=0;//从DMA缓冲器中获取数据 Q15,并对其进行线性矫正-采用线性矫正SADC.Vin = ((uint32_t )ADC1_RESULT[0]*CAL_VIN_K>>12)+CAL_VIN_B;SADC.Iin = (((int32_t )ADC1_RESULT[1]-SADC.IinOffset)*CAL_IIN_K>>12)+CAL_IIN_B;SADC.Vout = ((uint32_t )ADC1_RESULT[2]*CAL_VOUT_K>>12)+CAL_VOUT_B;SADC.Iout = (((int32_t )ADC1_RESULT[3] - SADC.IoutOffset)*CAL_IOUT_K>>12)+CAL_IOUT_B;if(SADC.Vin <100 )//采样有零偏离,采样值很小时,直接为0SADC.Vin = 0;if(SADC.Iin <0 )//对电流采样限制,当采样值小于SADC.IinOffset时SADC.Iin =0;if(SADC.Vout <100 )SADC.Vout = 0;if(SADC.Iout <0 )SADC.Iout = 0;//计算各个采样值的平均值-滑动平均方式VinAvgSum = VinAvgSum + SADC.Vin -(VinAvgSum>>2);//求和,新增入一个新的采样值,同时减去之前的平均值。SADC.VinAvg = VinAvgSum>>2;//求平均IinAvgSum = IinAvgSum + SADC.Iin -(IinAvgSum>>2);SADC.IinAvg = IinAvgSum >>2;VoutAvgSum = VoutAvgSum + SADC.Vout -(VoutAvgSum>>2);SADC.VoutAvg = VoutAvgSum>>2;IoutAvgSum = IoutAvgSum + SADC.Iout -(IoutAvgSum>>2);SADC.IoutAvg = IoutAvgSum>>2;}/** ===================================================================** Funtion Name :void StateM(void)** Description : 状态机函数,在5ms中断中运行,5ms运行一次** 初始化状态** 等外启动状态** 启动状态** 运行状态** 故障状态** Parameters :** Returns :** ===================================================================*/void StateM(void){//判断状态类型switch(DF.SMFlag){//初始化状态case Init :StateMInit();break;//等待状态case Wait :StateMWait();break;//软启动状态case Rise :StateMRise();break;//运行状态case Run :StateMRun();break;//故障状态case Err :StateMErr();break;}}/** ===================================================================** Funtion Name :void StateMInit(void)** Description : 初始化状态函数,参数初始化** Parameters :** Returns :** ===================================================================*/void StateMInit(void){//相关参数初始化ValInit();//状态机跳转至等待软启状态DF.SMFlag = Wait;}/** ===================================================================** Funtion Name :void StateMWait(void)** Description : 等待状态机,等待1S后无故障则软启** Parameters :** Returns :** ===================================================================*/void StateMWait(void){//计数器定义static uint16_t CntS = 0;static uint32_tIinSum=0,IoutSum=0;//关PWMDF.PWMENFlag=0;//计数器累加CntS ++;//等待*S,采样输入和输出电流偏置好后, 且无故障情况,切按键按下,启动,则进入启动状态if(CntS>256){CntS=256;HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //开启PWM输出和PWM计时器if((DF.ErrFlag==F_NOERR)&&(DF.KeyFlag1==1)){//计数器清0CntS=0;IinSum=0;IoutSum=0;//状态标志位跳转至等待状态DF.SMFlag = Rise;//软启动子状态跳转至初始化状态STState = SSInit;}}else//进行输入和输出电流1.65V偏置求平均{ //输入输出电流偏置求和 IinSum += ADC1_RESULT[1];IoutSum += ADC1_RESULT[3]; //256次数 if(CntS==256) { //求平均SADC.IinOffset = IinSum >>8; SADC.IoutOffset = IoutSum >>8; }}}/*** ===================================================================** Funtion Name : void StateMRise(void)** Description :软启阶段** 软启初始化** 软启等待** 开始软启** Parameters : none** Returns : none** ===================================================================*/#define MAX_SSCNT 20//等待100msvoid StateMRise(void){//计时器static uint16_t Cnt = 0;//最大占空比限制计数器static uint16_tBUCKMaxDutyCnt=0,BoostMaxDutyCnt=0;//判断软启状态switch(STState){//初始化状态case SSInit:{//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//软启中将运行限制占空比启动,从最小占空比开始启动CtrValue.BUCKMaxDuty = MIN_BUKC_DUTY;CtrValue.BoostMaxDuty = MIN_BOOST_DUTY;//环路计算变量初始化VErr0=0;VErr1=0;VErr2=0;u0 = 0;u1 = 0;//跳转至软启等待状态STState = SSWait;break;}//等待软启动状态case SSWait:{//计数器累加Cnt++;//等待100msif(Cnt> MAX_SSCNT){//计数器清0Cnt = 0;//限制启动占空比CtrValue.BuckDuty = MIN_BUKC_DUTY;CtrValue.BUCKMaxDuty= MIN_BUKC_DUTY;CtrValue.BoostDuty = MIN_BOOST_DUTY;CtrValue.BoostMaxDuty = MIN_BOOST_DUTY;//环路计算变量初始化VErr0=0;VErr1=0;VErr2=0;u0 = 0;u1 = 0;//CtrValue.Voref输出参考电压从一半开始启动,避免过冲,然后缓慢上升CtrValue.Voref = CtrValue.Voref >>1;STState = SSRun;//跳转至软启状态}break;}//软启动状态case SSRun:{if(DF.PWMENFlag==0)//正式发波前环路变量清0{//环路计算变量初始化VErr0=0;VErr1=0;VErr2=0;u0 = 0;u1 = 0;HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //开启PWM输出和PWM计时器HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //开启PWM输出和PWM计时器}//发波标志位置位DF.PWMENFlag=1;//最大占空比限制逐渐增加BUCKMaxDutyCnt++;BoostMaxDutyCnt++;//最大占空比限制累加CtrValue.BUCKMaxDuty = CtrValue.BUCKMaxDuty + BUCKMaxDutyCnt*5;CtrValue.BoostMaxDuty = CtrValue.BoostMaxDuty + BoostMaxDutyCnt*5;//累加到最大值if(CtrValue.BUCKMaxDuty > MAX_BUCK_DUTY)CtrValue.BUCKMaxDuty = MAX_BUCK_DUTY ;if(CtrValue.BoostMaxDuty > MAX_BOOST_DUTY)CtrValue.BoostMaxDuty = MAX_BOOST_DUTY ;if((CtrValue.BUCKMaxDuty==MAX_BUCK_DUTY)&&(CtrValue.BoostMaxDuty==MAX_BOOST_DUTY)){//状态机跳转至运行状态DF.SMFlag = Run;//软启动子状态跳转至初始化状态STState = SSInit;}break;}default:break;}}/*** ===================================================================** Funtion Name :void StateMRun(void)** Description :正常运行,主处理函数在中断中运行** Parameters : none** Returns : none** ===================================================================*/void StateMRun(void){}/*** ===================================================================** Funtion Name :void StateMErr(void)** Description :故障状态** Parameters : none** Returns : none** ===================================================================*/void StateMErr(void){//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//若故障消除跳转至等待重新软启if(DF.ErrFlag==F_NOERR)DF.SMFlag = Wait;}/** ===================================================================** Funtion Name :void ValInit(void)** Description : 相关参数初始化函数** Parameters :** Returns :** ===================================================================*/void ValInit(void){//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//清除故障标志位DF.ErrFlag=0;//初始化电压参考量CtrValue.Voref=0;//限制占空比CtrValue.BuckDuty = MIN_BUKC_DUTY;CtrValue.BUCKMaxDuty= MIN_BUKC_DUTY;CtrValue.BoostDuty = MIN_BOOST_DUTY;CtrValue.BoostMaxDuty = MIN_BOOST_DUTY;//环路计算变量初始化VErr0=0;VErr1=0;VErr2=0;u0 = 0;u1 = 0;}/** ===================================================================** Funtion Name :void VrefGet(void)** Description : 从滑动变阻器值获取输出电压参考值,调整滑动电位器,CtrValue.Voref变换,当电压参考值变化时,缓慢增加** Parameters :** Returns :** ===================================================================*/#define MAX_VREF 2921//最大输出参考电压48V 0.5V的余量 48.5V/68V*Q12 Vsmax=68V#define MIN_VREF 60//最低输出电压参考值5V 0.5V的余量 4.5V/68V*Q12#define VREF_K 5//递增或递减步长void VrefGet(void){////电压参考值中间变量//int32_t VTemp = 0;////滑动平均求和中间变量//static int32_t VadjSum = 0;////获取ADC采样值-读滑动电位器上的电压//SADC.Vadj = HAL_ADC_GetValue(&hadc2);//对采样值滑动求平均//VadjSum = VadjSum + SADC.Vadj -(VadjSum>>8);//SADC.VadjAvg = VadjSum>>8;//////参考电压 = MIN_VREF+滑动变阻器采样值,MIN_VREF为最低输出电压。//VTemp = MIN_VREF + SADC.Vadj;//////缓慢递增或缓慢递减电压参考值//if( VTemp> ( CtrValue.Voref + VREF_K))//CtrValue.Voref = CtrValue.Voref + VREF_K;//else if( VTemp < ( CtrValue.Voref - VREF_K ))//CtrValue.Voref =CtrValue.Voref - VREF_K;//else//CtrValue.Voref = VTemp ;////MIX模式下调压限制-输出电压最大达到输入电压的2倍//if(CtrValue.Voref >(SADC.VinAvg<<1))//输出限制在输入的2*vin //CtrValue.Voref =(SADC.VinAvg<<1);//if( CtrValue.Voref >MAX_VREF )//CtrValue.Voref =MAX_VREF;}/*** ===================================================================** Funtion Name :void ShortOff(void)** Description :短路保护,可以重启10次** Parameters : none** Returns : none** ===================================================================*/#define MAX_SHORT_I 1396//短路电流判据#define MIN_SHORT_V 289//短路电压判据void ShortOff(void){static int32_t RSCnt = 0;static uint8_t RSNum =0 ;//当输出电流大于 *A,且电压小于*V时,可判定为发生短路保护if((SADC.Iout> MAX_SHORT_I)&&(SADC.Vout <MIN_SHORT_V)){//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//故障标志位setRegBits(DF.ErrFlag,F_SW_SHORT);//跳转至故障状态DF.SMFlag =Err;}//输出短路保护恢复//当发生输出短路保护,关机后等待4S后清楚故障信息,进入等待状态等待重启if(getRegBits(DF.ErrFlag,F_SW_SHORT)){//等待故障清楚计数器累加RSCnt++;//等待2Sif(RSCnt >400){//计数器清零RSCnt=0;//短路重启只重启10次,10次后不重启if(RSNum > 10){//确保不清除故障,不重启RSNum =11;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭}else{//短路重启计数器累加RSNum++;//清除过流保护故障标志位clrRegBits(DF.ErrFlag,F_SW_SHORT);}}}}/*** ===================================================================** Funtion Name :void SwOCP(void)** Description :软件过流保护,可重启** Parameters : none** Returns : none** ===================================================================*/#define MAX_OCP_VAL 1117//*A过流保护点 void SwOCP(void){//过流保护判据保持计数器定义static uint16_t OCPCnt=0;//故障清楚保持计数器定义static uint16_t RSCnt=0;//保留保护重启计数器static uint16_t RSNum=0;//当输出电流大于*A,且保持500msif((SADC.Iout > MAX_OCP_VAL)&&(DF.SMFlag ==Run)){//条件保持计时OCPCnt++;//条件保持50ms,则认为过流发生if(OCPCnt > 10){//计数器清0OCPCnt = 0;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//故障标志位setRegBits(DF.ErrFlag,F_SW_IOUT_OCP);//跳转至故障状态DF.SMFlag =Err;}}else//计数器清0OCPCnt = 0;//输出过流后恢复//当发生输出软件过流保护,关机后等待4S后清楚故障信息,进入等待状态等待重启if(getRegBits(DF.ErrFlag,F_SW_IOUT_OCP)){//等待故障清楚计数器累加RSCnt++;//等待2Sif(RSCnt > 400){//计数器清零RSCnt=0;//过流重启计数器累加RSNum++;//过流重启只重启10次,10次后不重启(严重故障)if(RSNum > 10 ){//确保不清除故障,不重启RSNum =11;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭}else{ //清除过流保护故障标志位clrRegBits(DF.ErrFlag,F_SW_IOUT_OCP);}}}}/*** ===================================================================** Funtion Name :void SwOVP(void)** Description :软件输出过压保护,不重启** Parameters : none** Returns : none** ===================================================================*/#define MAX_VOUT_OVP_VAL 3180//50V过压保护(48*110%/68)*Q12void VoutSwOVP(void){//过压保护判据保持计数器定义static uint16_t OVPCnt=0;//当输出电压大于50V,且保持100msif (SADC.Vout > MAX_VOUT_OVP_VAL){//条件保持计时OVPCnt++;//条件保持10msif(OVPCnt > 2){//计时器清零OVPCnt=0;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//故障标志位setRegBits(DF.ErrFlag,F_SW_VOUT_OVP);//跳转至故障状态DF.SMFlag =Err;}}elseOVPCnt = 0;}/*** ===================================================================** Funtion Name :void VinSwUVP(void)** Description :输入软件欠压保护,低压输入保护,可恢复** Parameters : none** Returns : none** ===================================================================*/#define MIN_UVP_VAL 686//11.4V欠压保护 (11.4/68 )*Q12#define MIN_UVP_VAL_RE 795//13.2V欠压保护恢复 (13.2/68)*Q12void VinSwUVP(void){//过压保护判据保持计数器定义static uint16_t UVPCnt=0;static uint16_tRSCnt=0;//当输出电流小于于11.4V,且保持200msif ((SADC.Vin < MIN_UVP_VAL) && (DF.SMFlag != Init )){//条件保持计时UVPCnt++;//条件保持10msif(UVPCnt > 2){//计时器清零UVPCnt=0;RSCnt=0;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//故障标志位setRegBits(DF.ErrFlag,F_SW_VIN_UVP);//跳转至故障状态DF.SMFlag =Err;}}elseUVPCnt = 0;//输入欠压保护恢复//当发生输入欠压保护,等待输入电压恢复至正常水平后清楚故障标志位,重启if(getRegBits(DF.ErrFlag,F_SW_VIN_UVP)){if(SADC.Vin > MIN_UVP_VAL_RE) {//等待故障清楚计数器累加RSCnt++;//等待1Sif(RSCnt > 200){RSCnt=0;UVPCnt=0;//清楚故障标志位clrRegBits(DF.ErrFlag,F_SW_VIN_UVP);}}elseRSCnt=0;}elseRSCnt=0;}/*** ===================================================================** Funtion Name :void VinSwOVP(void)** Description :软件输入过压保护,不重启** Parameters : none** Returns : none** ===================================================================*/#define MAX_VIN_OVP_VAL 3012//50V过压保护(50/68)*Q12void VinSwOVP(void){//过压保护判据保持计数器定义static uint16_t OVPCnt=0;//当输出电压大于50V,且保持100msif (SADC.Vin > MAX_VIN_OVP_VAL ){//条件保持计时OVPCnt++;//条件保持10msif(OVPCnt > 2){//计时器清零OVPCnt=0;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭//故障标志位setRegBits(DF.ErrFlag,F_SW_VIN_OVP);//跳转至故障状态DF.SMFlag =Err;}}elseOVPCnt = 0;}/** ===================================================================** Funtion Name :void LEDShow(void)** Description : LED显示函数** 初始化与等待启动状态,红黄绿全亮** 启动状态,黄绿亮** 运行状态,绿灯亮** 故障状态,红灯亮** Parameters :** Returns :** ===================================================================*///输出状态灯宏定义 #define SET_LED_G()HAL_GPIO_WritePin(GPIOB, LED_G_Pin,GPIO_PIN_SET)//绿灯亮 #define SET_LED_Y()HAL_GPIO_WritePin(GPIOB, LED_Y_Pin,GPIO_PIN_SET)//绿灯亮 #define SET_LED_R()HAL_GPIO_WritePin(GPIOB, LED_R_Pin,GPIO_PIN_SET)//绿灯亮 #define CLR_LED_G()HAL_GPIO_WritePin(GPIOB, LED_G_Pin,GPIO_PIN_RESET)//绿灯灭 #define CLR_LED_Y()HAL_GPIO_WritePin(GPIOB, LED_Y_Pin,GPIO_PIN_RESET)//黄灯灭 #define CLR_LED_R()HAL_GPIO_WritePin(GPIOB, LED_R_Pin,GPIO_PIN_RESET)//红灯灭void LEDShow(void){switch(DF.SMFlag){//初始化状态,红黄绿全亮case Init :{SET_LED_G();SET_LED_Y();SET_LED_R();break;}//等待状态,红黄绿全亮case Wait :{SET_LED_G();SET_LED_Y();SET_LED_R();break;}//软启动状态,黄绿亮case Rise :{SET_LED_G();SET_LED_Y();CLR_LED_R();break;}//运行状态,绿灯亮case Run :{SET_LED_G();CLR_LED_Y();CLR_LED_R();break;}//故障状态,红灯亮case Err :{CLR_LED_G();CLR_LED_Y();SET_LED_R();break;}}}/** ===================================================================** Funtion Name :void KEYFlag(void)** Description :两个按键的状态** 默认状态KEYFlag为0.按下时Flag变1,再次按下Flag变0,依次循环** 当机器正常运行,或者启动过程中,按下按键后,关闭输出,进入待机状态** Parameters :** Returns :** ===================================================================*/#define READ_KEY1() HAL_GPIO_ReadPin(GPIOB, KEY_1_Pin)#define READ_KEY2() HAL_GPIO_ReadPin(GPIOB, KEY_2_Pin)void KEYFlag(void){//计时器,按键消抖用static uint16_tKeyDownCnt1=0,KeyDownCnt2=0;//按键按下if(READ_KEY1()==0){//计时,按键按下150mS有效KeyDownCnt1++;if(KeyDownCnt1 > 30){KeyDownCnt1 = 0;//计时器清零//按键状态有变化if(DF.KeyFlag1==0)DF.KeyFlag1 = 1;elseDF.KeyFlag1 = 0;}}elseKeyDownCnt1 = 0;//计时器清零//按键按下if(READ_KEY2()==0){//计时,按键按??0mS有效KeyDownCnt2++;if(KeyDownCnt2 > 30){KeyDownCnt2 = 0;//计时器清零//按键状态有变化if(DF.KeyFlag2==0)DF.KeyFlag2 = 1;elseDF.KeyFlag2 = 0;}}elseKeyDownCnt2 = 0;//计时器清零//当机器正常运行,或者启动过程中,按下按键后,关闭输出,进入待机状态if((DF.KeyFlag1==0)&&((DF.SMFlag==Rise)||(DF.SMFlag==Run))){DF.SMFlag = Wait;//关闭PWMDF.PWMENFlag=0;HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //关闭HAL_HRTIM_WaveformOutputStop(&hhrtim1, HRTIM_OUTPUT_TB1|HRTIM_OUTPUT_TB2); //关闭}}/** ===================================================================** Funtion Name :void BBMode(void)** Description :运行模式判断** BUCK模式:输出参考电压1.2倍输入电压** MIX模式:1.15倍输入电压>输出参考电压>0.85倍输入电压** 当进入MIX(buck-boost)模式后,退出到BUCK或者BOOST时需要滞缓,防止在临界点来回振荡** Parameters :** Returns :** ===================================================================*/void BBMode(void){//上一次模式状态量uint8_t PreBBFlag=0;//暂存当前的模式状态量PreBBFlag = DF.BBFlag;//判断当前模块的工作模式switch(DF.BBFlag){//NA-初始化模式case NA :{ if(CtrValue.Voref < ((SADC.VinAvg*3277)>>12))//vout<0.8*vinDF.BBFlag = Buck;//buck modeelse if(CtrValue.Voref > ((SADC.VinAvg*4915)>>12))//vout>1.2*vinDF.BBFlag = Boost;//boost modeelseDF.BBFlag = Mix;//buck-boost(MIX) modebreak;}//BUCK模式case Buck :{if(CtrValue.Voref > ((SADC.VinAvg*4915)>>12))//vout>1.2*vinDF.BBFlag = Boost;//boost modeelse if(CtrValue.Voref >((SADC.VinAvg*3482)>>12))//1.2*vin>vout>0.85*vinDF.BBFlag = Mix;//buck-boost(MIX) modebreak;}//Boost模式case Boost :{if(CtrValue.Voref < ((SADC.VinAvg*3277)>>12))//vout<0.8*vinDF.BBFlag = Buck;//buck modeelse if(CtrValue.Voref < ((SADC.VinAvg*4710)>>12))//0.8*vin<vout<1.15*vinDF.BBFlag = Mix;//buck-boost(MIX) modebreak;}//Mix模式case Mix :{ if(CtrValue.Voref < ((SADC.VinAvg*3277)>>12))//vout<0.8*vinDF.BBFlag = Buck;//buck modeelse if(CtrValue.Voref > ((SADC.VinAvg*4915)>>12))//vout>1.2*vinDF.BBFlag = Boost;//boost modebreak;}}//当模式发生变换时(上一次和这一次不一样),则标志位置位,标志位用以环路计算复位,保证模式切换过程不会有大的过冲if(PreBBFlag==DF.BBFlag)DF.BBModeChange =0;elseDF.BBModeChange =1;}/** ===================================================================** Funtion Name :void MX_OLED_Init(void)** Description :OLED初始化函数** 通用OLED驱动程序** Parameters :** Returns :** ===================================================================*/void MX_OLED_Init(void){//初始化OLEDOLED_Init();OLED_CLS();//以下显示固定的字符OLED_ShowStr(25,0,\"BUCK-BOOST\",2);//OLED_ShowStr(0,2,\"State:\",2);OLED_ShowStr(16,2,\".\",2); OLED_ShowStr(32,2,\"V\",2);OLED_ShowStr(88,4,\".\",2); OLED_ShowStr(112,4,\"V\",2); OLED_ShowStr(16,4,\".\",2); OLED_ShowStr(40,4,\"V\",2);OLED_ShowStr(88,6,\".\",2); OLED_ShowStr(112,6,\"A\",2); OLED_ShowStr(16,6,\".\",2); OLED_ShowStr(40,6,\"A\",2);OLED_ON(); }/** ===================================================================** Funtion Name :void OLEDShow(void)** Description : OLED显示函数 ** 显示运行模式-BUCK MODE,BOOST MODE,MIX MODE** 显示状态:IDEL,RISISING,RUNNING,ERROR** 显示输出电压:两位小数** 显示输出电流:两位小数** Parameters :** Returns :** ===================================================================*/void OLEDShow(void){u8 VOtemp[4]={0,0,0,0};u8 IOtemp[4]={0,0,0,0};u8 VItemp[4]={0,0,0,0};u8 IItemp[4]={0,0,0,0};u8 VStemp[4]={0,0,0,0};uint32_t VoutT=0,IoutT=0;uint32_t VinT=0,IinT=0,VadjT=0;static uint16_t BBFlagTemp=10,SMFlagTemp=10;//将采样值转换成实际值,并扩大100倍(显示屏幕带小数点)如果显示输入电压电流,则打开另外注释掉的计算VoutT = SADC.VoutAvg*6800>>12; //校准 6800*1.015IoutT = SADC.IoutAvg*1100>>12;VinT = SADC.VinAvg*6800>>12; //6800*IinT = SADC.IinAvg*1100>>12;VadjT = CtrValue.Voref*6800>>12;//分别保存实际电压和电流的每一位,小数点后两位保留,如果显示输入电压电流,则打开另外注释掉的计算//输出电压VOtemp[0] = (u8)(VoutT/1000);VOtemp[1] = (u8)((VoutT-(uint8_t)VOtemp[0]*1000)/100);VOtemp[2] = (u8)((VoutT-(uint16_t)VOtemp[0]*1000-(uint16_t)VOtemp[1]*100)/10);VOtemp[3] = (u8)(VoutT-(uint16_t)VOtemp[0]*1000-(uint16_t)VOtemp[1]*100-(uint16_t)VOtemp[2]*10);//输入电压VItemp[0] = (u8)(VinT/1000);VItemp[1] = (u8)((VinT-(uint8_t)VItemp[0]*1000)/100);VItemp[2] = (u8)((VinT -(uint16_t)VItemp[0]*1000-(uint16_t)VItemp[1]*100)/10);VItemp[3] = (u8)(VinT-(uint16_t)VItemp[0]*1000-(uint16_t)VItemp[1]*100-(uint16_t)VItemp[2]*10);//输出电流IOtemp[0] = (u8)(IoutT/1000);IOtemp[1] = (u8)((IoutT-(uint8_t)IOtemp[0]*1000)/100);IOtemp[2] = (u8)((IoutT-(uint16_t)IOtemp[0]*1000-(uint16_t)IOtemp[1]*100)/10);IOtemp[3] = (u8)(IoutT-(uint16_t)IOtemp[0]*1000-(uint16_t)IOtemp[1]*100-(uint16_t)IOtemp[2]*10);//输入电流IItemp[0] = (u8)(IinT/1000);IItemp[1] = (u8)((IinT-(uint8_t)IItemp[0]*1000)/100);IItemp[2] = (u8)((IinT-(uint16_t)IItemp[0]*1000-(uint16_t)IItemp[1]*100)/10);IItemp[3] = (u8)(IinT-(uint16_t)IItemp[0]*1000-(uint16_t)IItemp[1]*100-(uint16_t)IItemp[2]*10); //参考电压//输入电流//VStemp[0] = (u8)(VadjT/1000);//VStemp[1] = (u8)((VadjT-(uint8_t)VStemp[0]*1000)/100);//VStemp[2] = (u8)((VadjT-(uint16_t)VStemp[0]*1000-(uint16_t)VStemp[1]*100)/10);//VStemp[3] = (u8)(VadjT-(uint16_t)VStemp[0]*1000-(uint16_t)VStemp[1]*100-(uint16_t)VStemp[2]*10); VStemp[0] = V_Key_Set/100;VStemp[1] = V_Key_Set/10%10;VStemp[2] = V_Key_Set%10;//如果运行模式有变化,则更改屏幕if(BBFlagTemp!= DF.BBFlag){//暂存标志位BBFlagTemp = DF.BBFlag;//显示运行模式switch(DF.BBFlag){//NAcase NA :{OLED_ShowStr(25,0,\"MODE:*NA* \",2);break;}//BUCK模式case Buck :{OLED_ShowStr(25,0,\"MODE:BUCK \",2);break;}//Boost模式case Boost :{OLED_ShowStr(25,0,\"MODE:BOOST\",2);break;}//Mix模式case Mix :{OLED_ShowStr(25,0,\"MODE:MIX \",2);break;}}}//电源工作状态有变换,更新屏幕if(SMFlagTemp!= DF.SMFlag){SMFlagTemp = DF.SMFlag;//显示电源工作状态switch(DF.SMFlag){//初始化状态case Init :{OLED_ShowStr(55,2,\"Init \",2);break;}//等待状态case Wait :{OLED_ShowStr(55,2,\"Waiting\",2);break;}//软启动状态case Rise :{OLED_ShowStr(55,2,\"Rising\",2);break;}//运行状态case Run :{OLED_ShowStr(55,2,\"Running\",2);break;}//故障状态case Err :{OLED_ShowStr(55,2,\"Error \",2);break;}}}//显示电压电流每一位OLEDShowData(72,4,VOtemp[0]);OLEDShowData(80,4,VOtemp[1]);OLEDShowData(96,4,VOtemp[2]);OLEDShowData(104,4,VOtemp[3]);OLEDShowData(72,6,IOtemp[0]);OLEDShowData(80,6,IOtemp[1]);OLEDShowData(96,6,IOtemp[2]);OLEDShowData(104,6,IOtemp[3]);//显示电压电流每一位OLEDShowData(0,4,VItemp[0]);OLEDShowData(8,4,VItemp[1]);OLEDShowData(24,4,VItemp[2]);OLEDShowData(32,4,VItemp[3]);OLEDShowData(0,6,IItemp[0]);OLEDShowData(8,6,IItemp[1]);OLEDShowData(24,6,IItemp[2]);OLEDShowData(32,6,IItemp[3]);//设置电压每一位OLEDShowData(0,2,VStemp[0]);OLEDShowData(8,2,VStemp[1]);OLEDShowData(24,2,VStemp[2]);}
4、原理图/PCB
原理图和PCB都使用立创EDA绘制,对新手较为友好。可以导出为AD格式的文件。
原理图主要包括电源电路,为单片机、显示器等提供辅助电源。信号调理电路,包括直流偏执电路,运算放大电路,BUCK-BOOST开关电路等。