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

📄 localmodbus.cpp

📁 一个modbus协议的opc server
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    m_abyBuffer[0]=':';
    m_abyBuffer[wLengthQuery*2+1]=Num2Ascii(HI4BITS(byLRC));
    m_abyBuffer[wLengthQuery*2+2]=Num2Ascii(LO4BITS(byLRC));
    m_abyBuffer[wLengthQuery*2+3]=C_R;
    m_abyBuffer[wLengthQuery*2+4]=L_F;
    
    if(!ClearBuffers()){
        TRACE("ClearBuffers Error");
    };
    
    //write query 
    if (!WriteQuery(m_abyBuffer,wLengthQuery*2+5,dwNumberOfBytesWritten)){
        TRACE("Write Query Error");
        wError=(ERR_WR_PORT);
        goto TxRxErrorAscii;
    } 
    
    m_abyBuffer.SetSize(RESP_BUFFER*2);
    ::ZeroMemory(m_abyBuffer.GetData(),m_abyBuffer.GetSize());
    
    
    if (!ReadResponseASCII(m_abyBuffer,dwNumberOfBytesRead)) //not using COMMTIMEOUTS
    {
        TRACE("ReadResponse Failed"); 
        wError=(ERR_RD_PORT);
        goto TxRxErrorAscii;
        
    }
    
    
    if (dwNumberOfBytesRead == 0){
        m_PerfCounter.End();
        wError=(ERR_TIMEOUT);
        goto TxRxErrorAscii;
    }
    
    
    if (!VerifyRespLRC(m_abyBuffer,dwNumberOfBytesRead)){
        
        wError=(ERR_CRC);
        goto TxRxErrorAscii;
        
    }
    
    if (HiLo4BitsToByte(Ascii2Num(m_abyBuffer[3]),Ascii2Num(m_abyBuffer[4]))>0x80) { 
        
        wError= (ERR_EXCPTION_CODE+HiLo4BitsToByte(Ascii2Num(m_abyBuffer[5]),Ascii2Num(m_abyBuffer[6]))
            );
        goto TxRxErrorAscii;
        
    }
    
    iDataSize = int((dwNumberOfBytesRead-5)/2);
    
    iDataSize= min(iDataSize,m_abyBuffer.GetSize());
    
    for (i=0;i<iDataSize;i++){
        abyResponse[i]=HiLo4BitsToByte(Ascii2Num(m_abyBuffer[1+i*2]),
									   Ascii2Num(m_abyBuffer[1+i*2+1]));
    }
    
    if (pwNumOfBytesRead!=NULL) {
        *pwNumOfBytesRead=WORD((dwNumberOfBytesRead-5)/2);
    }
    
    return(ERR_OK);
    
TxRxErrorAscii:
    
    if (Delay()>0) {
        ::Sleep(Delay());
    }
    
    return(wError);
}



