交直流双电源无缝切换

应用软件 专栏收录该内容
2 篇文章 0 订阅

 

使用ATmega32编写交直流双电源无缝切换,输入过欠压保护,输出过流保护。主要使用了单片机自带的比较器功能,比较器的一端使用了LT431制作的2.5V基准源。

--------------------------------------------------
#include  "iom32v.h"
#define   WDR()  asm("WDR")
#define   NOP()  asm("NOP")
unsigned char dcovervoltage_flag=0,acovervoltage_flag=0,dcundervoltage_flag=0,acundervoltage_flag=0;
             //直流过压标志        交流过压标志         直流欠压标志          交流欠压标志     
unsigned char dcreovervoltage_flag=0,acreovervoltage_flag=0,dcreundervoltage_flag=0,acreundervoltage_flag=0;
             //直流过压恢复标志      交流过压恢复标志        直流欠压恢复标志       交流欠压恢复标志
static unsigned char overcurrent[2]={0,0};

//---------------------------------------------------------
//---------------------------------------------------------


   /*使能看门狗*/
void WDT_enable(void)
     {
      WDTCR|=0x08;   //Allow change,WDT enable
      WDTCR|=0x0F;   //Set reset time,2.1S.
     }
//---------------------------------------------------------
//---------------------------------------------------------
   /*自定义延时程序*/
void delay(void)
    {
     unsigned char  i;
     for(i=2;i>0;i--);
    }
//---------------------------------------------------------
//---------------------------------------------------------
    /*初始化模拟比较器*/
void initialization_ac()
  {
   SFIOR|=0x08;        //使能模拟比较器多工输入
   ACSR&=0x3F;         //使能模拟比较器,利用外部基准,关闭中断
   ADCSRA|=0x80;       //关闭多路复用器,模拟比较器选择负极输入
  }
//---------------------------------------------------------
//---------------------------------------------------------
    /*直流过压检测程序*/
 unsigned char  dc_overvoltage(void)
     {
        unsigned char value;
        ADCSRA&=0x7F;                   // ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
        ADMUX&=0xF8;                    //选择通道0,直流过压检测
        delay();                        //转换延迟,等待转化结果
        ACSR=0x10;
        if(ACSR==0x00)              //条件成立,直流过压
           {
            PORTD&=0xDF;                //PD5输出设置为0,禁止直流输出
        
            PORTD&=0xF7;                // PD3输出低电平
            PORTD|=0x10;                //PD4输出高电平,说明直流输入异常
            value=1;
           }
         else                    //直流没有过压
            {
          PORTD|=0x08;        // PD3输出高电平,输入正常
       
            PORTD&=0xEF;          //PD4输出低电平,输入正常 
            value=0;
            } 
        ADCSRA|=0x80;             //关闭多路复用器,模拟比较器选择负极输入
        return(value);
 }
//---------------------------------------------------------
//---------------------------------------------------------
     /*直流过压恢复检测程序*/
 void dc_reovervoltage(void)
    {
    
      if(dcovervoltage_flag==1)      //条件成立,说明过压,需要检测恢复
         {
              ADCSRA&=0x7F;    //ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
              ADMUX&=0xF8;     //选择通道1,直流过压恢复检测
              ADMUX|=0x01;
              delay();         //转换延迟,等待转化结果。
              ACSR=0x10;
              if(ACSR==0x20)    //条件成立,说明过压恢复
                {
       
            PORTD|=0x08;        // PD3输出高电平,输入正常
          
                  PORTD&=0xEF;          //PD4输出低电平,输入正常
                  dcovervoltage_flag=0;
                  
                } 
               
         }
     ADCSRA|=0x80;       //关闭多路复用器,模拟比较器选择负极输入
    }
//---------------------------------------------------------
//---------------------------------------------------------
     /*直流欠压检测程序*/
unsigned  char  dc_undervoltage(void)
    {
         unsigned char  value;
         ADCSRA&=0x7F;     // ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
         ADMUX&=0xF8;     //选择通道2,直流欠压检测
         ADMUX|=0x02;
         delay();        //转换延迟,等待转化结果
         ACSR=0x10;
         if(ACSR==0x20)       //条件成立,直流欠压
           {
           PORTD&=0xDF;        //PD5输出设置为0,禁止直流输出

            PORTD&=0xF7;       // PD3输出低电平
            PORTD|=0x10;                //PD4输出高电平,说明直流输入异常
            value=1;
            
           }
         else                       //直流没有欠压
           {
            PORTD|=0x08;        // PD3输出高电平,输入正常
    
            PORTD&=0xEF;          //PD4输出低电平,输入正常
            value=0;
           } 
         ADCSRA|=0x80;         //关闭多路复用器,模拟比较器选择负极输入
         return(value);
    }

