⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mega88.c

📁 mega88做buck拓扑开关电源,pid调节
💻 C
字号:
#include <iom88v.h>
#include <macros.h>
#include <math.h>
//PWM由A口输出
//PWM频率40K,相位与频率修正方式,模式8
//将调整PWM放到TOV1溢出中
//外部16M晶振
//输出电压值OUT_V(通道0:0x40) 输入电压值IN_V(通道1:0x41) 输入电流值OUT_I(通道2:0x42)
//分两档:轻档恒流加限输出电压    重档恒电压
//增量法
//******PID参数*****************
//快速恒压参数 
#define A_V   0.31        
#define B_V   0.01      
//正常恒流参数
#define A_I   0.56       
#define B_I   0.07       
//****************************************
#define OCR1AL_MAX	0xBE			//占空比上限95%
#define OCR1AL_MIN	0x0A			//占空比上限5%  
#define OCR1AL_U	0x14			//占空比变化最大值10%
#define OCR1AL_I	0x14			//占空比变化最大值10%
//****************************************
unsigned int OUT_Voltage[12];  //输出电压
unsigned int OUT_V;
unsigned char OUT_V_Loop;
unsigned int OUT_Current[12];   //输出电流
unsigned int OUT_I;
unsigned char OUT_I_Loop;

float Ek_I,Ek_I_Before,Uk_I,Uk_I_Before;
float Ek_V,Ek_V_Before,Uk_V,Uk_V_Before;
//******************************************************/
void adc_init(void)
{
  OUT_I_Loop = 0;
  OUT_V_Loop = 0;
  ADCSRA = 0x00; 
  ACSR = (1<<ACD);   
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
//****************************************************/
#pragma interrupt_handler timer1_capt_isr:11
void timer1_capt_isr(void)
{
    unsigned int temp;
    unsigned char i;
    //------输出电压-------------
    ADMUX = 0x40;
    ADCSRA |= (1<<ADSC);
    while((ADCSRA&0x10) != 0x10)
	  WDR(); 
    ADCSRA |= (1<<ADIF);        
    OUT_Voltage[OUT_V_Loop] = ADC & 0x03FF;
    OUT_V_Loop ++;
    if(OUT_V_Loop == 12)
	  OUT_V_Loop = 0;
    temp = 0;
    for(i=0;i<12;i++)
	  temp = temp + OUT_Voltage[i];
    OUT_V = temp / 12;
	//-----输出电流---------------
	ADMUX = 0x43;
	ADCSRA |= (1<<ADSC);
    while((ADCSRA&0x10) != 0x10)
	  WDR(); 
    ADCSRA |= (1<<ADIF);         
    OUT_Current[OUT_I_Loop] = ADC & 0x03FF;
    OUT_I_Loop ++;
    if(OUT_I_Loop == 12)
	  OUT_I_Loop = 0;
    temp = 0;
    for(i=0;i<12;i++)
	  temp = temp + OUT_Current[i];
    OUT_I = temp / 12;
	//--------PID处理-------------
	//快速充电恒压  低电平
	if(!(PIND & 0x01))
	{
	  Ek_V = 14.2 - OUT_V * 0.0244;
	  Uk_V = A_V * (Ek_V - Ek_V_Before) + B_V * Ek_V + Uk_V_Before;
      
	  if(Uk_V < 0)
	    Uk_V = 0;
	  if(Uk_V > OCR1AL_MAX)
	    Uk_V = OCR1AL_MAX;
		
	  Uk_V_Before = Uk_V;
	  Ek_V_Before = Ek_V;
	  
	  if((Uk_V - OCR1AL) > OCR1AL_U)
	    OCR1AL = OCR1AL + OCR1AL_U;
	  else if((OCR1AL - Uk_V) > OCR1AL_U)
	    OCR1AL = OCR1AL - OCR1AL_U;
	  else
		OCR1AL = (unsigned char)(Uk_V);
	}
	//正常充电 恒流加恒压  高电平
	if(PIND & 0x01)
	{
	  if(OUT_I < 32) 
	  {
	    OCR1AL = 0x64; 
	  }
	  else
	  {
		Ek_I = 2 - OUT_I * 0.005;  
	    Uk_I = A_I * (Ek_I - Ek_I_Before) + B_I * Ek_I + Uk_I_Before;
        if(Uk_I < 0)
	      Uk_I = 0;
	    if(Uk_I > OCR1AL_MAX)
	      Uk_I = OCR1AL_MAX;
		
	    Uk_I_Before = Uk_I;
	    Ek_I_Before = Ek_I;
	   
	    if((Uk_I - OCR1AL) > OCR1AL_I)
	      OCR1AL = OCR1AL + OCR1AL_I;
	    else if((OCR1AL - Uk_I) > OCR1AL_I)
	      OCR1AL = OCR1AL - OCR1AL_I;
	    else
		  OCR1AL = (unsigned char)(Uk_I);
	  }
	}
} 
//****************************************************
void timer1_init(void)  
{
  DDRB |= (1<<PB2);
  DDRB |= (1<<PB1);
  
  TCCR1B = 0x00; 
  TCNT1H = 0xFF; 
  TCNT1L = 0x38;
  
  OCR1AH = 0x00; 
  OCR1AL = 0x0f;
  
  OCR1BH = 0x00;  
  OCR1BL = 0x0b;  
  
  ICR1H  = 0x00;
  ICR1L  = 0xC8;
  
  TCCR1A = (1<<COM1A1)|(1<<COM1B1); 
  TCCR1B = (1<<WGM13)|(1<<CS10);      
  TIMSK1 = 0x20;
}
//*************************************************/
void main(void)
{
  WDR(); 
  WDTCSR = 0x1F; 
  WDTCSR = 0x0F; 
  WDR();                     
  
  PORTD |= (1<<PD0);
  CLI();
  timer1_init();            
  adc_init(); 
  SEI();    
  
  Ek_V_Before = 0x00;
  Uk_V_Before = 0x00;
  Ek_I_Before = 0x00;
  Uk_I_Before = 0x00;
  while(1)
  {
    WDR();
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -