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

📄 rscomm.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
#include <Reg936.h>
#include <Rscomm.h>
#include <Meter_def.h>
#include <General.h>
#include <Math.h>
#include <var.h>

//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//函数定义
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
void  LCDView(void);
void  Comm_Proc(void);
void  ReadMeter(void);
void  WriteMeter(void);
void  Proc33(uchar procdata);
bit   TimeTerm(void);
uchar RxdCheck(void);
uchar PsWdCHK(uchar PsWdPtr);
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//函数外部引用
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
extern void  RTC_Read(void);
extern void  RTC_Init(void);
extern void  RTC_Set(uchar staddr,uchar idata *ptr,uchar len);
extern bit   DateTerm(void);
extern bit   DateCHK(uchar idata *ptr);
extern bit   TimeCHK(uchar idata *ptr);
extern uchar LastMonthSN(uchar sn);
extern uchar Temp_Read(void);
extern void  CreateRealTimeEry(void);
extern void  PowerDownProcess(void);
extern bit   Write24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);
extern bit   Read24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);

//**********************************************************
//名称:Comm_Proc()
//功能:
//说明:通讯处理函数
//**********************************************************
void Comm_Proc(void)
{
  uchar i,j;
  uchar TFlag;
    
  if(RxdFlag==1) //接收结束,进行数据处理并回应上位机
  {
    Watchdog_feed(); //喂狗
    Flag &= 0xE0;
    //TimeAdj  = 0;	//校时时间
    //TimeProg = 0;	//编程时间
    //RxdFlag  = 0;	//接收状态
    //TxdFlag  = 0;	//通信应答
    //TxdWork  = 0;	//发送状态
    ErrInfFlag = 0x00;  //通讯错误信息标志
    
    TFlag = RxdCheck(); //通讯帧格式及通讯地址检查
    
    if(TFlag!=0x00) //检查正确
    { 	    
      CommLCDSec = CommLCDTime; //液晶通讯指示显示时间	
      Proc33(0xCD); //数据去0x33处理
    
      if(TFlag==0x10) //广播校时,无应答
      {
        if((TimeCHK(&ComBuf[RS_CmdPtr+0])==1)&&(DateCHK(&ComBuf[RS_CmdPtr+3])==1))//日期时间检查正确
        {
          //在5分钟有效时间判断函数TimeTerm()中使用以下变量
          ComBuf[RS_CmdPtr+6+0] = ComBuf[RS_CmdPtr+0]; //秒
	  ComBuf[RS_CmdPtr+6+1]	= ComBuf[RS_CmdPtr+1]; //分
	  ComBuf[RS_CmdPtr+6+2]	= ComBuf[RS_CmdPtr+2]; //时
          if((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); //日、月、年
    				
    	    Flag    |= 0x03;
    	    //TimeAdj  = 1;	//校时标志
    	    //TimeProg = 1;	//编程标志
    	    Fee_Flag = 1;       //时段费率判断
    	    EryBln_Flag = 1;    //电量结算
          }
        }
      }  		    		
 		
      else if(TFlag==0x20) //密码修改
      { 
      	//密码初始化
      	if((ComBuf[10]==0x00)&&(ComBuf[11]==0x23)&&(ComBuf[12]==0x09)&&(ComBuf[13]==0x94))
      	{
          j = 0x10;
      	}
      	//密码修改(老密码修改新密码)
      	else
      	{
          j = PsWdCHK(RS_CmdPtr); //旧密码检查
        }
        //从站出错不应答
        if((j!=0x00)&&(PAN>=PAO)) //高密级可修改低密级
        {
          for(i=4;i>0;--i) //构造返回数据,新密级+新密码
          {
            ComBuf[RS_CmdPtr+i-1] = ComBuf[RS_CmdPtr+4+i-1];
          }
          i = PAN; //暂存待修改密码的密级
          ComBuf[RS_CmdPtr+4] = ~SumCHK(&ComBuf[RS_CmdPtr+1],3);//密码的校验和    
          Write24C64(&ComBuf[RS_CmdPtr+1],0x08,0x54+i*4,4); //保存新密码
          
          Flag |= 0x0A;
          //TimeProg = 1; //编程标志
          //TxdFlag  = 1; //回应标志
          RS_Len  = 0x04;
        }
      }
      
      else if(TFlag==0x21) //读电表数据或LCD显示屏查看
      {
      	if(RS_Len==0x02)  ReadMeter(); //读电表数据
      	else if((RS_Len==0x03)&&(RS_CmdL==0xE1)&&(RS_CmdH==0xEE))  LCDView(); //LCD显示屏查看
      	else  Flag &= 0xE0;
      }
      
      else if(TFlag==0x22) //设置电表数据
      {		
        WriteMeter();
      }    
      
      else  
      {
        Flag &= 0xE0;
      }
               	
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    if(TimeProg==1) //编程时间及编程次数
    {
      TimeProg = 0;
      RTC_Read();
      //编程时间
      ComBuf[50] = Min;  //分
      ComBuf[51] = Hour; //时
      ComBuf[52] = Day;  //日
      ComBuf[53] = Month;//月
      ComBuf[54] = SumCHK(&ComBuf[50],4);//校验和		
      //读编程次数和编程事件指针
      Read24C64(&ComBuf[55],0x08,0xF9,5);
      i= ComBuf[55]+ComBuf[56];
      //读编程次数失败的处理		
      if(i!=ComBuf[57])
      {
        ComBuf[55] = 0x00;
        ComBuf[56] = 0x00;
      }  
      //读编程事件指针失败的处理
      if(ComBuf[59]!=~ComBuf[58])
      {
      	ComBuf[58] = 0x00;
        ComBuf[59] = 0xFF;
      }
      BCDINC(&ComBuf[55],2); //编程次数+1
      ComBuf[57]=ComBuf[55]+ComBuf[56];
      
      ComBuf[58]++; //编程事件指针+1
      if(ComBuf[58]==0x05)  ComBuf[58] = 0x00;
      ComBuf[59] = ~ComBuf[58];
      //写编程次数和编程事件指针
      Write24C64(&ComBuf[55],0x08,0xF9,5);
      //写编程时间
      Write24C64(&ComBuf[50],0x08,0xE0+ComBuf[58]*5,5);
      //写校时时间
      if(TimeAdj==1)
      {
        TimeAdj = 0;
        ComBuf[54] = ~ComBuf[54];
        Write24C64(&ComBuf[50],0x08,0x7A,5); //写本次校时时间
      }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////    

    //通讯回应处理
    ComPtr  = 0x00;  //通讯缓冲区初始指针	
    if(TxdFlag==1)	 //电表应答
    {		 	      		
      TxdFlag  = 0;
      Proc33(0x33); //数据加0x33处理
      RS_Ctrl |= 0x80; //从机应答标识符
      if(ErrInfFlag==0xAA)  RS_Ctrl |= 0x40; //通讯错误信息标志
      RS_CRC   = SumCHK(ComBuf,RS_CmdPtr+RS_Len);
      RS_End   = 0x16;			
      //※※※※※※※※※※※※※※※※※※※※※※※※※※※
      //信道配置
      HW38K   = 1;    //P0.7红外调制信号输出引脚
      CTRL485 = 1;    //关闭RS485输出信道,打开默认的红外调制
      TMOD   |= 0x21; //设置Timer0,选择定时器模式2--通讯超时检测
  		      //设置Timer1,选择定时器模式3--红外载波		        	
      TAMOD   = 0x00; //T0M2=0,T1M1=0,T1M0=1
  		      //T1M2=0,T1M1=1,T1M0=0                   
      TH1     = 0xD0; //Timer1设置自动重装值		
      TL1     = 0xD0;                                    
      AUXR1  |= 0x20; //ENT1=1,Timer1溢出使P0.7发生翻转
      TR1     = 1; 
      if(COMMSEL==1)  //RS485发送配置
      {
        CTRL485 = 0;  //打开RS485输出信道
        TR1     = 0;  //关闭默认的红外调制
      }	                	
      //※※※※※※※※※※※※※※※※※※※※※※※※※※※							
      TxdWork  = 1;	  //发送标志,此时不允许接收
      CommFlag = 0;       //UART通讯状态标志
      ES       = 1;				
      TB8      = 1;	  //偶校验
      SBUF     = 0xFE;    //发送第一个字节值 
    }		
    else
    {
      ES = 0;             //关闭UART中断允许
      ReinitUARTFlag = 1; //UART重新初始化标志
    }
  } 
  
  ////////////////////////////////////////////////////////////////////////////////////////////////////		
  //清事件记录(清过程)
  if(ClearEvenFlag==1)
  {
    ClearEvenFlag = 0;
    ArrayInit(&ComBuf[40],32);
    //设置电表运行状态字
    //设置电表管理状态
    //预留一次清零机会
    ComBuf[73] = 0xA0; //默认清零事件指针为0
    ComBuf[74] = 0x5F;
    Write24C64(&ComBuf[73],0x05,0xE7,2);
    //清日时段表切换时发生的冻结电量
    Write24C64(&ComBuf[40],0x09,0x6A,22);
    Write24C64(&ComBuf[40],0x09,0x80,16);
    //清开盖、开端钮盒事件
    KBG_Last_State = 1; //预置表盖状态(按下为高)
    KDNH_Last_State = 0; //预置端钮盒状态(按下为低)
    KBGDeLayTimer = 0;
    KDNHDeLayTimer = 0;
    KBGSec = 0;
    KDNHSec = 0; 
    Write24C64(&ComBuf[40],0x09,0x00,32);
    Write24C64(&ComBuf[40],0x09,0x20,32);   
    //清编程事件
    Write24C64(&ComBuf[40],0x08,0xE0,30);
    //清上次结算日月份
    Write24C64(&ComBuf[40],0x08,0x8B,2);
    //清上次校时时间
    Write24C64(&ComBuf[40],0x08,0x7A,5);
    //清除电池报警时间、工作时间
    Write24C64(&ComBuf[40],0x00,0xE0,10);
    //清除有功反向累计总时间、当前月累计反向时间、最后一次反向起止时间
    //上1~12月累计反向时间、最后一次反向起止时间
    EryRev = 0; //电能反向标志清零
    RevDeLayTimer = 0;
    RevSec = 0;
    for(i=0;i<7;i++)
    {
      Write24C64(&ComBuf[40],0x04,(i*2)<<4,32);
    }
    //清清零事件
    for(i=0;i<8;i++)
    {
      Write24C64(&ComBuf[40],0x05,(i*2)<<4,32);
    }      
  } 
  ////////////////////////////////////////////////////////////////////////////////////////////////////		
  
  //////////////////////////////////////////////
  ePowerDownCheckFlag = ENABLE; //打开掉电检测
  //////////////////////////////////////////////
  PowerDownProcess(); //掉电检测处理程序
}
	
//**********************************************************
//名称: ReadMeter()
//功能: 读电表中的数据
//说明: 
//**********************************************************
void ReadMeter(void)
{	
  char  Temp[2];
  uint  RSCommand;
  uchar i,j,addr1,addr2;
  uchar LLastEryFlag=0x00;
  
  if(isLastMonthEry==0x01)  LLastEryFlag = 0x01; //用上上月电量代替上月电量
	
  TxdFlag = 1; //数据返回标志
  RS_Len  = 2+16; //返回数据长度
  RSCommand = (RS_CmdH<<8)+RS_CmdL;

  switch(RSCommand)
  {
    case 0x5501://软件版本号
                {
                  ComBuf[RS_DataPtr+0]  = 0x30; //版本序号:3.0
                  ComBuf[RS_DataPtr+1]  = 0x06; //年号:06
                  ComBuf[RS_DataPtr+2]  = 0x55; //用户地区号:55
                  ComBuf[RS_DataPtr+3]  = 0x00; //           00
                  ComBuf[RS_DataPtr+4]  = 0x00; //OEM外协厂家编号、备用码:00
                  ComBuf[RS_DataPtr+5]  = 0x42; //产品分类号:B
                  ComBuf[RS_DataPtr+6]  = 0x56; //           V
                  ComBuf[RS_DataPtr+7]  = 0x34; //产品型号:4
                  ComBuf[RS_DataPtr+8]  = 0x38; //         8
                  ComBuf[RS_DataPtr+9]  = 0x32; //         2
                  ComBuf[RS_DataPtr+10] = 0x46; //         F
                  
                  RS_Len =2+11;
                  break;
                }
    case 0x9010://当前月正向总有功(总)指数
    case 0x9012://当前月正向总有功(峰)指数
    case 0x9013://当前月正向总有功(平)指数
    case 0x9014://当前月正向总有功(谷)指数
                {
                  if(RS_CmdL==0x10)  i = 0;
                  else  i = RS_CmdL-0x11;
                  CreateRealTimeEry();
                  for(j=0;j<4;j++)
                  {
                    ComBuf[RS_DataPtr+j] = CommVariant[16+i*4+j];
                  }
        
                  RS_Len =2+4;
                  break;
                }
    case 0x9020://当前月反向总有功(总)指数
    case 0x9022://当前月反向总有功(峰)指数
    case 0x9023://当前月反向总有功(平)指数
    case 0x9024://当前月反向总有功(谷)指数
                {
                  if(RS_CmdL==0x20)  i = 0;
                  else  i = RS_CmdL-0x21;
                  CreateRealTimeEry();
                  for(j=0;j<4;j++)
                  {
                    ComBuf[RS_DataPtr+j] = CommVariant[32+i*4+j];
                  }
        
                  RS_Len =2+4;
                  break;
                }  
    case 0x901F://当前月正向总有功指数数据块       
    case 0x902F://当前月反向总有功指数数据块
                {
                  if(RS_CmdL==0x1F)  i = 16;
                  else  i = 32;
                  CreateRealTimeEry();
                  for(j=0;j<16;j++)
                  {
                    ComBuf[RS_DataPtr+j] = CommVariant[i+j];
                  }
                  //RS_Len =2+16;
                  break;
                }                                        

⌨️ 快捷键说明

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