PrtModbus.cpp
上传用户:asikq0571
上传日期:2014-07-12
资源大小:528k
文件大小:15k
源码类别:

Internet/IE编程

开发平台:

Visual C++

  1. // PrtModbus.cpp: implementation of the CPrtModbus class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Peugeot.h"
  6. #include "PrtModbus.h"
  7. #include "MainFrm.h"
  8. #include "PeugeotDoc.h"
  9. #include "PeugeotView.h"
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[]=__FILE__;
  13. #define new DEBUG_NEW
  14. #endif
  15. //////////////////////////////////////////////////////////////////////
  16. // Construction/Destruction
  17. //////////////////////////////////////////////////////////////////////
  18. CPrtModbus::CPrtModbus()
  19. {
  20. //初始化成员变量
  21.  m_Addr     = 1;
  22.  m_YXFunc   = 2;
  23.  m_YCFunc   = 3;
  24.  m_YCSize   = 2;
  25.  m_CallIntv = 1000;
  26.  m_CallTimerID  = 0;
  27.      m_CallYXFlag   = true;
  28.      m_bIsTimerStar = false;
  29.  
  30.  int i;
  31.  for (i=0;i<8;i++)
  32.  {
  33.    m_CallYXByte[i]    = 0x00;    //召遥信报文
  34.        m_CallYCByte[i]    = 0x00;    //召遥测报文
  35.        m_SRecByte[i]  = 0x00;    
  36.  }
  37.  for (i=0;i<260;i++)
  38.  {
  39.    m_MRecByte[i]  = 0x00;    
  40.        m_SSendByte[i] = 0x00;    
  41.  }
  42.      m_MReadState = AddrCode;
  43.  m_SReadState = AddrByte;
  44.  m_MInfoIndex = 0;
  45. }
  46. CPrtModbus::~CPrtModbus()
  47. {
  48. }
  49.  //启动主站召唤时钟
  50. void CPrtModbus::StartTimer()
  51. {
  52.   CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;        //框架窗口指针;
  53.   CPeugeotView* pView    = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
  54.   ASSERT_VALID(pView);
  55.   m_CallTimerID  = pView->SetTimer(1,m_CallIntv,NULL);
  56.   m_bIsTimerStar = true;
  57. }
  58.  //关闭主站召唤时钟
  59. void CPrtModbus::CloseTimer()
  60. {
  61.   CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;        //框架窗口指针;
  62.   CPeugeotView* pView    = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
  63.   ASSERT_VALID(pView);
  64.   if (m_bIsTimerStar)
  65.   {
  66.      pView->KillTimer(m_CallTimerID);
  67.      m_bIsTimerStar = false;
  68.   }
  69. }
  70. //主站召唤子站数据
  71. void CPrtModbus::MasterSend(UINT nIDEvent)
  72. {
  73.   CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;        //框架窗口指针;
  74.   CPeugeotView* pView    = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
  75.   ASSERT_VALID(pView);
  76.   DWORD dwBytesSended = 0;
  77.   CString s1 = "" ;  //显示的字符串
  78.   if (m_CallYXFlag)
  79.   {   //发送主站召遥信报文,并显示
  80.      if ( pView->Send(m_CallYXByte,8,dwBytesSended) )  //召遥信
  81.  {
  82.         s1 = "<Send>:Modbus主站召遥信";
  83. s1 = s1 + "rn" + ByteArrayToString(m_CallYXByte,8) + "rn";
  84.         pView->DisplayMsg(s1);     //显示召唤报文
  85.  }
  86.   }
  87.   else
  88.   {  //发送主站召遥测报文,并显示
  89.      if ( pView->Send(m_CallYCByte,8,dwBytesSended) )  //召遥测
  90.  {
  91.         s1 = "<Send>:Modbus主站召遥测";
  92.     s1 = s1 + "rn" + ByteArrayToString(m_CallYCByte,8) + "rn";
  93.         pView->DisplayMsg(s1);     //显示召唤报文
  94.  }
  95.   } 
  96.   
  97.   m_CallYXFlag = !m_CallYXFlag;
  98. }
  99. void CPrtModbus::InitPrt()
  100. {
  101.    MPackYX();     //打包召遥信报文
  102.    MPackYC();     //打包召遥测报文
  103. }
  104. //打包召唤遥信报文
  105. void CPrtModbus::MPackYX()
  106. {
  107.    CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  108.    CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  109.    ASSERT_VALID(pDoc);
  110.    m_CallYXByte[0] = m_Addr;
  111.    m_CallYXByte[1] = m_YXFunc;
  112.    WORD temVar = 0x0000;
  113.    temVar = (WORD)pDoc->m_YXAddr;      //遥信首地址
  114.    m_CallYXByte[2] = HIBYTE(temVar);
  115.    m_CallYXByte[3] = LOBYTE(temVar);
  116.    temVar = (WORD)pDoc->m_YXNum;       //遥信个数
  117.    m_CallYXByte[4] = HIBYTE(temVar);
  118.    m_CallYXByte[5] = LOBYTE(temVar);
  119.    //CRC校验
  120.    WORD CRCWord = GetCRC16Byte(m_CallYXByte,6); //获取CRC校验码
  121.    BYTE CRCHi = HIBYTE(CRCWord);
  122.    BYTE CRCLo = LOBYTE(CRCWord);
  123.    m_CallYXByte[6] = CRCHi;     //CRC校验高字节
  124.    m_CallYXByte[7] = CRCLo;     //CRC校验低字节
  125. }
  126. //打包召唤遥测报文
  127. void CPrtModbus::MPackYC()
  128. {
  129.   CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  130.   CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  131.   ASSERT_VALID(pDoc);
  132.    m_CallYCByte[0] = m_Addr;
  133.    m_CallYCByte[1] = m_YCFunc;
  134.    WORD temVar = 0x0000;
  135.    temVar = (WORD)pDoc->m_YCAddr;      //遥测首地址
  136.    m_CallYCByte[2] = HIBYTE(temVar);
  137.    m_CallYCByte[3] = LOBYTE(temVar);
  138.    temVar = (WORD)pDoc->m_YCNum;       //遥测个数
  139.    m_CallYCByte[4] = HIBYTE(temVar);
  140.    m_CallYCByte[5] = LOBYTE(temVar);
  141. //CRC校验
  142.    WORD CRCWord = GetCRC16Byte(m_CallYCByte,6); //获取CRC校验码
  143.    BYTE CRCHi = HIBYTE(CRCWord);
  144.    BYTE CRCLo = LOBYTE(CRCWord);
  145.    m_CallYCByte[6] = CRCHi;     //CRC校验高字节
  146.    m_CallYCByte[7] = CRCLo;     //CRC校验低字节
  147. }
  148. //主站接收子站应答报文
  149. void CPrtModbus::MasterRec(BYTE recByte)
  150. {
  151.    switch (m_MReadState)
  152.    {
  153.    case AddrCode:       //地址码
  154.    if (recByte == m_Addr)
  155.    {
  156.    m_MRecByte[0] = recByte;
  157.            m_MReadState  = FuncCode;
  158.    }
  159.    break;
  160.    case FuncCode:       //功能码
  161.        if ( (recByte == m_YXFunc) || (recByte == m_YCFunc) )
  162.    {
  163.    m_MRecByte[1] = recByte;
  164.            m_MReadState  = NumCode;
  165.    }
  166.    else
  167.            m_MReadState  = AddrCode;    //丢弃,重新从地址码读取
  168.    break;
  169.    case NumCode:        //信息体字节数
  170.            m_MRecByte[2] = recByte;
  171.            m_MInfoIndex  = 0;
  172.            m_MReadState  = InfoCode;
  173.    break;
  174.    case InfoCode:       //信息体
  175.        m_MRecByte[3+m_MInfoIndex] = recByte;
  176.    if (m_MInfoIndex < (m_MRecByte[2]-1))   // 如读取的字节数小于信息字节数,则继续读取
  177.    m_MInfoIndex++;
  178.    else
  179.    { 
  180.    m_MReadState = CRCHiCode;
  181.    m_MInfoIndex = 0;
  182.    }
  183.    break;
  184.    case CRCHiCode:
  185.        m_MRecByte[3+m_MRecByte[2]] = recByte;
  186.        m_MReadState = CRCLoCode;
  187.    break;
  188.    case CRCLoCode:
  189.        m_MRecByte[4+m_MRecByte[2]] = recByte;
  190.        m_MReadState  = AddrCode;    //本帧读取结束,下帧从地址码读取
  191.    //读进报文CRC校验
  192.         WORD CRCWord;
  193.         BYTE CRCHi, CRCLo;
  194. CRCWord = GetCRC16Byte(m_MRecByte,(3+m_MRecByte[2]));
  195.     CRCHi   = HIBYTE(CRCWord);
  196.     CRCLo   = LOBYTE(CRCWord);
  197. //////////////////
  198.    if ((m_MRecByte[3+m_MRecByte[2]] == CRCHi) && (m_MRecByte[4+m_MRecByte[2]] == CRCLo))
  199.     MasterUnPack();        //CRC校验正确,解信息报文
  200.    break;
  201.    default:
  202.        m_MReadState  = AddrCode;    //重新从地址码读取
  203.    break;
  204.    }
  205. }
  206. // 信息报文解包,并显示报文
  207. void CPrtModbus::MasterUnPack()
  208. {
  209.    CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
  210.    CPeugeotView* pView    = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
  211.    ASSERT_VALID(pView);
  212.    CString s1 = "" ;  //显示的字符串
  213.    if (m_MRecByte[1] == m_YXFunc)
  214. { //遥信数据包
  215.    MUnPackYX();
  216.        s1 = "<Rec>:Modbus子站遥信";
  217. }
  218.     else
  219.     {
  220.        MUnPackYC();
  221.        s1 = "<Rec>:Modbus子站遥测";
  222.     }
  223.      int recnum = 5+m_MRecByte[2];
  224.      s1 = s1 + "rn" + ByteArrayToString(m_MRecByte,recnum) + "rn";
  225.  pView->DisplayMsg(s1);     //显示召唤报文
  226. }
  227. void CPrtModbus::MUnPackYX()
  228. {
  229.     CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  230.     CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  231.     ASSERT_VALID(pDoc);
  232.    
  233. int iyxnum = m_MRecByte[2]*8;
  234. BYTE* pyx   = new BYTE[iyxnum];       //临时存放解包的数据
  235.     int  i;
  236. BYTE tembyte;    //临时变量
  237. for (i=0; i<m_MRecByte[2]; i++)       //按字节解包
  238. {
  239.       tembyte = m_MRecByte[3+i];    
  240. for (int j=0;j<8;j++)             //每个字节取8个遥信量
  241. { //取最低位,提取遥信
  242.   pyx[8*i+j] = 0x01 & tembyte;
  243.           tembyte   = tembyte >> 1;
  244. }
  245. }
  246. if (pDoc->m_pYXData != NULL)
  247. {
  248.        iyxnum > pDoc->m_YXNum ? (iyxnum = pDoc->m_YXNum) : 1;
  249.    for (i=0; i<iyxnum; i++)
  250.    pDoc->m_pYXData[i] = pyx[i];
  251.        pMainFrame->UpdateYXGrid(); //更新电子表格数据
  252. }
  253.       
  254. delete[] pyx;
  255. }
  256. void CPrtModbus::MUnPackYC()
  257. {
  258.     CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  259.     CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  260.     ASSERT_VALID(pDoc);
  261. int iycnum = m_MRecByte[2]>>1;        //需要解包的遥测数量,如有剩余单个字节,不处理该字节
  262. iycnum > pDoc->m_YCNum ? (iycnum = pDoc->m_YCNum) : 1;
  263. if (pDoc->m_pYCData != NULL)
  264. {
  265. for (int i=0; i<iycnum; i++)          //给MODBUS遥测库更新
  266.     pDoc->m_pYCData[i] = m_MRecByte[3+2*i]*256 + m_MRecByte[3+2*i+1];
  267. pMainFrame->UpdateYCGrid();           //更新电子表格数据  HIBYTE
  268. }
  269. }
  270. // 从站接收召唤数据
  271. void CPrtModbus::SlaveRec(BYTE recByte)
  272. {
  273.   CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;        //框架窗口指针;
  274.   CPeugeotView* pView    = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
  275.   ASSERT_VALID(pView);
  276. switch (m_SReadState)
  277. {
  278. case AddrByte:                       //地址码
  279.         if (recByte == m_Addr)             
  280. {
  281.    m_SRecByte[0] = recByte;
  282.            m_SReadState  = FuncByte;
  283. }
  284. break;
  285. case FuncByte:                       //功能码
  286.         if ( (recByte == m_YXFunc) || (recByte == m_YCFunc) )
  287. {
  288.    m_SRecByte[1] = recByte;
  289.            m_SReadState  = AddrHiByte;
  290. }
  291.     else
  292.            m_SReadState  = AddrByte;     //丢弃,重新从地址码读取
  293. break;
  294. case AddrHiByte:
  295.         m_SRecByte[2] = recByte;
  296.         m_SReadState  = AddrLoByte;
  297. break;
  298. case AddrLoByte:
  299.         m_SRecByte[3] = recByte;
  300.         m_SReadState  = NumHiByte;
  301. break;
  302.     case NumHiByte:
  303.         m_SRecByte[4] = recByte;
  304.         m_SReadState  = NumLoByte;
  305. break;
  306.     case NumLoByte:
  307.         m_SRecByte[5] = recByte;
  308.         m_SReadState  = CRCHiByte;
  309. break;
  310.     case CRCHiByte:
  311.         m_SRecByte[6] = recByte;
  312.         m_SReadState  = CRCLoByte;
  313. break;
  314.     case CRCLoByte:
  315.         m_SRecByte[7] = recByte;
  316.         m_SReadState  = AddrByte;      //本帧读取结束,下帧从地址码读取   
  317.         //读进报文CRC校验
  318.         WORD CRCWord;
  319.         BYTE CRCHi, CRCLo;
  320. CRCWord = GetCRC16Byte(m_SRecByte,6);
  321.     CRCHi   = HIBYTE(CRCWord);
  322.     CRCLo   = LOBYTE(CRCWord);
  323. //////////////////
  324.    if ((m_SRecByte[6] == CRCHi) && (m_SRecByte[7] == CRCLo))
  325.    {  
  326.   CString s1;
  327.   if (m_SRecByte[1] == m_YXFunc)
  328.   s1 = "<Rec>:Modbus主站召遥信";
  329.   else
  330.               s1 = "<Rec>:Modbus主站召遥测";
  331.   s1 = s1 + "rn" + ByteArrayToString(m_SRecByte,8) + "rn";
  332.           pView->DisplayMsg(s1);     //显示召唤报文
  333.   SlaveSend();
  334.    }
  335. break;
  336.     default:
  337.         m_SReadState  = AddrByte;      //重新从地址码读取
  338.     break;
  339. }
  340. }
  341. //从站应答召唤
  342. void CPrtModbus::SlaveSend()
  343. {
  344.   CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  345.   CPeugeotView* pView    = (CPeugeotView*) pMainFrame->GetActiveView();    //视图指针
  346.   ASSERT_VALID(pView);
  347.  // CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  348.  //ASSERT_VALID(pDoc);
  349.   int sendnum = 0;        //发送字节数
  350.   CString s1  = "";       //显示信息
  351.   DWORD dwBytesSended = 0;
  352.   if (m_SRecByte[1] == m_YXFunc)
  353.   {
  354.  SPackYX();
  355.  s1 = "<Send>:Modbus子站遥信";
  356.   }
  357.   else
  358.   {
  359.      SPackYC();
  360.      s1 = "<Send>:Modbus子站遥测";
  361.   }
  362.   
  363.    //CRC校验
  364.     WORD CRCWord = GetCRC16Byte(m_SSendByte,(m_SSendByte[2]+3)); //获取CRC校验码
  365.     BYTE CRCHi = HIBYTE(CRCWord);
  366.     BYTE CRCLo = LOBYTE(CRCWord);
  367.     m_SSendByte[m_SSendByte[2]+3] = CRCHi;     //CRC校验高字节
  368. m_SSendByte[m_SSendByte[2]+4] = CRCLo;     //CRC校验低字节
  369.   sendnum = m_SSendByte[2] + 5;
  370.   if (pView->Send(m_SSendByte,sendnum,dwBytesSended))  //发送应答报文并显示
  371.   {
  372.    s1 = s1 + "rn" + ByteArrayToString(m_SSendByte,sendnum) + "rn";
  373.    pView->DisplayMsg(s1);
  374.   }
  375. }
  376. //从从站打遥信包
  377. void CPrtModbus::SPackYX()
  378. {
  379.    CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  380.    CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  381.    ASSERT_VALID(pDoc);
  382.    m_SSendByte[0] = m_Addr;
  383.    m_SSendByte[1] = m_YXFunc;
  384.    
  385.    WORD yxaddr = (m_SRecByte[2]<<8) | (m_SRecByte[3]);    //遥信首地址
  386.    WORD yxnum  = (m_SRecByte[4]<<8) | (m_SRecByte[5]);    //遥信信息字节数
  387.    yxnum > 0x07F8 ? (yxnum = 0x07F8):1;                   //遥信个数不能超过 255 ×8 
  388.    if ((yxnum & 0x0007) > 0)                              //遥信信息字节数,如余1~7个遥信,则补一个字节
  389.       m_SSendByte[2] = LOBYTE(yxnum>>3)+1;  
  390.    else
  391.       m_SSendByte[2] = LOBYTE(yxnum>>3);  
  392.    
  393.  //读出遥信库中的值,放入字节数组,不足八个的补零
  394.  if (pDoc->m_pYXData != NULL)
  395.  {
  396.    BYTE* pb = NULL;
  397.    
  398.    yxnum = (WORD) pDoc->m_YXNum; 
  399.    if ((yxnum & 0x0007) > 0)         //实时库遥信个数,如余1~7个遥信,则补齐8个(1字节)
  400.        yxnum = (yxnum | 0x0007) + 1;  
  401.   
  402.    pb = new BYTE[yxnum];
  403.    int i = 0; int j = 0; int k = 0;
  404.    
  405.    while(i<yxnum)
  406.    {
  407.  if (i<pDoc->m_YXNum)
  408.    pb[i] = pDoc->m_pYXData[i];
  409.  else
  410.    pb[i] = 0x00;
  411.  i++;
  412.    }
  413.  //////////////////////////////////
  414.    yxnum = yxnum>>3;   
  415.    for (i=0;i<m_SSendByte[2];i++)         //共发送m_SSendByte[2]个遥信信息字节
  416.    {
  417.   m_SSendByte[i+3] = 0x00;            //初始化第(i+3)个字节
  418.   if ( (yxaddr+i)>=(pDoc->m_YXAddr) && (yxaddr+i)<(pDoc->m_YXAddr+yxnum) )
  419.   { //如果在遥信库范围内,则发送信息取值实时遥信库
  420.       k = (yxaddr + i) - pDoc->m_YXAddr;
  421.   for (j=8; j>0; j--)
  422.   {
  423.        m_SSendByte[i+3] = m_SSendByte[i+3]<<1;    //先左移1位,腾出低位填入第j个遥信状态
  424.            m_SSendByte[i+3] = m_SSendByte[i+3] | pb[k*8+j-1];
  425.   }
  426.   }
  427.    }
  428.  delete[] pb;
  429.  }
  430. }
  431. //从从站打遥测包
  432. void CPrtModbus::SPackYC()
  433. {
  434.    CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;           //框架窗口指针;
  435.    CPeugeotDoc* pDoc      = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
  436.    ASSERT_VALID(pDoc);
  437.    m_SSendByte[0] = m_Addr;
  438.    m_SSendByte[1] = m_YCFunc;
  439.    WORD ycaddr = (m_SRecByte[2]<<8) | (m_SRecByte[3]);    //主站召唤的遥测首地址
  440.    if (m_SRecByte[5] > 0x7F)
  441.        m_SSendByte[2] = 0XFE;              //2个字节组一个遥测时,最多为254个字节
  442.    else
  443.        m_SSendByte[2] = m_SRecByte[5]<<1;  //发送的字节数,一个遥测量两个字节,所以,遥测数×2
  444.    if (pDoc->m_pYCData != NULL)
  445.    {
  446.   int i = 0; int j = 0;
  447.       for (i=0; i<(m_SSendByte[2]>>1); i++)
  448.   {
  449.          if ((ycaddr+i)>=(pDoc->m_YCAddr) && (ycaddr+i)<(pDoc->m_YCAddr+pDoc->m_YCNum))
  450.  {  //如果在遥测库范围内,则发送信息取值实时遥测库
  451.     j = (ycaddr + i) - pDoc->m_YCAddr;
  452.             m_SSendByte[2*i+3] = HIBYTE(pDoc->m_pYCData[j]); //第i个遥测高字节
  453.             m_SSendByte[2*i+4] = LOBYTE(pDoc->m_pYCData[j]); //第i个遥测高字节
  454.  }
  455.  else
  456.  {
  457.             m_SSendByte[2*i+3] = 0x00; //第i个遥测高字节
  458.             m_SSendByte[2*i+4] = 0x00; //第i个遥测高字节
  459.  } 
  460.   }
  461.    } 
  462. }