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

📄 rscomm.c

📁 江苏单相复费率电能表方案
💻 C
📖 第 1 页 / 共 2 页
字号:
    TFlag = PsWdCHK(RS_DataPtr);  								//密码检查
		
   	if((TFlag==0x10)&&(RS_CmdH==0xC1)&&(RS_CmdL==0x19))			//清零密码+电表清零指令
    {   		
    	//编程允许+清零次数
    	TFlag=0x00;
    	
    	if(Prog_Flag==1) TFlag = 0x03; 	                        //编程允许后有2次机会
 		else
 		{
			Addr[0] = 0xA0;
    		Addr[1] = 0xBE;    
    		Len[1]  = 0x02;
    		do
    		{
       			ReadData(Temp);
    		} while((Temp[0]!=~Temp[1])&&(Addr[0]<=0xA4));
    	
			if((Temp[0]==~Temp[1])&&(Temp[0]<0x03))	TFlag = Temp[0];	//清零次数
		}

        if(TFlag<3) ArrayInit(&ComBuf[RS_CmdPtr+6],16);
		else
		{
			if( BCDCHK(&ComBuf[RS_CmdPtr+6],16)==0 )	TFlag = 0x00;
		}
       	
		
		if( TFlag!=0x00 )
       	{
			ArrayInit(&ComBuf[RS_CmdPtr+6],16);
        	for(i=0;i<5;i++)
        	{
        		j= 4*i;
           		
        		//小数清零
        		EryTmp[i] = ComBuf[RS_CmdPtr+6+j];           		
        		Temp[0]   = EryTmp[i];
           		Temp[1]   =~EryTmp[i];           		
           			
           		Addr[0]   = 0xA0;
				Addr[1]   = Ptr[i];					
      			Len[1]    = 0x02;
				WriteEPMData(Temp);
					
				//整数校验和
           		ComBuf[RS_CmdPtr+6+j]=SumCHK(&ComBuf[RS_CmdPtr+6+j+1],3);               		
           	}			
			
			EryTmp[5]=SumCHK(EryTmp,5);//小数检验和
           	

           	//有功电量整数清零
			Addr[0] = 0xA0; 
			Addr[1] = 0xC0;           	
      		Len[1]  = 0x10; 
			WriteEPMData(&ComBuf[RS_CmdPtr+6]);

			//ArrayInit(&ComBuf[RS_CmdPtr+6],16);			

			//有功电量整数低字节清零
			Addr[0] = 0xA0; 
			Addr[1] = 0xA0;           	
      		Len[1]  = 0x0A; 
			WriteEPMData(&ComBuf[RS_CmdPtr+6]);		
			
		    //反向电量整数清零			
			Addr[0] = 0xA0;
			Addr[1] = 0xD0;             	
      Len[1]  = 0x04;
			WriteEPMData(&ComBuf[RS_CmdPtr+6]);
//****
		    //反向累计总时间
			Addr[0] = 0xA0;
			Addr[1] = 0x30;             	
      Len[1]  = 0x10;
			WriteEPMData(&ComBuf[RS_CmdPtr+6]);

			//最近一次反向起始时间
		  Addr[0] = 0xA0;
			Addr[1] = 0xAA;             	
      Len[1]  = 0x05;
			WriteEPMData(&ComBuf[RS_CmdPtr+6]);			
			EryRev = 0;	//电能反向标志清零(060302)			
//****						
			//清零次数回写
			TFlag--;
			Temp[0] =  TFlag;
			Temp[1] = ~TFlag;
		
			Addr[0] = 0xA0;
   			Addr[1] = 0xBE; 
   			Len[1]  = 0x02;   	
			WriteEPMData(Temp);	
			
			ArrayInit(PulseTmp,6);//剩余脉冲清零
    	}    	
    	else Flag &= ~0x0A;	
	}   	
   	  	
   	else if(TFlag==0x11)			//编程密码 
    {
		if(RS_CmdH==0xC0)
    	{	   		
    		if( (RS_CmdL==0x10)&&(Prog_Flag==1) )//日期编程+编程允许
    		{ 
   				if((ComBuf[RS_CmdPtr+6]<0x07)&&(DateCHK(&ComBuf[RS_CmdPtr+7])==1))
				{
					//周日月年					
   					RTC_Set(0x30,&ComBuf[RS_CmdPtr+6],0x04);   				   				
					TimeAdj = 1;//校时时间
					
					//********
					EryBln_Flag = 1;
				}
   			}
   			   					
			else if((RS_CmdL==0x11)&&(TimeTerm()==1))//时间编程
			{
				RTC_Set(0x00,&ComBuf[RS_CmdPtr+6],0x03);
        		
				AdjTime = 0;//校时条件满足

        		TimeAdj = 1;//校时时间
				Fee_Flag= 1;//费率检查    							
    		}   		
    		
    		else if(((RS_CmdL==0x32)||(RS_CmdL==0x33))&&(Prog_Flag==1))
    		{
    			Addr[0] = 0xA0;
    			
    			Addr[1] = 0xF0;						//局编号    			
    			if(RS_CmdL==0x32)	Addr[1] = 0xF8;	//出厂编号
    			//else 				Addr[1] = 0xF0;	//局编号    			
        		Len[1]  = 0x07; 
       		
    			ComBuf[RS_CmdPtr+6+6]=SumCHK(&ComBuf[RS_CmdPtr+6],6);

				WriteEPMData(&ComBuf[RS_CmdPtr+6]);	
			}
			else Flag &= ~0x0A;	 
    	}
		//else if((RS_CmdH==0xC1)&&(RS_CmdL==0x15)&&(Prog_Flag==1))//显示选择 		
		else if((RS_CmdH==0xC1)&&(RS_CmdL==0x15))					//显示选择
		{
			DspTime    = ComBuf[RS_CmdPtr+6+0];
        	DspCtrl2   = ComBuf[RS_CmdPtr+6+1];
        	DspCtrl1   = ComBuf[RS_CmdPtr+6+2]|0x1C;
        	if(DspTime>0x30||DspTime<0x02)DspTime=0x10;
        	
        	DspParaCHK = ~(DspCtrl1+DspCtrl2+DspTime);
        	
        	Addr[0] = 0xA0;
			Addr[1] = 0xDC;    		
    		Len[1] 	= 0x04;	
    		WriteEPMData(DspPara);	
        	
        	DspSec = BCD2HEX(DspTime);
        	DspPtr = 0xFF;	
		}
		
		else if((RS_CmdH==0xC1)&&(RS_CmdL==0x17)&&(Prog_Flag==1))//自动抄表日期
		{
			ComBuf[RS_CmdPtr+6+2]=~(ComBuf[RS_CmdPtr+6+0]+ComBuf[RS_CmdPtr+6+1]);//~SumCHK(&ComBuf[RS_CmdPtr+6],2);
			
			Addr[0] = 0xA0;
			Addr[1] = 0xD4;			
    		Len[1] 	= 0x03;    		
			WriteEPMData(&ComBuf[RS_CmdPtr+6]);
		}
    	
    	else if((RS_CmdH==0xC3)&&(RS_CmdL==0x3F)&&(Prog_Flag==1))//时段表	
        {
        	//时段表数据分析
        	TFlag=0x00;        	
        	i=RS_CmdPtr+6;//两位命令符+4位密码
        	j=RS_CmdPtr+RS_Len;
        	
        	//一个时段单位数据检查
        	do
        	{
        		//费率
 	       		if((ComBuf[i]<0x02)||(ComBuf[i]>0x04))		    TFlag |= 0x01;
 	       		
 	       		//分
 	       		i++;
 	       		if((ComBuf[i]!=0x00)&&(ComBuf[i]!=0x30))		TFlag |= 0x01; 	       		
 	       		
 	       		//时
 	       		i++;
 	       		if(((ComBuf[i]&0x0F)>0x09)||(ComBuf[i]>0x23))	TFlag |= 0x01; 	       		
 	       		
 	       		i++;
 	       		
        	}while((TFlag==0x00)&&(i<j));
        	
        	
        	if(TFlag==0x00)//数据正确
        	{           	
        		Temp[0] = (RS_Len/3)-2;		//有效时段数
        		    		
        		j -= 3;        		
        		do//时段表排序算法(冒泡)
        		{
        			k=1;
        			for(i=RS_CmdPtr+6;i<j;)
        			{
 	       				//基于小时量的比较
 	       				if(ComBuf[i+2]>ComBuf[i+5])
 	       				{
 	       					//费率
 	       					Temp[1]		= ComBuf[i];
 	       					ComBuf[i]   = ComBuf[i+3];
 	       					ComBuf[i+3] = Temp[1]; 
 	       					
 	       					//分
 	       					Temp[1]     = ComBuf[i+1];
 	       					ComBuf[i+1] = ComBuf[i+4];
 	       					ComBuf[i+4] = Temp[1];
 	       					
 	       					//时
 	       					Temp[1]		= ComBuf[i+2];
 	       					ComBuf[i+2]	= ComBuf[i+5];
 	       					ComBuf[i+5]	= Temp[1];		
 	       				}
 	       				else if(ComBuf[i+2]==ComBuf[i+5])
 	       				{	
 	       					if(ComBuf[i+1]>ComBuf[i+4])//分比较
 	       					{
 	       						//费率
 	       						Temp[1]		= ComBuf[i];
 	       						ComBuf[i]   = ComBuf[i+3];
 	       						ComBuf[i+3] = Temp[1];
 	       						
 	       						//分
 	       						Temp[1]	    = ComBuf[i+1];
 	       						ComBuf[i+1] = ComBuf[i+4];
 	       						ComBuf[i+4] = Temp[1];
 	       					} 	       					
 	       					else if((ComBuf[i+1]==ComBuf[i+4])&&	//同时段,费率不同错误
 	       							(  ComBuf[i]!=ComBuf[i+3]))		TFlag =0x01;
 	       					else k++;
 	       				}
 	       				else k++; 	       				
 	       				i += 0x03;		
        			}        			        	
        		}while(k<Temp[0]);
        	
        	
        		if(TFlag==0x00)        	
        		{	
        			Fee_Flag = 1;
        			
        			i = RS_Len-6;
        			RS_CRC = ~SumCHK(&ComBuf[RS_CmdPtr+6],i);//时段费率检验和反码
        		
        			//有效时段数
        			Temp[1] = ~Temp[0];
        			Addr[0] = 0xA2; 
					Addr[1] = 0xCE;					
      				Len[1]  = 0x02; 
					WriteEPMData(Temp);
				
        			if(Temp[0]<6)
        			{
        				Addr[0] = 0xA2; 
						Addr[1] = 0xD0;						
      					Len[1]  = i+1; 
						WriteEPMData(&ComBuf[RS_CmdPtr+6]);
        			} 			
 					else if(Temp[0]>10)
 					{
 						Addr[0] = 0xA2; 
						Addr[1] = 0xD0;
      					Len[1]  = 0x10; 
						WriteEPMData(&ComBuf[RS_CmdPtr+6]);
					
						Addr[0] = 0xA2; 
						Addr[1] = 0xE0; 
						WriteEPMData(&ComBuf[RS_CmdPtr+6+16]);
					
						Addr[0] = 0xA2; 
						Addr[1] = 0xF0;						
      					Len[1]  = i-32+1; 
						WriteEPMData(&ComBuf[RS_CmdPtr+6+32]);
 					} 			
 					else
 					{
 						Addr[0] = 0xA2; 
						Addr[1] = 0xD0;						
      					Len[1]  = 0x10; 
						WriteEPMData(&ComBuf[RS_CmdPtr+6]);
										
						Addr[0] = 0xA2; 
						Addr[1] = 0xE0;						
      					Len[1]  = i-16+1; 
						WriteEPMData(&ComBuf[RS_CmdPtr+6+16]);
 					} 					
 				}
 				else Flag &= ~0x0A;	
        	}
        	else Flag &= ~0x0A;	 
    	}
    	else Flag &= ~0x0A;	    	
	}
	else Flag &= ~0x0A;
}





