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

📄 rscomm.c

📁 江苏单相复费率电能表方案
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <Reg931.h>
#include <Rscomm.h>
#include <Meter_def.h>
#include <General.h>
#include <Math.h>

#ifdef    uchar 
  #define READYDEF 1     //宏uchar已定义
#else  
  #define uchar unsigned char 
#endif



//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//						变量定义
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
// MeterFlag
extern uchar bdata MeterFlag;
extern bit Battery;
extern bit Hardware;
extern bit RsComm; 
extern bit AdjTime;
extern bit EryRev;
extern bit AdjDate;
extern bit Fee0;
extern bit Fee1;
//Flag
extern uchar bdata Flag;
extern bit TimeAdj;
extern bit TimeProg ;
extern bit RxdFlag;
extern bit TxdFlag;
extern bit TxdWork;
extern bit DspType;
extern bit DspPage;
extern bit DspFlag;

//SystemStates
extern uchar bdata SystemStates; 
extern bit Comm_RTC_Err;
extern bit Comm_EPM_Err;
extern bit Data_RTC_Err;
extern bit Data_EPM_Err;
extern bit EryBln_Flag;
extern bit Prog_Flag;
extern bit Fee_Flag;
extern bit CommFlag;

extern uchar DspSec;
extern uchar DspPtr;
extern uchar ComPtr;
extern uchar CommTimer;
extern uchar CommSec;

extern uchar Len[2];
extern uchar Addr[2];
extern uchar DspPara[4];
extern uchar PulseTmp[6];  
extern uchar EryTmp[6];
extern uchar Ptr[8];
extern uchar RTC[8];
extern uchar idata ComBuf[RS_MaxSize];




//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//						  函数定义
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
void  Comm_Proc(void);
void  ReadMeter(void);
void  WriteMeter(void);

void  Proc33(uchar procdata);
void  ReadMeterData(uchar addr,uchar saddr,uchar DataLen);

bit   TimeTerm(void);

uchar RxdCheck(void);
uchar PsWdCHK(uchar PsWdPtr);


//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//						函数外部引用
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
extern void  RTC_Read(void);
//extern void  Fee_CHK(void);
extern void  WriteEPMData(uchar idata *ptr);
extern void  RTC_Init(void);
extern void  RTC_Set(uchar staddr,uchar idata *ptr,uchar len);
extern void  ErrorModify(uchar addr,uchar idata *ptr);

extern bit   DateTerm(void);
extern bit   DateCHK(uchar idata *ptr);
extern bit   TimeCHK(uchar idata *ptr);
extern bit   ReadData(uchar idata *ptr);

extern uchar LastMonthSN(uchar sn);