//Transmit Raw Data to serial port 
WORD CLocalModbus::TxRxRawData(const BYTE* pDataWrite,
    WORD wLengthData,
    BYTE* pRespBuffer,
    WORD  wMaxBufferSize,
    WORD& wNumOfBytesRead,
    DWORD dwTimeOut
    )
{ 
    
    COMMTIMEOUTS cto;
    WORD wError;
    DWORD  dwTime_Out;
    
    
    Lock();
    
    wNumOfBytesRead=0;
    
    if (m_hComHandle==INVALID_HANDLE_VALUE){
        TRACE("Port Not opened\n"); 
        
        wError=(ERR_NOT_INT);
        goto TxRxErrorRawData;
    }
    
    if (dwTimeOut!=0) {
        
        if (!GetTimeouts(cto)){
            wError=(ERR_NOT_INT);
            goto TxRxErrorRawData;
            
        }
        dwTime_Out= dwTimeOut;
        SetTimeouts(NULL);
    }
    else {
        
        dwTime_Out=(DWORD)m_lTimeOut;
    }
    
    
    if(!ClearBuffers()){
        TRACE("ClearBuffers Error");
    }
    
    //Write Data 
    DWORD  dwNumberOfBytesWritten;
    DWORD  dwErrors;
    DWORD  dwStart;
    COMSTAT cstStatus;
    
    if( !::WriteFile(m_hComHandle,pDataWrite,wLengthData,&dwNumberOfBytesWritten,NULL) ) {
        if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
            //Verify Returned error 
            TRACE("Writefile Error %d\n",dwErrors);
        }
        else{
            TRACE("ClearCommError Failed writing\n");
        }
        wError=(ERR_WR_PORT);
        goto TxRxErrorRawData;
    }
    
    
    
    ::ClearCommError(m_hComHandle,&dwErrors,&cstStatus);
    
    dwStart = ::timeGetTime(); 
    
    while (((dwStart+dwTime_Out) >::timeGetTime())&&(cstStatus.cbOutQue>0)){
        ::ClearCommError(m_hComHandle,&dwErrors,&cstStatus);
    }
    
    
    //Read Data
    DWORD dwNumberOfBytesRead;
    DWORD dwRead;
    
    dwRead=0;
    dwStart = ::timeGetTime(); 
    
    do {
        if( !::ReadFile(m_hComHandle,(pRespBuffer+dwRead),1,&dwNumberOfBytesRead,NULL) ) { //read one charcter 
            if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
                TRACE("ReadFile Errors 0x=%xd",dwErrors);
            }
            else{
                TRACE(" ClearCommError Failed reading");
            }
            wError=(ERR_RD_PORT);
            goto TxRxErrorRawData;
        }
        dwRead+=dwNumberOfBytesRead;
    }
    while (((dwStart+dwTime_Out) >::timeGetTime())&&(dwRead<wMaxBufferSize));
    
    wNumOfBytesRead=(WORD)dwRead;
    
    //set timeout back to default values
    if (dwTimeOut!=0) {
        
        if (!SetTimeouts(&cto)){
            wError=(ERR_NOT_INT);
            goto TxRxErrorRawData;
            
        }
        
    }
    
    
    Unlock();
    return(ERR_OK);
    
TxRxErrorRawData:
    
    if (Delay()>0) {
        ::Sleep(Delay());
    }
    
    Unlock();
    return(wError);
}

// private functions 

//verify modbus response
//return true if ok 
//abyResp Modbus response 
//dwLength Length of response without CRC 
BOOL CLocalModbus::VerifyRespCRC(CByteArray& abyResp, WORD wLength){ 
    WORD wcrc; 
    wcrc=m_crc.CalcCrcFast(abyResp,wLength);
    return( (abyResp[wLength]==HIBYTE(wcrc)) && (abyResp[wLength+1]==LOBYTE(wcrc)) );
}

BOOL CLocalModbus::WriteQuery(CByteArray& abyQuery,DWORD dwQuerySize, DWORD& dwNumberOfBytesWritten) {
    
    DWORD  dwTimeOut;  
    DWORD  dwErrors;
    COMSTAT cstStatus;
    //Write Query 
    if( !::WriteFile(m_hComHandle,&abyQuery[0],dwQuerySize,&dwNumberOfBytesWritten,NULL) ) {
        if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
            //Verify Returned error 
            TRACE("Writefile Error %d",dwErrors);
        }
        else{
            TRACE("ClearCommError Failed writing");
        }
        return (FALSE);
    }
    
    
    
    //conut time after send message to device
    m_PerfCounter.Start();
    
    ::ClearCommError(m_hComHandle,&dwErrors,&cstStatus);
    
    dwTimeOut = ::timeGetTime() + m_lTimeOut;
    
    while ((dwTimeOut <::timeGetTime())&&(cstStatus.cbOutQue>0)){
        ::ClearCommError(m_hComHandle,&dwErrors,&cstStatus);
    }
    
    return (cstStatus.cbOutQue==0);
    
    
}

