Chinaunix首页 | 论坛 | 博客
  • 博客访问: 524343
  • 博文数量: 63
  • 博客积分: 1265
  • 博客等级: 中尉
  • 技术积分: 789
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-06 21:54
文章分类

全部博文(63)

文章存档

2017年(1)

2016年(3)

2015年(2)

2013年(5)

2012年(20)

2011年(32)

分类: C/C++

2012-04-17 14:39:18

    104规约文章很长,很难理解,对于初学的人员来说比较难理解,其实104规约主要理解一下报头部分的控制报文。
   

点击(此处)折叠或打开

  1. //设置遥测APCI
  2. void CMainFrame::SetYCAPCI()
  3. {
  4.  memset(byteAPDUYC,0,sizeof(byteAPDUYC));//初始化
  5.  //计算报头字节
  6.  //////////////////APCI//////////////////////////////////////////////////////
  7.  byteAPDUYC[0] = 0x68;//报头字
  8.  byteAPDUYC[1] = 0xFA;//APDU长度,最大253 计算**
  9.      
  10.  byteAPDUYC[2] = 0x12;//1 8位控制域 低位  00000010
  11.  byteAPDUYC[3] = 0x00;//2 8位控制域 高位  00000000  
  12.     // 0000000000000010 I格式发送帧计数
  13.  byteAPDUYC[4] = 0x02;//3 8位控制域 低位 00000010
  14.  byteAPDUYC[5] = 0x00;//4 8位控制域 高位 00000000
  15.     // 0000000000000010 I格式接收帧计数
  16.  /////////////////////ASDU////////////////////////////////////////////////
  17.  byteAPDUYC[6] = 0x15;//标识符 遥测
  18.  //可变帧限定词 10111100 第一位1表示连续,如果为0表示非连续
  19.  byteAPDUYC[7] = 0xBC;//计算** 0111100 60个数据
  20.  //传送原因
  21.  byteAPDUYC[8] = 0x14;//响应总召唤 传送原因
  22.  byteAPDUYC[9] = 0x00;//响应总召唤 传送原因
  23. }

理解了报头就知道了,我们在组包的时候就需要将数据加上,要计算数据的长度。


点击(此处)折叠或打开

  1. //发送遥信数据
  2. void CMainFrame::SendYXData()
  3. {
  4.  //总遥信个数
  5.  int iYXByteCout = dbm.yxsum;
  6.  //APDU个数
  7.  int iAPDUCout = 0;
  8.  //最后一帧APDU字节数
  9.  int iLastAPDUCout = 0;
  10.  //最大遥信字节数
  11.  int iMaxYx = 127;
  12.  //得到APDU个数
  13.  iAPDUCout = iYXByteCout / iMaxYx;
  14.  //得到最后一帧APDU字节数
  15.  iLastAPDUCout = iYXByteCout % iMaxYx;
  16.     //循环组APDU
  17.  for(int w=0;w<iAPDUCout;w++)
  18.  {
  19.   SetYXAPCI();
  20.   //计算公共地址 ASDU地址
  21.   BYTE *pXXTDZ = new byte[2];
  22.   memcpy(pXXTDZ, &dbm.r_yx[w*iMaxYx].NU, 2);
  23.   //给公共地址赋值
  24.   byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
  25.   byteAPDU[11] =pXXTDZ[1];
  26.   //释放临存公共地址的空间
  27.   free(pXXTDZ);
  28.   //信息体
  29.   //如果SQ=0,表示非连续数据,一个三字节信息地址,一个一字节遥信数据
  30.   //如果SQ=1,表示连续数据,用公用地址,然后连续一个字节遥信数据
  31.   int iIndex = 0;//累加号
  32.   for(int i=(w*iMaxYx);i<((w+1)*iMaxYx);i++)
  33.   {
  34.    byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
  35.    iIndex++;
  36.   }
  37.   //校验和CS
  38.   byteAPDU[12+iIndex] = 0x89;
  39.   //结束标识
  40.   byteAPDU[13+iIndex] = 0x16;
  41.   //发送
  42.   if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
  43.   {
  44.    //SetSendBufData(byteAPDU,sizeof(byteAPDU));
  45.    m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,141,atoi(strPort),strIP);
  46.    Sleep(100);
  47.   }
  48.  }
  49.  //最后一个APDU组包
  50.     SetYXAPCI();
  51.  //计算APDU长度
  52.  int ilastLen = iLastAPDUCout+10;
  53.  BYTE *pAPDULEN = new byte[1];
  54.  memcpy(pAPDULEN, &ilastLen, 1);
  55.     byteAPDU[1] = pAPDULEN[0];
  56.  //计算可变帧限定词
  57.     BYTE *pAPDULENKB = new byte[1];
  58.  memcpy(pAPDULENKB, &iLastAPDUCout, 1);
  59.     byteAPDU[7] =(pAPDULENKB[0]|0x80);//高位补1
  60.     free(pAPDULENKB);
  61.     //计算公共地址 ASDU地址
  62.  BYTE *pXXTDZ = new byte[2];
  63.  memcpy(pXXTDZ, &dbm.r_yx[iAPDUCout*iMaxYx].NU, 2);
  64.  //给公共地址赋值
  65.  byteAPDU[10] =pXXTDZ[0]; //ASDU地址 可能要累加计算** (低位在前,高位在后)2A 75
  66.  byteAPDU[11] =pXXTDZ[1];
  67.  //释放临存公共地址的空间
  68.  free(pXXTDZ);
  69.  int iIndex = 0;//顺序号
  70.  for(int i=(iAPDUCout*iMaxYx);i<iYXByteCout;i++)
  71.  {
  72.   byteAPDU[12+iIndex] = (BYTE)dbm.r_yx[i].val;
  73.   iIndex++;
  74.  }
  75.  //校验和CS
  76.     byteAPDU[12+iIndex] = pAPDULEN[0];//CS校验和
  77.  free(pAPDULEN);
  78.  //结束标识
  79.  byteAPDU[13+iIndex] =0x16;
  80.  //发送
  81.  if(m_pMListenSocket->CheckpClientSocket(m_pMListenSocket->m_pClientSocket))
  82.  {
  83.   //SetSendBufData(byteAPDU,sizeof(byteAPDU));
  84.     m_pMListenSocket->m_pClientSocket->SendTo(byteAPDU,sizeof(byteAPDU),atoi(strPort),strIP);
  85.   Sleep(100);
  86.  }
  87. }


阅读(9614) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~