//---------------------------------------------------------
//---------------------------------------------------------
     /*直流欠压恢复检测程序*/
void  dc_reundervoltage(void)
    {
       if(dcundervoltage_flag==1)      //条件成立,说明过压,需要检测恢复
         {
            ADCSRA&=0x7F;     //ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
            ADMUX&=0xF8;      //选择通道3,直流欠压恢复检测
            ADMUX|=0x03;
            delay();        //转换延迟,等待转化结果。
            ACSR=0x10;
            if(ACSR==0x00)       //条件成立,说明欠压恢复
              {
       
             PORTD|=0x08;        // PD3输出高电平,输入正常
        
                PORTD&=0xEF;          //PD4输出低电平,输入正常
                dcundervoltage_flag =0;
              }
          
          }
        ADCSRA|=0x80;      //关闭多路复用器,模拟比较器选择负极输入
    }

//---------------------------------------------------------
//---------------------------------------------------------
     /*交流过压检测程序*/
unsigned char  ac_overvoltage(void)
    {
          unsigned char  value;
          ADCSRA&=0x7F;     // ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
          ADMUX&=0xF8;     
          ADMUX|=0x04;            //选择通道4,交流过压检测
          delay();                //转换延迟,等待转化结果
          delay();
          delay();
          delay();
          delay();
          ACSR=0x10;
          if(ACSR==0x00)          //条件成立,交流过压
            {
             PORTD|=0x40;         // PD6输出设置为1,禁止AC/DC输出
       
             PORTD|=0x02;          //PD1输出高电平,说明交流输入异常
             PORTD&=0xFE;         // PD0输出低电平
             value=1;
            }
         else                       //交流没有过压
            {
             PORTD|=0x01;        // PD0输出高电平,输入正常
     
             PORTD&=0xFD;        // PD1输出低电平,输入正常
             value=0;
            } 
          ADCSRA|=0x80;         //关闭多路复用器,模拟比较器选择负极输入
          return(value);
    }
//---------------------------------------------------------
//---------------------------------------------------------
      /*交流过压恢复检测程序*/
void  ac_reovervoltage(void)
    {
      if(acovervoltage_flag==1)      //条件成立,说明过压,需要检测恢复
         {
           ADCSRA&=0x7F;    //ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
           ADMUX&=0xF8;     
           ADMUX|=0x05;       //选择通道5,交流过压恢复检测
           delay();            //转换延迟,等待转化结果。
           delay();
           delay();
           delay();
           delay();
           ACSR=0x10;
           if(ACSR==0x20)       //条件成立,说明过压恢复
              {
        
                PORTD|=0x01;        // PD0输出高电平,输入正常
       
                PORTD&=0xFD;        // PD1输出低电平,输入正常
                acovervoltage_flag=0;
              }
         }
        ADCSRA|=0x80;      //关闭多路复用器,模拟比较器选择负极输入
    }
//---------------------------------------------------------
//---------------------------------------------------------
      /*交流欠压检测程序*/
unsigned  char  ac_undervoltage(void)
    {
         unsigned char  value;
         ADCSRA&=0x7F;     // ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
         ADMUX&=0xF8;     
         ADMUX|=0x06;             //选择通道6,交流欠压检测
         delay();                 //转换延迟,等待转化结果
         delay();
          delay();
          delay();
          delay();
         ACSR=0x10;
         if(ACSR==0x20)          //条件成立,交流欠压
           {
             PORTD|=0x40;       // PD6输出设置为1,禁止AC/DC输出
      
             PORTD|=0x02;          //PD1输出高电平,说明交流输入异常
             PORTD&=0xFE;         // PD0输出低电平
             value=1;
           }
         else                       //交流没有欠压
           {
             PORTD|=0x01;        // PD0输出高电平,输入正常
     
             PORTD&=0xFD;        // PD1输出低电平,输入正常
             value=0;
           } 
         ADCSRA|=0x80;      //关闭多路复用器,模拟比较器选择负极输入
         return(value);
    }

//---------------------------------------------------------
//---------------------------------------------------------
       /*交流欠压恢复检测程序*/