//read device response 
//return true if Read OK 
BOOL CLocalModbus::ReadResponseASCII(CByteArray& abyResponse,//bytes read 
                                     DWORD& dwRead) {    //num of bytes read 
    
    
    DWORD dwNumberOfBytesRead=0;
    DWORD dwTimeOut = m_lTimeOut;
    DWORD bFirstNull=FALSE;
    DWORD dwFirstNullTime=0;
    DWORD dwNullTime=0;
    DWORD  dwErrors;
    COMSTAT cstStatus;
    int iRespMaxSize;
    BOOL bAsciiCompleted;
    
    iRespMaxSize = abyResponse.GetSize();
    
    dwRead=0;
    
    bAsciiCompleted=FALSE;
    
    do {
        
        if (dwRead>DWORD(iRespMaxSize-1)) {
            return FALSE;
        }
        
        if( !::ReadFile(m_hComHandle,&abyResponse[dwRead],1,&dwNumberOfBytesRead,NULL) ) { //read one charcter 
            if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
                TRACE("ReadFile Errors 0x=%xd",dwErrors);
            }
            else{
                TRACE(" ClearCommError Failed reading");
            }
            
            return (FALSE);
        }
        
        
        if (dwNumberOfBytesRead == 1){
            dwRead += 1;
            if (1==dwRead) {
                m_PerfCounter.End();
            }
            dwTimeOut=m_dwSilentInterval;
            bFirstNull=FALSE;
            dwNullTime=0;
            if (dwRead>(DWORD)abyResponse.GetSize()) {
                return FALSE;
            }
        }
        
        else{
            
            if (!bFirstNull){
                bFirstNull=TRUE;
                dwFirstNullTime=::timeGetTime();
            }
            else {
                dwNullTime=::timeGetTime();
            }
            //DoEvents();
            ::Sleep(1);
            
        }
        
        
        
        if (!::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
            TRACE("ReadResponse ClearCommError Failed reading");
        }
        
        if (m_wTranmitionMode==MODE_ASCII){
            if (dwRead>5){//Read at least  <:>  <Address> <Functioncode> 
                if ((C_R==abyResponse[dwRead-2])&&(L_F==abyResponse[dwRead-1])){
                    bAsciiCompleted=TRUE;
                }
            }
            
        }
        
        
    } while	( ( (cstStatus.cbInQue>0)
        ||(dwNullTime<(dwTimeOut+dwFirstNullTime))
        )
        &&(!bAsciiCompleted)
        );
    
    return(TRUE);
    
}

//read device response 
//return true if Read OK 
BOOL CLocalModbus::ReadResponseRTU(CByteArray& abyResponse,//bytes read 
                                   DWORD& dwRead) {    //num of bytes read 
    
    
    DWORD dwNumberOfBytesRead=0;
    DWORD  dwErrors;
    COMSTAT cstStatus;
    int iRespMaxSize;
    
    
    iRespMaxSize = abyResponse.GetSize();
    
    dwRead=0;
    
    
    if( !::ReadFile(m_hComHandle,&abyResponse[dwRead],INITIAL_READ,&dwNumberOfBytesRead,NULL) ) { //read one charcter 
        if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
            TRACE("ReadFile Errors 0x=%xd",dwErrors);
        }
        else{
            TRACE(" ClearCommError Failed reading");
        }
        
        return (FALSE);
    }
    
    dwRead=dwRead+dwNumberOfBytesRead;
    
    if (INITIAL_READ==dwNumberOfBytesRead) {
        
        // do {
        
        if (dwRead>DWORD(iRespMaxSize-INITIAL_READ)) {
            return FALSE;
        }
        
        if( !::ReadFile(m_hComHandle,&abyResponse[dwRead],(iRespMaxSize-INITIAL_READ),&dwNumberOfBytesRead,NULL) ) { //read one charcter 
            if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
                TRACE("ReadFile Errors 0x=%xd",dwErrors);
            }
            else{
                TRACE(" ClearCommError Failed reading");
            }
            
            return (FALSE);
        }
        
        dwRead=dwRead+dwNumberOfBytesRead;
        
        
        //if (!::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
        //	   TRACE("ReadResponse ClearCommError Failed reading");
        // }
        
        
        //} while	(READ_SIZE==dwNumberOfBytesRead);   
        //} while	((cstStatus.cbInQue>0)||(READ_SIZE==dwNumberOfBytesRead));
        
    }
    
    return(TRUE);
    
}

