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

📄 motor.c

📁 AVR Mega128 电机保护程序源码 含过流、欠压、不平衡保护
💻 C
📖 第 1 页 / 共 2 页
字号:

//============================================================================
//   反时限表 						
//============================================================================
//过流保护反时限表
const unsigned int IDT_Table_OC[3][50]={  				  
     0,    0,   0,   0,   0,  10,  18,  27,  37,  47,  //0.2~2.0
	59,   72,  86, 101, 117, 135, 153, 172, 193, 215,  //2.2~4.0
	238, 262, 287, 313, 340, 369, 398, 429, 461, 494,  //4.2~6.0
	528, 563, 599, 636, 675, 714, 755, 797, 840, 884,  //6.2~8.0
	929, 975,1023,1071,1121,1171,1223,1276,1330,1385,  //8.2~10.0
     0,    0,   0,   0,   0,  10,  18,  27,  37,  47,  //0.2~2.0
	59,   72,  86, 101, 117, 135, 153, 172, 193, 215,  //2.2~4.0
	238, 262, 287, 313, 340, 369, 398, 429, 461, 494,  //4.2~6.0
	528, 563, 599, 636, 675, 714, 755, 797, 840, 884,  //6.2~8.0
	929, 975,1023,1071,1121,1171,1223,1276,1330,1385,  //8.2~10.0
     0,    0,   0,   0,   0,  10,  18,  27,  37,  47,  //0.2~2.0
	59,   72,  86, 101, 117, 135, 153, 172, 193, 215,  //2.2~4.0
	238, 262, 287, 313, 340, 369, 398, 429, 461, 494,  //4.2~6.0
	528, 563, 599, 636, 675, 714, 755, 797, 840, 884,  //6.2~8.0
	929, 975,1023,1071,1121,1171,1223,1276,1330,1385}; //8.2~10.0
//过流保护反时限表
const unsigned int IDT_Table_UB[50]={  				  
	 10,  28,  52,  80, 112, 133, 154, 175, 196, 217,
    238, 259, 280, 300, 321, 341, 362, 382, 403, 423,
    443, 463, 484, 504, 524, 544, 564, 584, 604, 624,
    644, 664, 684, 704, 724, 744, 763, 783, 803, 823,
    842, 862, 882, 902, 921, 941, 960, 980,1000,1019};

//============================================================================
//   反时限保护子程序 						
//============================================================================
unsigned char protect_idt(unsigned int TestValue,struct PRT_UNIT *p1,
		                 struct PRT_CNST *p2,unsigned char type)
//保护单元结构:越限			p1->OverLmt
//				瞬时越限		p1->OverLmtInst				
// 				动作延迟计数	p1->ActDT
//				复位延迟计数	p1->RstDT
//保护参数结构:整定值			p2->ActLvl
//				返回值			p2->RstLvl
//				复位延迟时间	p2->RstTim
// 				动作延迟时间	p2->ActTim
//type:			0-过流;1-不平衡         
{   unsigned int temp;
    if(type==0)
	  temp=(TestValue/RateCrt-2)>>1;
	else
	  temp=TestValue/RateCrt-1;
    if(temp>49) temp=49;
    if(TestValue>p2->ActLvl){
 	   p1->OverLmtInst=1;   //大于动作定值  
	   if(type==1)
   	      p1->ActDT+=IDT_Table_UB[temp];
	   if(type==0)
   	      p1->ActDT+=IDT_Table_OC[1][temp];
	   if(p1->ActDT>=p2->ActTim*100) p1->OverLmt=1;
	      p1->RstDT=0; 
	}
 	if(TestValue<p2->RstLvl){
	   p1->OverLmtInst=0;   //小于返回定值
	   (p1->RstDT)++;
	   if(p1->RstDT>=p2->RstTim){
	      p1->ActDT=0; p1->OverLmt=0;
	   }
	   else{
	      if(p1->OverLmtInst==0){
	         if(type==1)
   	    	    p1->ActDT+=IDT_Table_UB[temp];
	         if(type==0)
  	      	    p1->ActDT+=IDT_Table_OC[1][temp];
	   	     if(p1->ActDT>=p2->ActTim*100){
		        p1->OverLmt=1;
	   	        p1->RstDT=0;
		     }
	      }				 
	      else{
	         (p1->RstDT)++;
	         if(p1->RstDT >= p2->RstTim){
		        p1->ActDT=0;p1->OverLmtInst=0;
		     }
	      }
	   }
    }
 	return p1->OverLmt;
}