void  ac_reundervoltage(void)
    {
       if(acundervoltage_flag==1)      //条件成立,说明过压,需要检测恢复
         {
           ADCSRA&=0x7F;  //ADCSRA的ADEN位(位7)为0时,打开多路复用器,ADC多路复用器为模拟比较器选择负极输入
           ADMUX&=0xF8;     //选择通道7,交流欠压恢复检测
           ADMUX|=0x07;
           delay();       //转换延迟,等待转化结果。
           delay();
          delay();
          delay();
          delay();
           ACSR=0x10;
           if(ACSR==0x00)       //条件成立,说明欠压恢复
             {
    
                PORTD|=0x01;        // PD0输出高电平,输入正常
      
                PORTD&=0xFD;        // PD1输出低电平,输入正常
                acundervoltage_flag=0;
             }
           ADCSRA|=0x80;      //关闭多路复用器,模拟比较器选择负极输入
         }
    }
//---------------------------------------------------------
//---------------------------------------------------------
      /*过流检测程序*/
void  check_overcurrent(void)
     {
       
       ADCSRA|=0x80; 
       delay(); 
       delay();
       delay();
       delay();
       delay();
       ACSR=0x10;
       delay(); 
       delay(); 
       delay(); 
       if(ACSR==0x00)
      {
         if((PIND&0x80)==0x80)
              {
              overcurrent[0]=1;       //交流输出过流  
              PORTD|=0x40;            //PD6输出设置为1,禁止AC/DC输出  
              PORTD&=0xDF;           //PD5输出设置为0,禁止直流输出 
              }
         if((PINB&0x02)==0x02)
              {          
              overcurrent[1]=1;
              PORTD&=0xDF;           //PD5输出设置为0,禁止直流输出 
              }     
    
       }          

     }
//---------------------------------------------------------
//---------------------------------------------------------
 
void state_checkinput_dc(void)
 {
     if(dcreundervoltage_flag==0) 
     {
       if(dcreovervoltage_flag==0)
           {
             dcovervoltage_flag=dc_overvoltage();
             if(dcovervoltage_flag==1)
                {
                 dc_reovervoltage();  
                 WDR();   
                 dcreovervoltage_flag=dcovervoltage_flag;
                }
             else
                {
                   if(dcreundervoltage_flag==0) 
                     {
                      dcundervoltage_flag=dc_undervoltage();
                      if(dcundervoltage_flag==1)
                        {
                         dc_reundervoltage();
                         WDR();
                         dcreundervoltage_flag=dcundervoltage_flag;
                        }
                      else
                        {
                         ;
                        }
                      
                    }
                   else
                     {
                      dc_reundervoltage();
                      dcreundervoltage_flag=dcundervoltage_flag;
                     } 
                }    
           }
       else 
           {
            dc_reovervoltage();
            dcreovervoltage_flag=dcovervoltage_flag;
           } 
      }
     else
        {
         dc_reundervoltage();
         dcreundervoltage_flag=dcundervoltage_flag;
        }          
 }
//---------------------------------------------------------
//---------------------------------------------------------
void state_checkinput_ac(void)
 {
    if(acreundervoltage_flag==0) 
     {
       if(acreovervoltage_flag==0)
           {
             acovervoltage_flag=ac_overvoltage();
             if(acovervoltage_flag==1)
                {
                 ac_reovervoltage();  
                 WDR();   
                 acreovervoltage_flag=acovervoltage_flag;
                }
             else
                {
                   if(acreundervoltage_flag==0) 
                     {
                      acundervoltage_flag=ac_undervoltage();
                      if(acundervoltage_flag==1)
                        {
                         ac_reundervoltage();
                         WDR();
                         acreundervoltage_flag=acundervoltage_flag;
                        }
                      else
                        {
                         ;
                        }
                      
                    }
                   else
                     {
                      ac_reundervoltage();
                      acreundervoltage_flag=acundervoltage_flag;
                     } 
                }    
           }
       else 
           {
            ac_reovervoltage();
            acreovervoltage_flag=acovervoltage_flag;
           } 
      }
     else
        {
         ac_reundervoltage();
         acreundervoltage_flag=acundervoltage_flag;
        }       
 }