//**********************************************************
//名称:
//功能:
//说明:
//**********************************************************
uchar RxdCheck(void)
{	
	uchar Address[6];
	
	//帧长度、帧结构检查
	if( ComPtr<RS_MinSize || RS_Head!=0x68 || RS_Head0!=0x68 || RS_End!=0x16  ) return 0x00;  
  	
  	//校验错误  	
    if( RS_CRC!=SumCHK(ComBuf,RS_CmdPtr+RS_Len)) return 0x00;     
    
    Addr[0] = 0xA0;        	
    Addr[1] = 0xF0;  //局编号地址 
	Len[1]  = 0x06;   	
	ReadData(Address);
   	
   	if( RS_Addr0==0x99 && RS_Addr1==0x99 && RS_Addr2==0x99 &&
    	RS_Addr3==0x99 && RS_Addr4==0x99 && RS_Addr5==0x99 )
  	{
    	if( RS_Ctrl==RS_CTRL_Time  ) 	  					return 0x10;	//广播校时
    	else if( RS_Ctrl==RS_CTRL_MetID && Prog_Flag==1 ) 	return 0x11;	//广播设置电表号 
    	
    	//※※※※※※※※ 
    	//else if( RS_Ctrl==0xAA && Prog_Flag==1 )         	return 0x12;  	//自定义命令集    
    	//※※※※※※※※ 
    	
    	else 							  				 	return 0x00;	//广播命令码错误
  	}

  	//局号符合(包含缩位寻址)
  	else if( (RS_Addr0==Address[0]||RS_Addr0==0xAA) && (RS_Addr1==Address[1]||RS_Addr1==0xAA) && 
  	         (RS_Addr2==Address[2]||RS_Addr2==0xAA) && (RS_Addr3==Address[3]||RS_Addr3==0xAA) &&
  	         (RS_Addr4==Address[4]||RS_Addr4==0xAA) && (RS_Addr5==Address[5]||RS_Addr5==0xAA) ) 
  	{	
  		RS_Addr0 = Address[0];
		RS_Addr1 = Address[1];
		RS_Addr2 = Address[2];
		RS_Addr3 = Address[3];
		RS_Addr4 = Address[4];
		RS_Addr5 = Address[5];
		
		if( RS_Ctrl==RS_CTRL_Pswd )       return 0x20;	//修改密码
  		
  		else if( RS_Ctrl==RS_CTRL_Read  ) return 0x21;	//读数据
  		
        else if( RS_Ctrl==RS_CTRL_Write ) return 0x22;	//写数据
        
        else 							  return 0x00;
  	}
  	else return 0x00;   								//地址身份不符合,错误不响应
}