//**********************************************************
//名称:Comm_Proc()
//功能:
//说明:通讯处理函数
//**********************************************************
void Comm_Proc(void)
{
    uchar i;
    uchar j;
    uchar TFlag;
    
    if( RxdFlag==1 )
    {
  		Watchdog_feed();				//喂狗  		
  		
  		//※※※※※※※※※※※※※※※※※※※※※※※※※※※
		//信道配置	    
		HW38K   = 1;		

		CTRL485 = 1;					//打开默认:红外调制		
		TR1   	= 1; 

		if(COMMSEL==1)					//RS485发送配置
		{
			CTRL485 = 0;			
			TR1     = 0;
		}	                	
    	//※※※※※※※※※※※※※※※※※※※※※※※※※※※

  		Flag &= 0xE0;
    	//TimeAdj  = 0;					//校时时间
		//TimeProg = 0;					//编程时间
		//RxdFlag  = 0;					//接收状态
    	//TxdFlag  = 0;					//通信应答
		//TxdWork  = 0;					//发送状态		
  		  	
	  	TFlag = RxdCheck();				//通讯帧格式及通讯地址检查		
    	
    	if( TFlag!=0x00 )
    	{ 	       	
    		Proc33(0xCD);	            //数据去0x33处理

       		if(TFlag==0x10)				//广播校时,无应答 
    		{
        	    if((TimeCHK(&ComBuf[RS_CmdPtr]+0)==1)&&(DateCHK(&ComBuf[RS_CmdPtr+3])==1))
				{
					ComBuf[RS_CmdPtr+6] = ComBuf[RS_CmdPtr+0];
					ComBuf[RS_CmdPtr+7]	= ComBuf[RS_CmdPtr+1];
					ComBuf[RS_CmdPtr+8]	= ComBuf[RS_CmdPtr+2];
	
					if(Prog_Flag==1||((ComBuf[RS_CmdPtr+3]==Day)&&(ComBuf[RS_CmdPtr+4]==Month)&&(ComBuf[RS_CmdPtr+5]==Year)&&(TimeTerm()==1)))
					{
						//RTC_Init();
						RTC_Set(0x00,&ComBuf[RS_CmdPtr+0],0x03);	//秒、分、时
        				RTC_Set(0x40,&ComBuf[RS_CmdPtr+3],0x03);	//日、月、年
        			        			
        				CommSec  = CommLEDTime;						//亮10秒
						LED_COMM = 0;

						Flag    |= 0x03;					
						//TimeAdj  = 1;		//校时标志
						//TimeProg = 1;		//编程标志
						Fee_Flag = 1; 		//时段费率判断
					
						//*******
						EryBln_Flag = 1;    //电量结算
				 	}
				}
    		}  		    		


    	    //※※※※※※※※※※※※※※※※※※※※※※※※※※※※  	    
    		else if( TFlag==0x11 )			//广播设置电表表号
    		{
    		    for(i=0;i<6;i++)ComBuf[1+i] = ComBuf[RS_CmdPtr+i]; 	//表号数据返回			
        			
        		ComBuf[RS_CmdPtr+6] = SumCHK(&ComBuf[RS_CmdPtr],6); //表号检验和
        			
        		Addr[0] = 0xA0;        			
        		Addr[1] = 0xF0;          //写局编号
        		//Addr[1] = 0xF8;       //写出厂编号				
        		Len[1]  = 0x07;             		
				WriteEPMData(&ComBuf[RS_CmdPtr]);
						            
  		        RS_Len  = 0x00; 
  		            		          		
            	Flag |= 0x0A;
            	//TimeProg = 1;
            	//TxdFlag  = 1;             		    				
    		}   	    
    	    
			/*    	    
    	    //※※※※※※※※※※※※※※※※※※※※※※※※※※※※    	    
    	    else if( TFlag==0x12)					//自定义命令集
            {    
    		    if( RS_CmdH==0x00 && RS_CmdL==0x00) //数据清零命令
                {                  
                    LED_F    = 0;
                    LED_G    = 0;                    
                    LED_COMM = 0;
        		    CommSec  = CommLEDTime;			//亮10秒
        		    
        		    EA = 0;
        		    ArrayInit(ComBuf,RS_MaxSize);
        		    
        		    //数据清零        		    
					for(i=0;i<16;i++)
                    {
                        Addr[0] = 0xA0;
					    Addr[1] = i*16;						
    				    Len[1] 	= 16; 
    				    WriteEPMData(ComBuf);
    				    
    				    Addr[0] = 0xA2;
    				    WriteEPMData(ComBuf);
                   	}

					ComBuf[0] = 0x02;
					ComBuf[1] =~0x02;

					Addr[0]   = 0xA0;
   					Addr[1]   = 0xBE; 
   					Len[1]    = 0x02;   	
					WriteEPMData(ComBuf);
                     
                    AUXR1 |= 0x08;					//复位  
                }    		               
    		}
    	    //※※※※※※※※※※※※※※※※※※※※※※※※※※※※	
    		*/
    			
    		else if(TFlag==0x20)		//密码修改
    		{
    			j = PsWdCHK(RS_CmdPtr); //旧密码检查

				for(i=0;i<4;i++)		//构造返回数据
    			{
    				ComBuf[RS_CmdPtr+i] = ComBuf[RS_CmdPtr+4+i];
            	}

            	ComBuf[RS_CmdPtr+4] = ~SumCHK(&ComBuf[RS_CmdPtr+1],3);//密码的校验和
            	
            	Addr[0] = 0xA0;
            	Len[1] 	= 0x04;			

				if((j==0x10)&&(ComBuf[RS_CmdPtr]==0x00))//清零密码
    			{
            		Addr[1] = 0xE8;         
					WriteEPMData(&ComBuf[RS_CmdPtr+1]);
					
            		Flag |= 0x0A;
            		//TimeProg = 1;
            		//TxdFlag  = 1;        	
				}
					
    			if((j==0x11)&&(ComBuf[RS_CmdPtr]==0x01))//编程密码
    			{
            		Addr[1] = 0xEC;
            		WriteEPMData(&ComBuf[RS_CmdPtr+1]);
					
            		Flag |= 0x0A;
            		//TimeProg = 1;
            		//TxdFlag  = 1;        	
				}
				RS_Len  = 0x04;		
 			} 
    		
    		else if(TFlag==0x21) ReadMeter(); 			//读电表数据 
    		else
    		{				 
    			WriteMeter();							//设置电表数据
				RS_Len = 0x00;    		
    		}    	    	
    	}
    	
    	if( TimeProg==1 )							    //编程时间及编程次数
    	{
    		TimeProg = 0;
    	
     		RTC_Read();
           		
     		//编程时间
     		ComBuf[40] = Min;							//分
     		ComBuf[41] = Hour;							//时
     		ComBuf[42] = Day;							//日
     		ComBuf[43] = Month;        					//月
     		ComBuf[44] = SumCHK(&ComBuf[40],4);         //校验和
           		
        	//编程次数
				Addr[0] = 0xA0;
        Addr[1] = 0xE5;
        Len[1]  = 0x03;
        do
        {
        		ReadData(&ComBuf[45]);
						i= ComBuf[45]+ComBuf[46];				//SumCHK(&ComBuf[45],2);        		        				
        } while((i!=ComBuf[47])&&(Addr[0]<=0xA4));
           		
        if(i!=ComBuf[47])
        {
        	ComBuf[45] = 0x00;
					ComBuf[46] = 0x00;
        }           		
           		
        	BCDINC(&ComBuf[45],2,1);					//编程次数+1
        	ComBuf[47]=ComBuf[45]+ComBuf[46];			//SumCHK(&ComBuf[45],2);            	
			
			//写编程时间+编程次数	
        	Addr[0] = 0xA0;
        	Addr[1] = 0xE0;
        	Len[1]  = 0x08;           		
	  			WriteEPMData(&ComBuf[40]);
			
        	//写校时时间
		 		if(TimeAdj==1)
        	{   
						TimeAdj = 0; 
   			
   					Addr[0] = 0xA2;
        		Addr[1] = 0xF8;           			 	
        		Len[1]  = 0x05;
        		WriteEPMData(&ComBuf[40]);				
        	}    		
    	}

    	ComPtr  = 0x00; 					//通讯缓冲区初始指针
		
			if(TxdFlag==1)						//电表应答
    	{		 	
		 		TxdFlag  = 0;
		 	
		 		LED_COMM = 0;		 	
		 		CommSec  = CommLEDTime;			//亮10秒
           
				Proc33(0x33);                   //数据加0x33处理

				RS_Ctrl |= 0x80;				//从机应答标识符
   			RS_CRC   = SumCHK(ComBuf,RS_CmdPtr+RS_Len);
				RS_End   = 0x16;
         				
				TxdWork  = 1;					//发送标志				
				ES       = 1;
						
				TB8  	 = 1;					//偶校验
				SBUF     = 0xFE;					//发送第一个字节值
			}	
    	else 
			{
 				COMMSEL = 0;  					//默认红外通讯方式
				CTRL485 = 1;  					//RS485接收状态  	

				TR1     = 0;					//Timer1关闭,无红外载波
//			HW38K   = 1;					//P0.7置高			   						
				CommFlag= 0;
			
				ArrayInit(ComBuf,RS_MaxSize);		
			
				TR0 = 0;
    		TH0 = 0x53; 					//Timer0定时12mS初值			
    		TL0 = 0x33;	
				TR0 = 1;						//打开Timer0  
		}			
	} 
}