//---------------------------------------------------------
//---------------------------------------------------------
void  main(void)
{
        unsigned int i;
        static unsigned int SoftStage=0;
        
        DDRD|=0x7F;      //PD0~PD6设置为输出
        PORTD&=0xE0;     //PD0~PD4输出设置为0,均无指示
        PORTD&=0xDF;     //PD5输出设置为0,禁止直流输出
        PORTD|=0x40;     //PD6输出设置为1,禁止AC/DC输出
        DDRD&=0x7F;      //PD7设置为输入
        PORTD|=0x80;     //PD7上拉有效
        DDRB&=0xCF;      // PB4、PB5设置为输入
        PORTB|=0x30;     // PB4、PB5上拉有效
        DDRB&=0xFD;      // PB1设置为输入
        PORTB|=0x02;     // PB1上拉有效
        initialization_ac();   //初始化模拟比较器    
        WDT_enable();
                  for(i=20000;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }
    while(1)
    {
            while((PINB&0x30)==0x30)     //无开机信号
            {
                 PORTD&=0xDF;                           //PD5输出设置为0,禁止直流输出
                 PORTD|=0x40;                           //PD6输出设置为1,禁止AC/DC输出
                 for(i=8000;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }
                if((PINB&0x02)==0x02)              //(PB1)有直流输入      
                     {
                      for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }    
                      state_checkinput_dc(); 
                     }
                else                                //无直流输入
                     {
                      PORTD&=0xE7;                  //PD3=0,PD4=0,清除直流显示标志
                      dcovervoltage_flag=0;
                      dcundervoltage_flag=0;
                      dcreundervoltage_flag=0;
                      dcreovervoltage_flag=0;   
                      }      
                if((PIND&0x80)==0x80)                 //(PD7)有交流输入
                    {
                      for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }    
                     state_checkinput_ac();                             
                    }
                else                               //无交流输入
                    {
                     PORTD&=0xFC;                  //PD0=0,PD1=0,清除交流显示标志
                     acovervoltage_flag=0;
                     acundervoltage_flag=0;
                     acreundervoltage_flag=0;
                     acreovervoltage_flag=0; 
                    }  
                if(((dcundervoltage_flag||dcovervoltage_flag)||(acundervoltage_flag||acovervoltage_flag))==0)
                   {
                   PORTD&=0xFB;           //PD2输出设置为低电平,交直流输入均为无故障
                   }
                else
                   {
                   PORTD|=0x04;           //PD2输出设置为高电平,交直流输入有一个有故障
                   }      
            }  
        /********************************************************************/
        /********************************************************************/
            while((PINB&0x30)!=0x30)             //有开机信号,PB4、PB5不同时为1开机
            {                                       
                if(((PINB&0x02)==0x02)&&((PIND&0x80)!=0x80)) SoftStage=1;//当前只有直流输入                                                            
                if(((PINB&0x02)!=0x02)&&((PIND&0x80)==0x80)) SoftStage=2;//当前只有交流输入                                                            
                if(((PINB&0x02)==0x02)&&((PIND&0x80)==0x80)) SoftStage=3;//交直流都有输入情况下
                                                
                while(SoftStage==1)//当前只有直流输入
                 {
                    PORTD|=0x40;  //PD6输出设置为1,禁止AC/DC输出                
                    for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }
                    if((PINB&0x02)==0x02)                  //如果有直流输入,就判断直流输入         
                     {
                      for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }    
                       PORTD&=0xFC;                  //PD0=0,PD1=0,清除交流显示标志
                       acovervoltage_flag=0;
                       acundervoltage_flag=0;
                       acreundervoltage_flag=0;
                       acreovervoltage_flag=0; 
                       state_checkinput_dc(); 
                       
                     }
                    else
                     {
                      PORTD&=0xE7;                    //清除直流显示标志
                      dcovervoltage_flag=0;
                      dcundervoltage_flag=0;
                      dcreundervoltage_flag=0;
                      dcreovervoltage_flag=0;   
                      }      
                   
                   if((dcundervoltage_flag||dcovervoltage_flag)==0)
                       {
                       PORTD&=0xFB;           //PD2输出设置为低电平,交直流输入均为无故障
                       }
                    else
                       {
                       PORTD|=0x04;           //PD2输出设置为高电平,交直流输入有一个有故障
                       }    
                  
                   if(((dcundervoltage_flag||dcovervoltage_flag)||overcurrent[1])==0)
                        {
                         PORTD|=0x20;         // PD5输出设置为1,允许直流输出      
                        }
                   else 
                         {
                          PORTD&=0xDF;        //PD5输出设置为0,禁止直流输出
                         }
                     check_overcurrent();
                     WDR();
                     delay();  
                 
                    if(overcurrent[1]==1)
                        {
                        PORTD&=0xDF;           //PD5输出设置为0,禁止直流输出 
                        overcurrent[1]=1;
                        }
                                        
                    if(((PINB&0x02)==0x02)&&((PIND&0x80)==0x80)) SoftStage=3;//交直流都有输入情况下
                        {
                          PORTD&=0xBF;      //PD6输出设置为0,允许AC/DC输出 
                          for(i=5000;i>0;i--) delay();      
                                                
                        }                                    
                    if((PINB&0x30)==0x30) break; 
                 }
                 
                  while(SoftStage==2)//当前只有交流输入
                 {
                    PORTD&=0xDF;           //PD5输出设置为0,禁止直流输出
                           
                     for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }
                       
                     if((PIND&0x80)==0x80)                 //如果有交流输入,就判断交流输入
                      {
                      for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }  
                          PORTD&=0xE7;                  //PD3=0,PD4=0,清除直流显示标志
                          dcovervoltage_flag=0;
                          dcundervoltage_flag=0;
                          dcreundervoltage_flag=0;
                          dcreovervoltage_flag=0; 
                          state_checkinput_ac();                              
                      }
                     else
                        {
                         PORTD&=0xFC;                    //清除交流显示标志
                         acovervoltage_flag=0;
                         acundervoltage_flag=0;
                         acreundervoltage_flag=0;
                         acreovervoltage_flag=0; 
                        } 
                    WDR();       
                    if((acundervoltage_flag||acovervoltage_flag)==0)
                       {
                       PORTD&=0xFB;           //PD2输出设置为低电平,交直流输入均为无故障
                       }
                    else
                       {
                       PORTD|=0x04;           //PD2输出设置为高电平,交直流输入有一个有故障
                       }      
                    if(((acundervoltage_flag||acovervoltage_flag)||overcurrent[0])==0)
                         {
                          PORTD&=0xBF;;        //PD6输出设置为0,允许AC/DC输出
                         }
                    else 
                         {
                         PORTD|=0x40;         //PD6输出设置为1,禁止AC/DC输出
                         }
                    
                     check_overcurrent();
                     WDR();
                     delay();  
                     if(overcurrent[0]==1)
                        {
                        PORTD|=0x40;            //PD6输出设置为1,禁止AC/DC输出       
                        overcurrent[0]=0;  
                        for(i=20000;i>0;i--)
                             {
                              delay(); 
                              WDR();
                             }
                        }
                    
                     if(((PINB&0x02)==0x02)&&((PIND&0x80)==0x80))  SoftStage=3;//交直流都有输入情况下
                     if((PINB&0x30)==0x30) break; 
                     }
                     
                 while(SoftStage==3)//当前交直流一起输入
                 {
                    PORTD&=0xDF;      //PD5输出设置为0,禁止直流输出
                     for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }
                   
                   if((PINB&0x02)==0x02)                  //如果有直流输入,就判断直流输入         
                     {
                      for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }    
                      state_checkinput_dc(); 
                     }
                   else
                       {
                      PORTD&=0xE7;                    //清除直流显示标志
                      dcovervoltage_flag=0;
                      dcundervoltage_flag=0;
                      dcreundervoltage_flag=0;
                      dcreovervoltage_flag=0;   
                      } 
                        
                  if((PIND&0x80)==0x80)                 //如果有交流输入,就判断交流输入
                    {
                      for(i=2;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }   
                       
                     state_checkinput_ac();                              
                    }
                  else
                    {
                     PORTD&=0xFC;                    //清除交流显示标志
                     acovervoltage_flag=0;
                     acundervoltage_flag=0;
                     acreundervoltage_flag=0;
                     acreovervoltage_flag=0; 
                    } 
                  WDR();       
                  if(((dcundervoltage_flag||dcovervoltage_flag)||(acundervoltage_flag||acovervoltage_flag))==0)
                   {
                   PORTD&=0xFB;           //PD2输出设置为低电平,交直流输入均为无故障
                   }
                  else
                   {
                   PORTD|=0x04;           //PD2输出设置为高电平,交直流输入有一个有故障
                   }    
                  if(((acundervoltage_flag||acovervoltage_flag)||overcurrent[0])==0)
                     {
                      PORTD&=0xBF;        //PD6输出设置为0,允许AC/DC输出
                     }
                  else 
                     {
                      PORTD|=0x40;       //PD6输出设置为1,禁止AC/DC输出
                     }
                  check_overcurrent();
                  WDR();
                  delay();  
                  if(overcurrent[0]==1)
                    {
                    PORTD|=0x40;            //PD6输出设置为1,禁止AC/DC输出       
                    overcurrent[0]=0;  
                    for(i=20000;i>0;i--)
                         {
                          delay(); 
                          WDR();
                         }
                    }                 
                 if(((PINB&0x02)==0x02)&&((PIND&0x80)!=0x80)) SoftStage=1;//当前只有直流输入                                                
                 if(((PINB&0x02)!=0x02)&&((PIND&0x80)==0x80))
                     SoftStage=2;//当前只有交流输入
                       
                 if((PINB&0x30)==0x30) break; 
                 }
                
            }
         
    
    }
}    

  • 1
    点赞
  • 1
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值