//============================================================================
//    读EE子程序
//============================================================================
unsigned char eeread(unsigned int eeaddr)
{ unsigned char data;
   while(EECR&1<<EEWE);
   EEARL=eeaddr;
   EEARH=eeaddr>>8;
   if(SREG&0x80){
      CLI();
      EECR|=1<<EERE;
      data=EEDR;	
      SEI();
   }
   else{
      EECR|=1<<EERE;
      data=EEDR;
   }	  	
   return data;
}
//============================================================================
//    写EE子程序
//============================================================================
void eewrite(unsigned int eeaddr,unsigned char eedata)
{  while(EECR&1<<EEWE);
   EEARL=eeaddr;
   EEARH=eeaddr>>8;
   EEDR=eedata;	
   if(SREG&0x80){
      CLI();
      EECR|=1<<EEMWE;
      EECR|=1<<EEWE;
      SEI();
   }	  
   else{
      EECR|=1<<EEMWE;
      EECR|=1<<EEWE;
   }
}
//============================================================================
//    保护处理子程序(每10ms)
//============================================================================
void _10ms_process(void)
{unsigned int max,min;
 unsigned char i,j;
 	_10msCnt++;
 	SEI();	  
	//模拟输入(200us)
    #ifdef DEBUG
    for(i=0;i<ADBufLen;i++){
  	  j=i;
	  if(j>=16) j-=16;	   
      ADBuf[0][i]=debug_data0[j];
      ADBuf[1][i]=debug_data1[j];
      ADBuf[2][i]=debug_data2[j];
      ADBuf[3][i]=debug_data3[j];
      ADBuf[4][i]=debug_data4[j];
      ADBuf[5][i]=debug_data5[j];
    }  
    ADBufCnt=0;
    #endif 
	ADBufCntHold=ADBufCnt;
    //数字傅氏变换(1400us)
	for(i=0;i<8;i++){
       dft(i);
	}   							  					
    //有效值计算(2200us)
    for(i=0;i<8;i++){
      IU[i]=sqrt_32(((unsigned long)ab[i][0]*ab[i][0]+(unsigned long)ab[i][1]*ab[i][1])>>1);
	  IU[i]=(unsigned long)IU[i]*1852/1000;
  	  if(i<3)
        IU[i]=(unsigned long)IU[i]*adc_rate;
	  else if(i<6)
        IU[i]=(unsigned long)IU[i]*10*adc_rate;      //满量程为1000.0A
    }
    //量程切换
    if((IU[3]>1000)||(IU[4]>1000)||(IU[5]>1000)){
      I1=IU[3];
      I2=IU[4];
      I3=IU[5];
    }
    else{
      I1=IU[0];
      I2=IU[1];
      I3=IU[2];
    }	
    //不平衡电流
    min=I1;max=I1;
    if(I2<min) min=I2;
    if(I3<min) min=I3;
    if(I2>max) max=I2;
    if(I3>max) max=I3;
    I0=max-min;
    //电流检测
    I=(I1+I2+I3)/3;
    if(I>RateCrt*4){       //>0.4x额定电流
	  PowOffCnt=0;
      if(PowOnCnt++>100){   //持续1s					  
         COMF|=comf_pw_on;
		 PowOnCnt=100;
	  }	 
    }
    if(I<RateCrt){         //<0.1x额定电流
      PowOffCnt++;
 	  PowOnCnt=0;
      if(PowOffCnt>1000){   //持续10s
         COMF&=~comf_pw_on;
		 PowOffCnt=1000;
      }
   }	   
   //电容器投入
   if(COMF&comf_pw_on){
	  if(CapDlyCnt++>CapDlyTime){ //通电延迟后接通电容器
	     CapDlyCnt=CapDlyTime;
	     PORTB|=bRL1;	
	  }	 
   }
    //过流保护
   if (protect_idt(I1,&UnitOC[0],&CnstOC,0))  //A相过流 
      PRS|=prs_oc1;
   else 
      PRS&=~prs_oc1;
   if (protect_idt(I2,&UnitOC[1],&CnstOC,0))  //B相过流 
      PRS|=prs_oc2;
   else 
      PRS&=~prs_oc2;
   if (protect_idt(I3,&UnitOC[2],&CnstOC,0))  //C相过流 
      PRS|=prs_oc3;
   else 
      PRS&=~prs_oc3;
   //电流不平衡保护
   if (protect_idt(I0,&UnitUB,&CnstUB,1))	  //不平衡 
      PRS|=prs_ub;
   else 
      PRS&=~prs_ub;
   //跳闸处理
   if(PRS&(prs_oc1|prs_oc2|prs_oc3|prs_ub)){
   	  PORTB|=bRL2;
	  TripDlyCnt=0;
	  PRSH|=PRS;
   }
   if(PORTB&bRL2){
      if(TripDlyCnt++>200)				  //吸合时间2s
	     PORTB&=~bRL2;
   }		 		
   //电流(电压)平均
   Iacc+=I;
   Uacc+=U;
   if(AveCnt++>=49){
      Iave=(Iacc+25)/50;
	  Uave=(Uacc+25)/50;   
  	  Iacc=0;
	  Uacc=0;
	  AveCnt=0;
   }
   //按键扫描
   if(!(PINB&bS1)){
      if(S1DownCnt++>5)
	     COMF|=comf_s1down;
	  S1UpCnt=0;
   }
   else{
      if(S1UpCnt++>5)
	     COMF&=~comf_s1down;
   	  S1DownCnt=0;
   }
   if(!(PINB&bS2)){
      if(S2DownCnt++>5)
	     COMF|=comf_s2down;
	  S2UpCnt=0;
   }
   else{
      if(S2UpCnt++>5)
	     COMF&=~comf_s2down;
   	  S2DownCnt=0;
   }
    //字符定义   afbedhcg
   #define _1  0b11011101
   #define _2  0b01000110
   #define _3  0b01010100
   #define _b  0b10100000
   #define _C  0b00100011
   #define _E  0b00100110
   #define _O  0b00000001
   #define _P  0b00001110
   #define _r  0b11101110
   #define _U  0b10000001
   #define _V  0b10000101
   #define _c  0b11100110
   #define __  0b11110111
   #define _o  0b11100100
   #define _n  0b11101100
   if(DspBlinkCnt++>99) DspBlinkCnt=0;
   //s1按下,显示保护定值
   if(COMF&comf_s1down){
      LED[3]=_P;//PrXX
	  LED[2]=_r;
	  if(DspBlinkCnt<50){
	     LED[1]=LEDChar[crt_rv[PRV]/10];
	     LED[0]=LEDChar[crt_rv[PRV]%10];
      }
	  else{
		 if(eeread(EERate)!=PRV){
		    LED[1]=0xff;
	        LED[0]=0xff;
		 }
		 else{
			LED[1]=LEDChar[crt_rv[PRV]/10];
	        LED[0]=LEDChar[crt_rv[PRV]%10];
		 }  
	  }
      if((COMF&comf_s2down)&&(!(COMFP&comf_s2down))){
	     PRV++;
    	 if(PRV>5) PRV=0;
	  }	
   }	 
   //S1不按下
   //新定值写入EE
   else if(!(COMF&comf_s1down)&&(COMFP&comf_s1down)){
      if(eeread(EERate)!=PRV){
        COMF|=comf_eewrt;
	  }  
   }
   else{
      if(DspBlinkCnt<50){
	     INT2SEC(Iave);	   //XXXX
		 if(CapDlyCnt<CapDlyTime){
            LED[0]&=LEDChar[16];
		 }
	  }
	  else{
		 LED[3]=0xff;  
		 LED[2]=0xff;  
		 LED[1]=0xff;  
		 LED[0]=0xff;  
		 i=0;
   	     if(PRSH&(prs_oc1|prs_oc2|prs_oc3)){
   	        LED[1]=_O;
	  	    LED[0]=_C;
			i=1;	
         }
   	     if(PRSH&prs_ub){
   	        LED[3]=_U;
	  	    LED[2]=_b;	
			i=2;	
         }
   	     if(COMF&comf_err_ee){
   	        LED[3]=_E;//Err2
	  	    LED[2]=_r;	
	  	    LED[1]=_r;	
	  	    LED[0]=_2;	
			i=3;	
         }
         if(COMF&comf_err){
            LED[3]=_E;//Err1
     		LED[2]=_r;	
      		LED[1]=_r;	
      		LED[0]=_1;	
			i=4;	
   		 }
   	     if(COMF&comf_err_cal){
   	        LED[3]=_E;//Err3
	  	    LED[2]=_r;	
	  	    LED[1]=_r;	
	  	    LED[0]=_3;	
			i=5;	
         }
		 if(i==0)
		    INT2SEC(Iave);	   //XXXX
	  }
    //清除故障显示
   if(S2ClikDly!=0)
	  S2ClikDly--;
   if(COMF&comf_s2down){
  	  if(!(COMFP&comf_s2down)){
         S2ClikCnt++;
	     S2ClikDly=50;
      }	  
      if(S2ClikDly<=10){
         if(S2ClikCnt==1){
	       INT2SEC(Uave);	   //显示电压
		 }
         if(S2ClikCnt==2){
	       INT2SEC(PRSH);	   //显示保护状态
		 }
         if(S2ClikCnt==3){
	       INT2SEC(PRSH);	   //清除保护状态
		   PRSH=0;
		 }
         if(S2ClikCnt==6){
	       COMF|=comf_cal;	   //校准
		   S2ClikCnt=0;
		 }
	  }
   }
   else if(S2ClikDly==0)
	  S2ClikCnt=0;
   }	 		
   COMFP=COMF;
   WDF|=wdf_t2;	  	       //置看门狗标志
   PowOnDlyCnt++;
	  
#ifdef DEBUG_P
if(DspBlinkCnt==0){
   if(DspCnt++>15) DspCnt=0;
}   	   
   PORTB|=bRL1|bRL2;
   LED[3]=LEDChar[DspCnt];  
   LED[2]=LEDChar[DspCnt];  
   LED[1]=LEDChar[DspCnt];  
   LED[0]=LEDChar[DspCnt];
#endif
}