//**********************************************************
//名称:
//功能:
//说明:
//**********************************************************
uchar PsWdCHK(uchar PsWdPtr)
{
	uchar Temp;
	uchar PassWord[4];
 
    if(ComBuf[PsWdPtr]>0x01)		return 0x00;	//权限错误  
    else
    {	
    	Addr[0] = 0xA0;   	
    	Addr[1] = 0xEC;								//编程密码地址    	
    	if(ComBuf[PsWdPtr]==0x00)	Addr[1] = 0xE8;	//清零密码地址    	
    	Len[1]  = 0x04;
		
		//密码读取和检查
    	do
    	{
    		ReadData(PassWord);
			Temp = PassWord[0]+PassWord[1]+PassWord[2];//SumCHK(PassWord,3);
    	}while((PassWord[3]!=~Temp)&&(Addr[0]<=0xA4));
    	
    	//默认密码
    	if( PassWord[3]!=~Temp ) 
    	{ 
    		PassWord[0]=0x56;
       		PassWord[1]=0x34;
       		PassWord[2]=0x12;
       		PassWord[3]=0x63;
    	}
    	
    	//密码出错修正
		ErrorModify(0xA4,PassWord);

		//密码比较
    	if( ComBuf[PsWdPtr+1]==PassWord[0] && ComBuf[PsWdPtr+2]==PassWord[1] && ComBuf[PsWdPtr+3]==PassWord[2] )
    	{	
        	if(ComBuf[PsWdPtr]==0x00)	return 0x10; 	//清零密码     	 
    		else  						return 0x11; 	//编程密码
    	}
    	else return 0x00;								//密码错误 
    } 
}





