📄 localmodbus.cpp
字号:
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 + -