//**********************************************************
//名称:ReadMeter()
//功能:读电表中的数据
//说明:
//**********************************************************
void ReadMeter(void)
{	
	uchar Temp[2];	
	
   	TxdFlag = 1;								//数据返回标志
  
    RS_Len  = 2+4;								//返回数据长度
     
   	if((RS_CmdH==0x90)&&(RS_CmdL==0x1F))		//当前有功电量集合
   	{
 		ReadMeterData(0xA0,0xC0,16);			//整数
 		
 		ComBuf[RS_DataPtr+0]  = EryTmp[0];		//总电量小数
 		ComBuf[RS_DataPtr+4]  = EryTmp[1];		//峰电量小数
 		ComBuf[RS_DataPtr+8]  = EryTmp[2];		//平电量小数
 		ComBuf[RS_DataPtr+12] = EryTmp[3];		//谷电量小数
 		
 		RS_Len  = 2+16;
 	}		
 	 	
 	else if((RS_CmdH==0x90)&&(RS_CmdL==0x20))	//反向累计电量
 	{    	   		
        ReadMeterData(0xA0,0xD0,0x04);		    //反向电量整数        
        ComBuf[RS_DataPtr]  = EryTmp[4];		//反向电量小数         
        //RS_Len  = 2+4; 	
    } 
  
   	else if((RS_CmdH==0xB0)&&(RS_CmdL==0x20))	//反向起始时间
   	{   
   		ReadMeterData(0xA0,0xAA,4);   		
        //RS_Len = 2+4;
    }
    
    else if((RS_CmdH==0xB0)&&(RS_CmdL==0x21))	//反向累计时间
    { 
    	ReadMeterData(0xA0,Ptr[6],3);    	
    	RS_Len = 2+3;
 	}		
 	
 	else if((RS_CmdH==0xB2)&&(RS_CmdL==0x10))	//编程时间
   	{ 
    	ReadMeterData(0xA0,0xE0,4);    	        
        //RS_Len = 2+4;
    }

    else if((RS_CmdH==0xB2)&&(RS_CmdL==0x12))	//编程次数
    {
    	ReadMeterData(0xA0,0xE5,2);    	
    	RS_Len = 2+2;
 	}
  
   	else if((RS_CmdH==0xC0)&&(RS_CmdL==0x10))	//当前日期及周次
   	{  
        ComBuf[RS_DataPtr+0] = Week; 
    	ComBuf[RS_DataPtr+1] = Day;
        ComBuf[RS_DataPtr+2] = Month;
    	ComBuf[RS_DataPtr+3] = Year;    	
    	//RS_Len = 2+4;
    }
    
    else if((RS_CmdH==0xC0)&&(RS_CmdL==0x11))	//当前时间
    {    
    	ComBuf[RS_DataPtr+0] = Sec; 
    	ComBuf[RS_DataPtr+1] = Min;
      ComBuf[RS_DataPtr+2] = Hour;        
      RS_Len = 2+3;
	 	}
    
    else if((RS_CmdH==0xC0)&&(RS_CmdL==0x20))	//运行状态
    {		
    	ComBuf[RS_DataPtr] = MeterFlag;
    	RS_Len = 2+1;  
    }
	
    else if((RS_CmdH==0xC0)&&(RS_CmdL==0x30))	//电表常数
    {	
    	ComBuf[RS_DataPtr+0] = 0x00;
    	ComBuf[RS_DataPtr+1] = 0x16;
    	ComBuf[RS_DataPtr+2] = 0x00; 

			RS_Len  = 2+3;
    }
	
	else if((RS_CmdH==0xC0)&&((RS_CmdL==0x32)||(RS_CmdL==0x33)))
	{		       	
      Temp[0] = 0xF8;							//出厂编号
      if(RS_CmdL==0x33) 	Temp[0] = 0xF0; 	//局编号      	
       	//else            	Temp[0] = 0xF8;		//出厂编号        
        
      ReadMeterData(0xA0,Temp[0],6);       
    	RS_Len  = 2+6;
   } 
   
   else if((RS_CmdH==0xC1)&&(RS_CmdL==0x17))	//自动抄表日期 
   {   		
   		ReadMeterData(0xA0,0xD4,3);
      RS_Len 	= 2+2;
   }
   	
   else if((RS_CmdH==0xC3)&&(RS_CmdL==0x3F))	//时段表 
   {   		
   		//有效时段数
   		Addr[0] = 0xA2;
    	Addr[1] = 0xCE;
      Len[1]  = 0x02;
      ReadData(Temp);
        
        //数据范围限制
      if( (Temp[0]>12)||(Temp[0]<2))Temp[0] = 0x02;

      Temp[0] *= 0x03;
  		ReadMeterData(0xA2,0xD0,Temp[0]);
  		  		      	
      RS_Len  = 2+Temp[0];
   	}
   	
   	else if((RS_CmdH==0xD1)&&(RS_CmdL>=0x20)&&(RS_CmdL<=0x2B))//电量历史数据		
   	{
   		Temp[0]  = LastMonthSN(RS_CmdL&0x0F)<<4;	
  		ReadMeterData(0xA2,Temp[0],16); 		   		   		
   		RS_Len =2+16;
   	}
   	else TxdFlag = 0;	//命令不在服务范围  
}





//**********************************************************
//名称:
//功能:
//说明:
//**********************************************************
void WriteMeter(void)
{
   	uchar i;
 	uchar j; 
 	uchar k;	
 	uchar TFlag;
   	uchar Temp[2];

   	Watchdog_feed();											//喂狗

    Flag |= 0x0A;
    //TxdFlag = 1;	//回应
	//TimeProg= 1;	//编程时间
    

⌨️ 快捷键说明

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