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

📄 main.c~

📁 基于AVR的智能充电器设计程序
💻 C~
字号:
/*电池充电电流大小设置函数
current_value------电流大小
pwm_initial_value----PWM控制占空比中ORC的初始值
电流由PID控制器控制PWM的占空比实现*/
#define current_adc_flag 0;
#define voltage_adc_flag 1;
unsigned int giADC_DataSave[10];
unsigned int adc_data;
unsigned char time_20ms_ok;
unsigned char LCD_I_value[3]={0,0,0};
unsigned char LCD_V_value[3]={0,0,0};
void current_adc(unsigned char adc_flag);
int adc_data_cmp();

typedef struct PID {

        int    SetPoint;           //  设定目标 Desired Value
        float  Proportion;         //  比例常数 Proportional Const
        float  Integral;           //  积分常数 Integral Const
        float  Derivative;         //  微分常数 Derivative Const
        int    LastError;          //  Error[1]
        int    PrevError;          //  Error[2]
        int    SumError;           //  误差累计值

} stPID;
int get_current_value(void)             //电流采样电阻采用1欧
     {   int i;
         get_adc(current_adc_flag);     //电流单位是mA
         i=adc_data_cmp();
         i=i*500/1024;     
         return i;
     }
int get_vlotage_ value(void);
{      
         int i;
         get_adc(current_adc_flag);     //电流单位是mA
         i=adc_data_cmp();
         i=i*500/1024;     
         return i;
}
             

void controlled_current (unsigned char current_value,unsigned char pwm_intial_value){
         int fi;
         int current_data;
         int fout;
if (time_20ms_ok){
        fi=get_current_value();  //获取真实电流值
        LCD_I_value[0]=(unsigned char)(fi/100);
        LCD_I_value[1]=(unsigned char)(fi%100/10);
        LCD_I_value[2]=(unsigned char)(fi%10);
        stPID.Proportion=1;
        stPID.Integral=0.5;
        stPID.Derivative=0.0;
        fout=PIDCalc(&stPID,fi); 
        active();
        }
}


//============================================================================================
//函数:float PIDCalc( PID *pp, int NextPoint )
//语法:float PIDCalc( PID *pp, int NextPoint )
//描述:PID计算
//参数:1、PID数值2、采样当前电流或电池电压值
//返回:PID输出值
//============================================================================================

float PIDCalc( PID *pp, unsigned long NextPoint )    //nextpoint为当前温度
{
    int   dError,
          Error;       
        Error = pp->SetPoint*10 -  NextPoint;          // 偏差,这里把温度放大10倍,去掉小数点
                                                       //便于处理
        pp->SumError += Error;                      // 积分
        dError = pp->LastError - pp->PrevError;     // 当前微分
        pp->PrevError = pp->LastError;
        pp->LastError = Error;        
        return (pp->Proportion * Error              // 比例项
            +   pp->Integral * pp->SumError         // 积分项
            +   pp->Derivative * dError             // 微分项
        );
}


//========================================================================
//函数: int adc_data_cmp()
//语法: int adc_data_cmp()
//描述: ADC采样数据的均值处理,抗干扰作用
//参数: 无
//返回: 无
//============================================================================================
	           
int adc_data_cmp()
{
    int max;
    int min;
    int Sum;
    int i;
    max = giADC_DataSave[0];
    for(i=0;i<10;i++){
    	if(giADC_DataSave[i]>max)     
    	   max = giADC_DataSave[i];          //取出最大值
    }
    min = giADC_DataSave[i];
    for(i=0;i<10;i++){
    	if(giADC_DataSave[i]<min)
    		min =  giADC_DataSave[i];        //取出最小值
    }
    for(i=0;i<10;i++)
       Sum += giADC_DataSave[i];             //累计值
    Sum = Sum - max-min;                     //排除最大最小值
    return(Sum/8);
}  


/*电流ADC采样转换函数   
        void current_adc()一共采样10次,存在全局变量giADC_DataSave[10]中
        用软件消除误差。ADC转换采用单次转换模式。 
        PA0-----电流采样接口
        PA2-----电池电压采样接口
*/ 
void get_adc(unsigned char adc_flag)                //ADC采样函数
{
         if (adc_flag==current_adc_flag) c_adc_initial();  //如果标志位位0,初始化电流采样
         if (adc_flag==voltage_adc_flag) v_adc_initial();  //若为1,初始化电源电压采样         
         for (i=0;i<10;i++){
            ADCSRA |=0x40h                 // 置位ADSC开始一次转换
            while (ADCSRA&0x40h);
            adc_data=ADCL;
            adc_data|=(int)ADCH<<8;
            giADC_DataSave[i]=adc_data;
            }
}

void c_adc_initial(void){
           ADMUX=0x41h;                      //采用内部电源AVCC,AD0单端输入
         ADCSRA=0x85h ;                     //单次转换 置位ADSC开始一次转换
         }
void v_adc_initial(void){
         ADMUX=0x40h ;                     //采用内部电源AVCC,AD1单端输入
         ADCSRA=0x85h ;                     //单次转换 置位ADSC开始一次转换 
         }
/*2ms定时中断,采用TC2的CTC模式比较中断
中断响应函数*/
interrupt [TIM2_COMP] void timer2_comp_isr (void)
{
          if(++time_counter1>=10)   //20ms到标志
            {
              time_counter1=0;
              time_20ms_ok=1;
            }
          if (++time_counter2>=500)  //1s 
              {
             time_counter2=0;
            time_1s_ok=1;
               if (++time[0] >=60)
                  {
                    time[0]=0;
                     if (++time[1] >=60)
                        {
                         time[1]=0;
                           time[2]++;
                         }
                   }
               }
}


/*对PID计算的结果FOUT进行处理,判断误差大小,分别处理*/
void active(void)
{
      if (fout<=0)         //电流大于设定值,要调小PWM占空比,即减小OCR0
         {
           if(OCRO--<=1)   OCR0=1;
          }
     else if (fout>10)     //当电流差别大于10mA时,PWM增大一个等级  
             {
               OCR0=OCR0+2;
               if(OCR0>=254)  OCRO=255;
             }
             else {        //当电流差别小于10mA且需要增大时,OCRO++
                 if(OCRO++>=254) OCRO=255;
                  }
}

/*PWM初始化,采用快速PWM模式16KHZ,PB3输出方式
   作为OC0输出PWM波*/
void pwm_initial(void)
{
   DDRB|=0x08;
   TCCR0=0x69;
   OCR0=pwm_intial_value;
   TIMSK=0x01;
}

⌨️ 快捷键说明

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