BOOL CLocalModbus::ReadResponse(CByteArray& abyResponse,DWORD& dwRead,DWORD dwBytesToRead) {
    
    DWORD dwErrors;
    COMSTAT cstStatus;
    DWORD dwNumberOfBytesRead;
    COMMTIMEOUTS timeouts;
    DWORD dwCurrentReadTotalTimeoutConstant;
    
    //Get Current Timeouts 
    if(GetTimeouts(timeouts)) {
        
        dwCurrentReadTotalTimeoutConstant=timeouts.ReadTotalTimeoutConstant;				 
        
    }
    else {
        return FALSE;
    }
    
    dwRead=0;
    
    do {
        if( !::ReadFile(m_hComHandle,&abyResponse[dwRead],1,&dwNumberOfBytesRead,NULL) ) { //read one charcter 
            if (::ClearCommError(m_hComHandle,&dwErrors,&cstStatus)){
                TRACE("ReadFile Errors 0x=%xd",dwErrors);
            }
            else{
                TRACE(" ClearCommError Failed reading");
            }
            
            return (FALSE);
        }
        
        if (dwNumberOfBytesRead == 1){
            dwRead++;
            if (1==dwRead) {
                m_PerfCounter.End();
                timeouts.ReadTotalTimeoutConstant=SilentInterval();
                if (!SetTimeouts(&timeouts)){
                    TRACE("SetTimeouts Failed");
                    break;
                }
            }
        }
        
    } while (dwNumberOfBytesRead>0);
    
    if (dwRead>0) {
        timeouts.ReadTotalTimeoutConstant=dwCurrentReadTotalTimeoutConstant;
        if (!SetTimeouts(&timeouts)){
            TRACE("SetTimeouts Failed\n");
        }
    }
    
    return (TRUE);
    
}


BOOL CLocalModbus::ClearBuffers(){
    //Clear RxTx Buffers 
    return(::PurgeComm(m_hComHandle,(PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR)));
}



void CLocalModbus::TransmissionMode(WORD wMode)
{
    
    m_wTranmitionMode=wMode;
}

WORD CLocalModbus::TransmissionMode()
{
    return m_wTranmitionMode;
}

void CLocalModbus::RTU2ASCII(BYTE* aRtu, int iSize , BYTE* aAscii)
{
    
    int i=0;
    
    //ASSERT((iSize*2)<aAscii.GetSize());
    
    for (i=0;i<iSize;i++){
        aAscii[i*2]=Num2Ascii(HI4BITS(aRtu[i]));
        aAscii[i*2+1]=Num2Ascii(LO4BITS(aRtu[i]));
    }
    
}

BYTE CLocalModbus::Num2Ascii(BYTE byNum)
{
    if (byNum<=9){
        return byNum+'0';
    }
    else if ((byNum>=0xA)&&(byNum<=0xF)){
        return ((byNum-0xA)+'A');
    }
    else {
        ASSERT(FALSE);
        return '0';
    }
}

BOOL CLocalModbus::VerifyRespLRC(CByteArray& aResp, DWORD dwLength)
{
    
    BYTE byLRC;
    BYTE byMsgLRC;
    
    if (dwLength<5) {
        return FALSE;
    }
    
    byLRC=LRCASCII(aResp.GetData(),WORD(dwLength)); //calc crc 
    
    byMsgLRC=HiLo4BitsToByte(Ascii2Num(aResp[dwLength-4]),
        Ascii2Num(aResp[dwLength-3]));
    
    return (byLRC==byMsgLRC);
}

BYTE CLocalModbus::Ascii2Num(BYTE byChar)
{
    if ((byChar>='0')&&(byChar<='9')){
        return (byChar-'0');
    }
    else if ((byChar>='A')&&(byChar<='F')){
        return (byChar-'A')+0xA;
    }
    else {
        //ASSERT(FALSE);
        return 0; 
        
    }
}

BYTE CLocalModbus::HiLo4BitsToByte(BYTE byHi, BYTE byLo)
{
    
    return ( (((0xF)&byHi)<<4)| ((0xF)&byLo)    );
    
}


BYTE CLocalModbus::LRCASCII(BYTE *auchMsgASCII, WORD usDataLen) {
    
    BYTE uchLRC = 0 ;	/* LRC char initialized   */
    BYTE byTemp =0;
    int i;
    
    int iDataSize = int((usDataLen-5)/2);
    
    for (i=0;i<iDataSize;i++){
        byTemp=HiLo4BitsToByte(Ascii2Num(auchMsgASCII[1+i*2]),
            Ascii2Num(auchMsgASCII[1+i*2+1]));
        uchLRC +=byTemp;
    }
    
    //uchLRC = uchLRC ^ 0xffff;
    //uchLRC += 1;
    
    return BYTE(-uchLRC);
    
    
}

void CLocalModbus::ByteSize(WORD wSize)
{
    m_wByteSize= wSize;
}

WORD CLocalModbus::ByteSize()
{
    return m_wByteSize;
}

⌨️ 快捷键说明

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