练习 电源 基于STM32F103C8T6的单片机降压电路

本文介绍了一个基于STM32F103C8T6单片机的降压(BUCK)开关电源控制电路设计方案。该方案通过软件闭环控制实现电压调节,详细描述了电路的基本要求、发挥部分及实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于STM32F103C8T6的单片机降压电路

一、任务
实验三的电路采用TL494内部的误差放大器实现电压的稳定,叫做硬件闭环控制,优点是控制快速,但缺点是电路复杂,改变PID参数不方便。用软件也可以实现电压的调节,即软件闭环控制,采用单片机产生PWM波驱动,同时在电源输出端采样,进入单片机AD端做比较,当输出电压偏高时,则PWM波占空比减小,使输出电压降低,反之亦然。
按下图设计并制作如图所示的降压(BUCK)开关电源控制电路。

在这里插入图片描述

二、基本要求
1、输入电压VCC为15V,负载51Ω/5W情况下,输出电压调节范围:6~12V,并显示;
2、输出电压可按0.5V的间隔设定,输出电压精度为±0.5V;
3、完成总结报告(4-5页,不含程序)。
三、发挥部分
1、进一步提高输出电压稳定度(输入电压在12~18V范围内改变,输出需保持稳定);
2、进一步提高输出功率,例如达到4W以上;
3、其他。
四、说明
1、不能采用任何专用芯片制作;
2、单片机输出PWM频率在5~10KHz左右,具体数值看实验效果;
3、在输入电压变化情况下,为了保证输出电压稳定不变(发挥部分),需采用反馈控制,通过采集输出电压,并结合一定的控制算法,调节单片机PWM宽度,从而使输出电压达到稳定;
4、制作时应考虑方便测试,合理设置测试点;
5、开关电源设计参考“集成开关电源的设计制作调试与维修”一书。

code part below

main.c

/*****************************************
 * @hardware STM32F103C8T6               
 * @author   CJLU_fmix   
 * @version  V1.0                      
 * @date     2021/04/14               
 *****************************************
 */
/* Includes ------------------------------------*/
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "key.h"
#include "usart.h"	

/* Includes ------------------------------------*/
u16 set_zkb = 8999;
float n = 20.0;
float v_real,v_set = 0;

/* CON -----------------------------------------*/
void CON(void)
{
	if(v_set > v_real)
	{
		if(v_set - v_real > 2000)
			n = n + 5.0;
		else if(v_set - v_real > 400)
			n = n + 2.0;
		else if(v_set - v_real > 150)
		  n = n + 0.1;
		else
			n = n + 0.05;
	}
	else if(v_set < v_real) 
			 {
					if(v_real - v_set > 2000)
						n = n - 5.0;
					else if(v_real - v_set > 400)
						n = n - 2.0;
					else if(v_real - v_set > 150)
						n = n - 0.1;
					else
						n = n - 0.05;
			 }
			 else
				 n = n;
}

void n_limit(void)
{
	if(n>100.0)
		n = 100.0;
}

/* TIM_PWM -------------------------------------*/
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
	 GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  
	                                                    
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	
	TIM_TimeBaseStructure.TIM_Period = arr; 
	TIM_TimeBaseStructure.TIM_Prescaler =psc;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  

  TIM_CtrlPWMOutputs(TIM1,ENABLE);

	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);	 
	
	TIM_ARRPreloadConfig(TIM1, ENABLE); 
	
	TIM_Cmd(TIM1, ENABLE); 
 
}

/* ExtiSet -------------------------------------*/
void EXTIX_Init(void)
{
  EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

	B8_Init();
    //GPIOB.0
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);

  EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);	 	
		
	//GPIOB.15
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);

  EXTI_InitStructure.EXTI_Line=EXTI_Line15;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);	  	
		
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;					
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure); 
 
  NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;			
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;							
  NVIC_Init(&NVIC_InitStructure); 
 
}

void EXTI0_IRQHandler(void)
{
	delay_ms(10);    		 
  if(B0 ==0)
	{
		v_set -= 500;
		n = (v_set/1000.0) / 15.0 * 100;
	}
	
	EXTI_ClearITPendingBit(EXTI_Line0); 
}
void EXTI15_10_IRQHandler(void)
{
  delay_ms(10);    		 
  if(B15==0)
	{
		/*Vafter+=5;
		if(Vafter==10)
		{
			Vafter=0;
			Vbefore++;
		}*/
		v_set += 500;
		n = (v_set/1000.0) / 15.0 * 100;
	}
	
	EXTI_ClearITPendingBit(EXTI_Line15); 
}

/* ADC_Init ------------------------------------*/													   
void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	  
 

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //14M

	//PA0                     
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;	
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  //ADC1

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	
	ADC_InitStructure.ADC_NbrOfChannel = 1;	
	ADC_Init(ADC1, &ADC_InitStructure);	

  
	ADC_Cmd(ADC1, ENABLE);	
	
	ADC_ResetCalibration(ADC1);	 
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	
	
	ADC_StartCalibration(ADC1);	 
 
	while(ADC_GetCalibrationStatus(ADC1));	
 
//	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		

}			
//ch: 0~3
u16 Get_Adc(u8 ch)   
{
  	
	ADC_RegularChannelConfig(ADC1, ch, 0, ADC_SampleTime_239Cycles5 );	
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));

	return ADC_GetConversionValue(ADC1);	
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u16 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 	 

/* Main ----------------------------------------*/
int main(void)
{
	u16 adcx;
	
	float temp,volt;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	delay_init();	
	
	KEY_Init();
	KEYSet();
	EXTIX_Init();
	
	Adc_Init();
	
	OLED_Init();	//OLED  
	OLED_Clear(); 
	
	TIM1_PWM_Init(8999,0);
	
	OLED_ShowString(10,0," O L E D",24); 
	OLED_ShowString(10,25,"R E A D Y",24);
  OLED_Refresh_Gram();
	delay_ms(1000);
	OLED_Clear(); //START UI
	
	//list of parameter;
	OLED_ShowString(6,0,"adcx:",12);
	OLED_ShowString(60,0,"/4096",12);//adcx
	OLED_ShowString(6,13,"Vt:",12);
	OLED_ShowString(60,13,"mV",12);//adc mv
	OLED_ShowString(6,25,"Real:",12);
	OLED_ShowString(72,25,"mV",12);//real volt
	OLED_ShowString(6,37,"Vset:",12);
	OLED_ShowString(72,37,"mV",12);//set volt
	
 	while(1)
	{
		set_zkb=(int)((100.0-n)*8999/100.0);
		TIM_SetCompare1(TIM1,set_zkb);
		delay_ms(10);
		
		adcx=Get_Adc_Average(ADC_Channel_0,10);
		
		OLED_ShowNum(36,0,adcx,4,12);
		temp=(float)adcx*(3.3/4096);
		volt =temp*1000;
		OLED_ShowNum(36,13,volt,4,12);//v adc
		v_real=4.93*volt;
		OLED_ShowNum(36,25,v_real,6,12);//v real
		OLED_ShowNum(36,37,v_set,6,12);//v set
		OLED_ShowNum(36,49,n*100,6,12);//n
		OLED_Refresh_Gram();
		
		CON();
		n_limit();
	}
}


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值