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

📄 comm_module.c

📁 一个电表的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
 void DL645_Command(void)
 {
   unsigned char i,j;


   MoveData_Api(eMeterNo_Dtr+e2RAM_Adr,(unsigned int)(&TempChar[0]),6);     //读入表号存入TempChar共用数据区
//--------------------------------------------------------------------------------
//                      表号比较,支持半字节缩位

   j=0;
   for (i=0;i<6;i++)
   {
      if (((TempChar[i] & 0x0F) == (RxTxBuf[i+1] & 0x0F)) && (!j ))
      {
         if ((TempChar[i] & 0xF0) != (RxTxBuf[i+1] & 0xF0))
         {
            j=12;
            if  ((RxTxBuf[i+1] & 0xF0) != 0xA0)
            {
               j=0xff;
               break;
            }
         }
      }
      else
      {
         if (RxTxBuf[i+1] != 0xAA)
         {
            if (RxTxBuf[i+1] == 0x99)
            {
               j++;           //记录广播地址"99"的个数 (6个字节的99才算广播地址)
            }
            else
            {
               j=0xff;
               break;
            }
         }
      }
   }
   if ((j!=6) && (j!=0) && (j!=12))
     return;                               //非本表地址,返回。


//--------------------------------------------------------------------------------
   Comm_Flg=1;                     //显示通信提示符号

   if (Key_Flg )
     Key_Time = KeyMaxTime;        //刷新编程有效时间

//--------------------------------------------------------------------------------
//                         校验和检查

   j=RxTxBuf[0];
   for (i=1;i<RxTxLen-2;i++)
     {j += RxTxBuf[i];}                    //求校验和

   for (i=0;i<RxTxBuf[9];i++)
     {RxTxBuf[10+i] -=0x33;}               //数据 -0x33H处理

   if (j != RxTxBuf[RxTxLen-2])
   {                                       //校验和检查错误,返回非法数据错误。
     RxTxBuf[8] |=0xC0;
     RxTxBuf[9] = 1;
     RxTxBuf[10] = Data_err;               // 非法数据

     DL645_DataSend();                     //按照DL/T-645协议发送数据
     return;
   }

//--------------------------------------------------------------------------------
//                   通信命令处理

   switch (RxTxBuf[8])              //CommandByte 命令字节
   {
     case 0x01:
        Read_Response();            //"01"读命令处理
        break;

     case 0x04:
        Write_Response();            //"04"写命令处理
        break;

     case 0x08:
     //   TimeChecking_Response();     //"08"广播校时命令处理
        break;


     default:
     //                           //非法命令,返回非法数据应答
			break;

   }
}


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

//          异常应答设置
//          错误命令
//          错误字

void ErrorResponse(unsigned char err_comm,unsigned char err_word )
{
  RxTxBuf[8] = err_comm;
  RxTxBuf[9] = 1;
  RxTxBuf[10] = err_word;

}

//-----------------------------------------------------------------------------------------------
/*                       发送数据
;          1、判断当前是红外口还是RS485口在通信,根据不同进行处理
           2、关闭接收
;          3、启动偶校验发送(一字节0xfe)
;          4、其余的数据由中断发送完毕
;          5、发送数据在RxTxBuf[]数据区钟,发送数据长度在RxTxLen中
*/



void DL645_DataSend(void)
{
  unsigned char i,add;

  RxTxBuf[0] = 0x68;
  ReadE2prom_Api((eMeterNo_Dtr+e2RAM_Adr),(unsigned int)(&RxTxBuf[1])+xRAM_Adr,6);
/*
  for (i=0;i<6;i++)
    {RxTxBuf[i+1] = MeterAdr[i];}             //装载表号
  RxTxBuf[7] = 0x68;
*/
  for (i=0;i<RxTxBuf[9];i++)
   { RxTxBuf[10+i] +=0x33; }                   //+33

  add = RxTxBuf[0];
  for (i=1;i<(RxTxBuf[9] + 10);i++)
    {add += RxTxBuf[i];}

  RxTxBuf[i] = add;                            //校验和
  RxTxBuf[i+1] = 0x16;                         //帧结束标志

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

  if (IR_CTRL)                   //是否为红外通信?
   {
     EPCFG_bit.MODE38_TxD = 1;    //38KHz输出到发送端口
     CommHWDelyTime = 250;
   }

  RxTxLen = RxTxBuf[9]+12;   //设定发送长度(645标准)
  RxTxAdr = RxTxBuf;         //置发送数据首地址

  SCON_bit.REN = 0;          //关接收
  SCON_bit.TI = 0;           //清发送中断
  SendByte(0xfe);            //发送一个字节

  CommByte_Time =8;          //80ms(发送一个字节最大等待时间80ms)
  RxTxFlg = 3;               //置发送状态

}