//============================================================================
//    读校准值子程序
//============================================================================
void read_cal()
{
   unsigned char i;
   COMF&=~comf_err_cal;
   for(i=0;i<7;i++){
      CalValue[i]=eeread(EECal+i*2);
      CalValue[i]+=(eeread(EECal+i*2+1)<<8);
      if((CalValue[i]>0x9000)||(CalValue[i]<0x7000)||(CalValue[i]==0x8000)){
         CalValue[i]=0x8000;
		 COMF|=comf_err_cal;
	  }	 
   }
}   
//============================================================================
//    读保护定值子程序
//============================================================================
void read_rate()
{
   //读保护定值
   COMF&=~comf_err;
   PRV=eeread(EERate);
   if(PRV>5){
      PRV=5;
	  COMF|=comf_err;	  
   }	  
   RateCrt=crt_rv[PRV];
   CnstOC.ActLvl=(unsigned long)RateCrt*overcrt_rv; //过流动作整定值
   CnstOC.RstLvl=(unsigned long)RateCrt*overcrt_rtn;//过流动作返回值
   CnstOC.RstTim=overcrt_rst_t;		 				//过流复位延迟时间
   CnstOC.ActTim=overcrt_dly_t;		 				//过流动作延迟时间
   CnstUB.ActLvl=(unsigned long)RateCrt*unblnc_rv;  //不平衡动作整定值
   CnstUB.RstLvl=(unsigned long)RateCrt*unblnc_rtn;	//不平衡动作返回值
   CnstUB.RstTim=unblnc_rst_t;		 				//不平衡复位延迟时间
   CnstUB.ActTim=unblnc_dly_t;		 				//不平衡动作延迟时间
}

