PrtModbus.cpp
上传用户:asikq0571
上传日期:2014-07-12
资源大小:528k
文件大小:15k
- // PrtModbus.cpp: implementation of the CPrtModbus class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Peugeot.h"
- #include "PrtModbus.h"
- #include "MainFrm.h"
- #include "PeugeotDoc.h"
- #include "PeugeotView.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CPrtModbus::CPrtModbus()
- {
- //初始化成员变量
- m_Addr = 1;
- m_YXFunc = 2;
- m_YCFunc = 3;
- m_YCSize = 2;
- m_CallIntv = 1000;
- m_CallTimerID = 0;
- m_CallYXFlag = true;
- m_bIsTimerStar = false;
-
- int i;
- for (i=0;i<8;i++)
- {
- m_CallYXByte[i] = 0x00; //召遥信报文
- m_CallYCByte[i] = 0x00; //召遥测报文
- m_SRecByte[i] = 0x00;
- }
- for (i=0;i<260;i++)
- {
- m_MRecByte[i] = 0x00;
- m_SSendByte[i] = 0x00;
- }
- m_MReadState = AddrCode;
- m_SReadState = AddrByte;
- m_MInfoIndex = 0;
- }
- CPrtModbus::~CPrtModbus()
- {
- }
- //启动主站召唤时钟
- void CPrtModbus::StartTimer()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotView* pView = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
- ASSERT_VALID(pView);
- m_CallTimerID = pView->SetTimer(1,m_CallIntv,NULL);
- m_bIsTimerStar = true;
- }
- //关闭主站召唤时钟
- void CPrtModbus::CloseTimer()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotView* pView = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
- ASSERT_VALID(pView);
- if (m_bIsTimerStar)
- {
- pView->KillTimer(m_CallTimerID);
- m_bIsTimerStar = false;
- }
- }
- //主站召唤子站数据
- void CPrtModbus::MasterSend(UINT nIDEvent)
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotView* pView = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
- ASSERT_VALID(pView);
-
- DWORD dwBytesSended = 0;
- CString s1 = "" ; //显示的字符串
- if (m_CallYXFlag)
- { //发送主站召遥信报文,并显示
- if ( pView->Send(m_CallYXByte,8,dwBytesSended) ) //召遥信
- {
- s1 = "<Send>:Modbus主站召遥信";
- s1 = s1 + "rn" + ByteArrayToString(m_CallYXByte,8) + "rn";
- pView->DisplayMsg(s1); //显示召唤报文
- }
- }
- else
- { //发送主站召遥测报文,并显示
- if ( pView->Send(m_CallYCByte,8,dwBytesSended) ) //召遥测
- {
- s1 = "<Send>:Modbus主站召遥测";
- s1 = s1 + "rn" + ByteArrayToString(m_CallYCByte,8) + "rn";
- pView->DisplayMsg(s1); //显示召唤报文
- }
- }
-
- m_CallYXFlag = !m_CallYXFlag;
- }
- void CPrtModbus::InitPrt()
- {
- MPackYX(); //打包召遥信报文
- MPackYC(); //打包召遥测报文
- }
- //打包召唤遥信报文
- void CPrtModbus::MPackYX()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- ASSERT_VALID(pDoc);
- m_CallYXByte[0] = m_Addr;
- m_CallYXByte[1] = m_YXFunc;
- WORD temVar = 0x0000;
- temVar = (WORD)pDoc->m_YXAddr; //遥信首地址
- m_CallYXByte[2] = HIBYTE(temVar);
- m_CallYXByte[3] = LOBYTE(temVar);
- temVar = (WORD)pDoc->m_YXNum; //遥信个数
- m_CallYXByte[4] = HIBYTE(temVar);
- m_CallYXByte[5] = LOBYTE(temVar);
- //CRC校验
- WORD CRCWord = GetCRC16Byte(m_CallYXByte,6); //获取CRC校验码
- BYTE CRCHi = HIBYTE(CRCWord);
- BYTE CRCLo = LOBYTE(CRCWord);
- m_CallYXByte[6] = CRCHi; //CRC校验高字节
- m_CallYXByte[7] = CRCLo; //CRC校验低字节
- }
- //打包召唤遥测报文
- void CPrtModbus::MPackYC()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- ASSERT_VALID(pDoc);
- m_CallYCByte[0] = m_Addr;
- m_CallYCByte[1] = m_YCFunc;
- WORD temVar = 0x0000;
- temVar = (WORD)pDoc->m_YCAddr; //遥测首地址
- m_CallYCByte[2] = HIBYTE(temVar);
- m_CallYCByte[3] = LOBYTE(temVar);
- temVar = (WORD)pDoc->m_YCNum; //遥测个数
- m_CallYCByte[4] = HIBYTE(temVar);
- m_CallYCByte[5] = LOBYTE(temVar);
- //CRC校验
- WORD CRCWord = GetCRC16Byte(m_CallYCByte,6); //获取CRC校验码
- BYTE CRCHi = HIBYTE(CRCWord);
- BYTE CRCLo = LOBYTE(CRCWord);
- m_CallYCByte[6] = CRCHi; //CRC校验高字节
- m_CallYCByte[7] = CRCLo; //CRC校验低字节
- }
- //主站接收子站应答报文
- void CPrtModbus::MasterRec(BYTE recByte)
- {
- switch (m_MReadState)
- {
- case AddrCode: //地址码
- if (recByte == m_Addr)
- {
- m_MRecByte[0] = recByte;
- m_MReadState = FuncCode;
- }
- break;
- case FuncCode: //功能码
- if ( (recByte == m_YXFunc) || (recByte == m_YCFunc) )
- {
- m_MRecByte[1] = recByte;
- m_MReadState = NumCode;
- }
- else
- m_MReadState = AddrCode; //丢弃,重新从地址码读取
- break;
- case NumCode: //信息体字节数
- m_MRecByte[2] = recByte;
- m_MInfoIndex = 0;
- m_MReadState = InfoCode;
- break;
- case InfoCode: //信息体
- m_MRecByte[3+m_MInfoIndex] = recByte;
- if (m_MInfoIndex < (m_MRecByte[2]-1)) // 如读取的字节数小于信息字节数,则继续读取
- m_MInfoIndex++;
- else
- {
- m_MReadState = CRCHiCode;
- m_MInfoIndex = 0;
- }
- break;
- case CRCHiCode:
- m_MRecByte[3+m_MRecByte[2]] = recByte;
- m_MReadState = CRCLoCode;
- break;
- case CRCLoCode:
- m_MRecByte[4+m_MRecByte[2]] = recByte;
- m_MReadState = AddrCode; //本帧读取结束,下帧从地址码读取
- //读进报文CRC校验
- WORD CRCWord;
- BYTE CRCHi, CRCLo;
- CRCWord = GetCRC16Byte(m_MRecByte,(3+m_MRecByte[2]));
- CRCHi = HIBYTE(CRCWord);
- CRCLo = LOBYTE(CRCWord);
- //////////////////
- if ((m_MRecByte[3+m_MRecByte[2]] == CRCHi) && (m_MRecByte[4+m_MRecByte[2]] == CRCLo))
- MasterUnPack(); //CRC校验正确,解信息报文
- break;
- default:
- m_MReadState = AddrCode; //重新从地址码读取
- break;
- }
- }
- // 信息报文解包,并显示报文
- void CPrtModbus::MasterUnPack()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotView* pView = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
- ASSERT_VALID(pView);
- CString s1 = "" ; //显示的字符串
-
- if (m_MRecByte[1] == m_YXFunc)
- { //遥信数据包
- MUnPackYX();
- s1 = "<Rec>:Modbus子站遥信";
- }
- else
- {
- MUnPackYC();
- s1 = "<Rec>:Modbus子站遥测";
- }
- int recnum = 5+m_MRecByte[2];
- s1 = s1 + "rn" + ByteArrayToString(m_MRecByte,recnum) + "rn";
- pView->DisplayMsg(s1); //显示召唤报文
- }
- void CPrtModbus::MUnPackYX()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- ASSERT_VALID(pDoc);
-
- int iyxnum = m_MRecByte[2]*8;
- BYTE* pyx = new BYTE[iyxnum]; //临时存放解包的数据
-
- int i;
- BYTE tembyte; //临时变量
- for (i=0; i<m_MRecByte[2]; i++) //按字节解包
- {
- tembyte = m_MRecByte[3+i];
- for (int j=0;j<8;j++) //每个字节取8个遥信量
- { //取最低位,提取遥信
- pyx[8*i+j] = 0x01 & tembyte;
- tembyte = tembyte >> 1;
- }
- }
- if (pDoc->m_pYXData != NULL)
- {
- iyxnum > pDoc->m_YXNum ? (iyxnum = pDoc->m_YXNum) : 1;
- for (i=0; i<iyxnum; i++)
- pDoc->m_pYXData[i] = pyx[i];
- pMainFrame->UpdateYXGrid(); //更新电子表格数据
- }
-
- delete[] pyx;
- }
- void CPrtModbus::MUnPackYC()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- ASSERT_VALID(pDoc);
- int iycnum = m_MRecByte[2]>>1; //需要解包的遥测数量,如有剩余单个字节,不处理该字节
- iycnum > pDoc->m_YCNum ? (iycnum = pDoc->m_YCNum) : 1;
- if (pDoc->m_pYCData != NULL)
- {
- for (int i=0; i<iycnum; i++) //给MODBUS遥测库更新
- pDoc->m_pYCData[i] = m_MRecByte[3+2*i]*256 + m_MRecByte[3+2*i+1];
- pMainFrame->UpdateYCGrid(); //更新电子表格数据 HIBYTE
- }
- }
- // 从站接收召唤数据
- void CPrtModbus::SlaveRec(BYTE recByte)
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotView* pView = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
- ASSERT_VALID(pView);
- switch (m_SReadState)
- {
- case AddrByte: //地址码
- if (recByte == m_Addr)
- {
- m_SRecByte[0] = recByte;
- m_SReadState = FuncByte;
- }
- break;
- case FuncByte: //功能码
- if ( (recByte == m_YXFunc) || (recByte == m_YCFunc) )
- {
- m_SRecByte[1] = recByte;
- m_SReadState = AddrHiByte;
- }
- else
- m_SReadState = AddrByte; //丢弃,重新从地址码读取
- break;
- case AddrHiByte:
- m_SRecByte[2] = recByte;
- m_SReadState = AddrLoByte;
- break;
- case AddrLoByte:
- m_SRecByte[3] = recByte;
- m_SReadState = NumHiByte;
- break;
- case NumHiByte:
- m_SRecByte[4] = recByte;
- m_SReadState = NumLoByte;
- break;
- case NumLoByte:
- m_SRecByte[5] = recByte;
- m_SReadState = CRCHiByte;
- break;
- case CRCHiByte:
- m_SRecByte[6] = recByte;
- m_SReadState = CRCLoByte;
- break;
- case CRCLoByte:
- m_SRecByte[7] = recByte;
- m_SReadState = AddrByte; //本帧读取结束,下帧从地址码读取
- //读进报文CRC校验
- WORD CRCWord;
- BYTE CRCHi, CRCLo;
- CRCWord = GetCRC16Byte(m_SRecByte,6);
- CRCHi = HIBYTE(CRCWord);
- CRCLo = LOBYTE(CRCWord);
- //////////////////
- if ((m_SRecByte[6] == CRCHi) && (m_SRecByte[7] == CRCLo))
- {
- CString s1;
- if (m_SRecByte[1] == m_YXFunc)
- s1 = "<Rec>:Modbus主站召遥信";
- else
- s1 = "<Rec>:Modbus主站召遥测";
- s1 = s1 + "rn" + ByteArrayToString(m_SRecByte,8) + "rn";
- pView->DisplayMsg(s1); //显示召唤报文
- SlaveSend();
- }
- break;
- default:
- m_SReadState = AddrByte; //重新从地址码读取
- break;
- }
- }
- //从站应答召唤
- void CPrtModbus::SlaveSend()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotView* pView = (CPeugeotView*) pMainFrame->GetActiveView(); //视图指针
- ASSERT_VALID(pView);
- // CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- //ASSERT_VALID(pDoc);
- int sendnum = 0; //发送字节数
- CString s1 = ""; //显示信息
- DWORD dwBytesSended = 0;
-
- if (m_SRecByte[1] == m_YXFunc)
- {
- SPackYX();
- s1 = "<Send>:Modbus子站遥信";
- }
- else
- {
- SPackYC();
- s1 = "<Send>:Modbus子站遥测";
- }
-
- //CRC校验
- WORD CRCWord = GetCRC16Byte(m_SSendByte,(m_SSendByte[2]+3)); //获取CRC校验码
- BYTE CRCHi = HIBYTE(CRCWord);
- BYTE CRCLo = LOBYTE(CRCWord);
- m_SSendByte[m_SSendByte[2]+3] = CRCHi; //CRC校验高字节
- m_SSendByte[m_SSendByte[2]+4] = CRCLo; //CRC校验低字节
- sendnum = m_SSendByte[2] + 5;
- if (pView->Send(m_SSendByte,sendnum,dwBytesSended)) //发送应答报文并显示
- {
- s1 = s1 + "rn" + ByteArrayToString(m_SSendByte,sendnum) + "rn";
- pView->DisplayMsg(s1);
- }
- }
- //从从站打遥信包
- void CPrtModbus::SPackYX()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- ASSERT_VALID(pDoc);
- m_SSendByte[0] = m_Addr;
- m_SSendByte[1] = m_YXFunc;
-
- WORD yxaddr = (m_SRecByte[2]<<8) | (m_SRecByte[3]); //遥信首地址
- WORD yxnum = (m_SRecByte[4]<<8) | (m_SRecByte[5]); //遥信信息字节数
- yxnum > 0x07F8 ? (yxnum = 0x07F8):1; //遥信个数不能超过 255 ×8
- if ((yxnum & 0x0007) > 0) //遥信信息字节数,如余1~7个遥信,则补一个字节
- m_SSendByte[2] = LOBYTE(yxnum>>3)+1;
- else
- m_SSendByte[2] = LOBYTE(yxnum>>3);
-
- //读出遥信库中的值,放入字节数组,不足八个的补零
- if (pDoc->m_pYXData != NULL)
- {
- BYTE* pb = NULL;
-
- yxnum = (WORD) pDoc->m_YXNum;
- if ((yxnum & 0x0007) > 0) //实时库遥信个数,如余1~7个遥信,则补齐8个(1字节)
- yxnum = (yxnum | 0x0007) + 1;
-
- pb = new BYTE[yxnum];
- int i = 0; int j = 0; int k = 0;
-
- while(i<yxnum)
- {
- if (i<pDoc->m_YXNum)
- pb[i] = pDoc->m_pYXData[i];
- else
- pb[i] = 0x00;
- i++;
- }
- //////////////////////////////////
- yxnum = yxnum>>3;
- for (i=0;i<m_SSendByte[2];i++) //共发送m_SSendByte[2]个遥信信息字节
- {
- m_SSendByte[i+3] = 0x00; //初始化第(i+3)个字节
- if ( (yxaddr+i)>=(pDoc->m_YXAddr) && (yxaddr+i)<(pDoc->m_YXAddr+yxnum) )
- { //如果在遥信库范围内,则发送信息取值实时遥信库
- k = (yxaddr + i) - pDoc->m_YXAddr;
- for (j=8; j>0; j--)
- {
- m_SSendByte[i+3] = m_SSendByte[i+3]<<1; //先左移1位,腾出低位填入第j个遥信状态
- m_SSendByte[i+3] = m_SSendByte[i+3] | pb[k*8+j-1];
- }
- }
- }
- delete[] pb;
- }
- }
- //从从站打遥测包
- void CPrtModbus::SPackYC()
- {
- CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; //框架窗口指针;
- CPeugeotDoc* pDoc = (CPeugeotDoc*) pMainFrame->GetActiveDocument(); //文档指针
- ASSERT_VALID(pDoc);
- m_SSendByte[0] = m_Addr;
- m_SSendByte[1] = m_YCFunc;
- WORD ycaddr = (m_SRecByte[2]<<8) | (m_SRecByte[3]); //主站召唤的遥测首地址
- if (m_SRecByte[5] > 0x7F)
- m_SSendByte[2] = 0XFE; //2个字节组一个遥测时,最多为254个字节
- else
- m_SSendByte[2] = m_SRecByte[5]<<1; //发送的字节数,一个遥测量两个字节,所以,遥测数×2
- if (pDoc->m_pYCData != NULL)
- {
- int i = 0; int j = 0;
- for (i=0; i<(m_SSendByte[2]>>1); i++)
- {
- if ((ycaddr+i)>=(pDoc->m_YCAddr) && (ycaddr+i)<(pDoc->m_YCAddr+pDoc->m_YCNum))
- { //如果在遥测库范围内,则发送信息取值实时遥测库
- j = (ycaddr + i) - pDoc->m_YCAddr;
- m_SSendByte[2*i+3] = HIBYTE(pDoc->m_pYCData[j]); //第i个遥测高字节
- m_SSendByte[2*i+4] = LOBYTE(pDoc->m_pYCData[j]); //第i个遥测高字节
- }
- else
- {
- m_SSendByte[2*i+3] = 0x00; //第i个遥测高字节
- m_SSendByte[2*i+4] = 0x00; //第i个遥测高字节
- }
- }
- }
- }