//-----------------------------------------------------------------------------------------------
//          01 通信命令(即读命令)

void Read_Response(void)
{
  unsigned int id,idAdr;
  unsigned char idDataLen;
  id = RxTxBuf[10] + (RxTxBuf[11] << 8);                 //取id
  if (RxTxBuf[11]==0x01)                                 //0x0100~0x012A
  {                               //读能量寄存器
    ReadEnergyReg3(RxTxBuf[10]);
    RxTxBuf[12]=Temp8L;
    RxTxBuf[13]=Temp8M;
    RxTxBuf[14]=Temp8H;
    RxTxBuf[8] = 0x81;
    RxTxBuf[9] = 5;
    DL645_DataSend();                     //按照DL/T-645协议发送数据
    return;
  }
  idAdr = GetDataTree_Adr_Len(id,&idDataLen );          //获取id数据地址和长度
  idDataLen &=0x7F;
  if (idDataLen)
  {
    RxTxBuf[8] = 0x81;
    RxTxBuf[9] = idDataLen + 2;
    MoveData_Api(idAdr,(unsigned int)(&RxTxBuf[12])+xRAM_Adr,idDataLen);             //转送数据
  }
  else
  {
    ErrorResponse(0xC1,iD_err);                  //发送无此标识信息错误应答
  }
  DL645_DataSend();                     //按照DL/T-645协议发送数据
}



//-----------------------------------------------------------------------------------------------
//             "0x11"读能量寄存器数据命令

void Read_Energy(void)
{

}
//-----------------------------------------------------------------------------------------------

//             "04"写命令处理

void  Write_Response(void)            //"04"写命令处理
{
  unsigned int id,idAdr;
  unsigned char idDataLen;

  id = RxTxBuf[10] + (RxTxBuf[11] << 8);                 //取id
  idAdr = GetDataTree_Adr_Len(id, &idDataLen );          //获取id数据地址和长度

  if (CompareE2prom(ePassWd00_Dtr,(unsigned int)(&RxTxBuf[12])+xRAM_Adr,4)==ErrorTrue)    //是否是用户密码?
  {
    if (CompareE2prom(eComposerPassword_Dtr,(unsigned int)(&RxTxBuf[12])+xRAM_Adr,4)==ErrorTrue)  //是否是设计者密码?
    {
      ErrorResponse(0xC4,Password_err);      //密码不正确,返回密码错误
    }
    else
    {
       goto  Down_comm;
    }
  }
  else if (Key_Flg &&(idDataLen & 0x80))      //判断是否是可写数据项和编程开关是否打开?
  {
   Down_comm:
    idDataLen &= 0x7f;
    MoveData_Api((unsigned int)(&RxTxBuf[16])+xRAM_Adr,idAdr,idDataLen);      //转送数据
    if (id==0xC011)
       SetTime();            //设置时钟
    else if (id==0xC010)
    {
      Temp8 = Week;
      Week = Date;
      Date = Month;
      Month = Year;
      Year = Temp8;
    }
    RxTxBuf[8] = 0x84;                 //正常应答返回
    RxTxBuf[9] = 0;
  }
  else
  {
    ErrorResponse(0xC4,Data_err);       //不是可写数据项或编程开关没有打开,返回非法数据操作
  }

  DL645_DataSend();                    //按照DL/T-645协议发送数据
  CommRefurbish();                     //通信需要刷新的数据

}

//===============================================================================================
#endif

⌨️ 快捷键说明

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