//============================================================================
//    主程序
//============================================================================
void main(void)
{
int i;
   //初始化	
   CLI(); 
   port_init();
   watchdog_init();
   timer0_init();
   timer2_init();
   adc_init();
   MCUCR = 0x00;
//   GICR  = 0x00;
   TIMSK = 0x81;
   COMF=0;
   COMFP=0;
   //读入校准值
   read_cal();
   read_rate();
   SEI(); 
   while(PowOnDlyCnt<20);   
   PRS=0;
   PRSH=0;
   Iacc=0;
   //主程序循环
   do{
   	  if((WDF&wdf_ad)&&(WDF&wdf_t2)&&(WDF&wdf_main)){
         WDR();
		 WDF&=~(wdf_ad|wdf_t2|wdf_main);
	  }	 
   	  if(COMF&comf_eewrt){
	  	 COMF&=~comf_err_ee;				  
	     eewrite(EERate,PRV);
		 if(eeread(EERate)!=PRV){
	        eewrite(EERate,PRV);
		    if(eeread(EERate)!=PRV){
			   COMF|=comf_err_ee;
			}
			else
			   read_rate();
		 }
		 else
		    read_rate();
         COMF&=~comf_eewrt;
	  }	 
      if((COMF&comf_cal)&&(S2ClikDly==0)){
	     if((U>=CALUMin)&&(U<=CALUMax))
            CalValue[0]=(long)0x8000*CALU/U;
         for(i=0;i<3;i++){
	        if((IU[i]>=CALiMin)&&(IU[i]<=CALiMax))
               CalValue[i+1]=(long)0x8000*CALi/IU[i];
         }			
         for(i=3;i<6;i++){
	        if((IU[i]>=CALIMin)&&(IU[i]<=CALIMax))
               CalValue[i+1]=(long)0x8000*CALI/IU[i];
         }			
         for(i=0;i<7;i++){
            eewrite(EECal+i*2,CalValue[i]);
            eewrite(EECal+i*2+1,CalValue[i]>>8);
         }
		 while(1);
	  }
   WDF|=wdf_main;	  
   }while(1);
}
 

⌨️ 快捷键说明

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