//**********************************************************
//名称:TimeTerm()
//功能:时间条件检查
//说明:
//**********************************************************
bit TimeTerm(void)
{
	uchar MinSum1;
    uchar MinSum2;
		
	//时间数据正确性检查    
	if( TimeCHK(&ComBuf[RS_CmdPtr+6])==0 )	return(0);
	
	//25天判断
	AdjDate = DateTerm();

  	//编程条件检查
 	if( Prog_Flag==1 )	return(1);	//编程允许
 	else
 	{    	
		if( AdjDate==1 )     	//25天判断
    	{    		
			//========================================
    		//不允许跨日校时
    		//========================================
    		if((Hour==0x00 && ComBuf[RS_CmdPtr+6+2]==0x23)|| 
       	   	   (Hour==0x23 && ComBuf[RS_CmdPtr+6+2]==0x00)) 		return(0);        	
			
			//时间误差计算
       		if(abs(BCD2HEX(Hour)-BCD2HEX(ComBuf[RS_CmdPtr+6+2]))>1) //小时条件检查
			{
				AdjTime = 1; //时钟异常
				return(0);
       	 	}
			else
       		{	
       		    //相差1小时之内	
       			MinSum1 = BCD2HEX(Min);
				MinSum2 = BCD2HEX(ComBuf[RS_CmdPtr+6+1]);
				
       			if(Hour>ComBuf[RS_CmdPtr+6+2]) MinSum1 += 60;
     	 		if(Hour<ComBuf[RS_CmdPtr+6+2]) MinSum2 += 60;
     	 	
     	 		if( abs(MinSum1-MinSum2)>=TimeErrorTerm )//大于时间条件
				{
					AdjTime = 1; //时钟异常
					return(0);
				}
    			else 
				{	
					AdjDate=0;	//?????????
					return(1);	//满足校时误差条件    			
				}
       		}
    	}
    	else return(0);
    }	
}





//**********************************************************
//名称:ReadMeterData()
//功能:从EEPROM中读取数据
//说明:
//**********************************************************
void ReadMeterData(uchar addr,uchar saddr,uchar DataLen)
{
	Addr[0] = addr;                //页地址
    Addr[1] = saddr;               //页内子地址	
    Len[1]  = DataLen;             //数据长度 
 	
	ReadData(&ComBuf[RS_DataPtr]);	
}





//**********************************************************
//名称:Proc33()
//功能:加减0x33H处理
//说明:
//**********************************************************
void Proc33(uchar procdata)
{
	uchar i;   	
   
    i=0x00;
    do
    {
        ComBuf[RS_CmdPtr+i] += procdata;
        i++;
    }while(i<RS_Len); 
}

⌨️ 快捷键说明

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