📄 itkplcdlg.cpp
字号:
//----(Member Function)-------------------------------------------------------
//
// @mfunc void | CItkPlcDlg | OnClearMemory |
//
// Clears the entire memory map.
//
void CItkPlcDlg::OnClearMemory()
{
this->UpdateMemoryMap(CLEAR_MEMORY);
}
/////////////////////////////////////////////////////////////////////////////
//
// All of the member functions from here are for communications to the
// I/O Driver and thread management.
//
/////////////////////////////////////////////////////////////////////////////
#include <Serial.h>
#include <ItkErr.h>
//----(Member Function)-------------------------------------------------------
//
// @mfunc UINT | CItkPlcDlg | IoHandler |
//
// Handler for the I/O Communication's thread.
//
UINT CItkPlcDlg::IoHandler(LPVOID ptr)
{
CItkPlcDlg *pThis = (CItkPlcDlg *)ptr;
DWORD dwStatus = IO_SUCCESS,
dwActualSize = 0;
BOOL bTcp = TRUE;
unsigned char buffer[4096];
pThis->m_hNotifyEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
if (NULL == pThis->m_hNotifyEvt)
{
return(0);
}
switch (pThis->m_dwProtocol)
{
case TCPIP_PROTOCOL:
// Create TCP/IP version of Io Object
bTcp = TRUE;
memset((char *)pThis->m_chReceiveBuffer, 0, RECEIVE_BUFFER_SIZE);
pThis->m_pTcp = new CTcpIp("Itk", pThis->m_szIpAddress, 0, bTcp, NULL, (void *)pThis, NULL, &TcpSrvCallback, NULL, (unsigned short) pThis->m_uPortNumber, pThis->m_chReceiveBuffer, RECEIVE_BUFFER_SIZE);
break;
case UDPIP_PROTOCOL:
// Create UDP/IP version of Io Object
bTcp = FALSE;
memset((char *)pThis->m_chReceiveBuffer, 0, RECEIVE_BUFFER_SIZE);
pThis->m_pTcp = new CTcpIp("Itk", pThis->m_szIpAddress, 0, bTcp, NULL, (void *)pThis, NULL, NULL, &UdpSrvCallback, (unsigned short) pThis->m_uPortNumber, pThis->m_chReceiveBuffer, RECEIVE_BUFFER_SIZE);
break;
case SERIAL_PROTOCOL:
default:
// Create Serial version of Io Object
pThis->m_pIo = new CSerial("ItkPlc");
break;
}
if (pThis->m_pIo || pThis->m_pTcp )
{
memset((char *)buffer, 0, 4096);
switch (pThis->m_dwProtocol)
{
case TCPIP_PROTOCOL:
case UDPIP_PROTOCOL:
// If tcpip do nothing. Server already started
//
break;
case SERIAL_PROTOCOL:
default:
dwStatus = pThis->m_pIo->Open(pThis->m_szPortName,
pThis->m_szPortMode,
(HANDLE)pThis->m_hNotifyEvt);
break;
}
if (IO_SUCCESS == dwStatus)
{
switch (pThis->m_dwProtocol)
{
case TCPIP_PROTOCOL:
case UDPIP_PROTOCOL:
// SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
break;
case SERIAL_PROTOCOL:
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
default:
break;
}// End switch
//
// Kick off a thread for unsolicited messages, if needed
//
if ((NULL == pThis->m_hUnsolThread) && (pThis->m_bUnsolicited))
{
DWORD dwUnsolIoThreadId = 0;
pThis->m_hUnsolThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)UnsolIoHandler,
(LPVOID)pThis,
0,
&dwUnsolIoThreadId);
}
while (!pThis->m_bShutdown)
{
switch (pThis->m_dwProtocol)
{
case TCPIP_PROTOCOL:
case UDPIP_PROTOCOL:
//
// If tcpip do nothing. Server already started
// If there is anything in receive buffer it will
// invoke the CALLBACK function
//
Sleep(WAIT_TIME);
break;
case SERIAL_PROTOCOL:
default:
//
// Receive and parse a serial message.
//
switch(WaitForSingleObject(pThis->m_hNotifyEvt, INFINITE))
{
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
AfxMessageBox("Wait for IO notification failed");
break;
case WAIT_OBJECT_0:
dwStatus = pThis->m_pIo->Receive(buffer,
4096,
&dwActualSize);
if (IO_SUCCESS == dwStatus)
{
pThis->ParseMsg(buffer, dwActualSize);
}
else
{
AfxMessageBox("Failed to read data");
}
break;
}
break;
} // end switch (pThis->m_dwProtocol)
} // end while (!pThis->m_bShutdown)
switch (pThis->m_dwProtocol)
{
case TCPIP_PROTOCOL:
case UDPIP_PROTOCOL:
break;
case SERIAL_PROTOCOL:
default:
pThis->m_pIo->Close();
break;
}
}
else
{
AfxMessageBox("Error occurred while performing an open");
}
CloseHandle(pThis->m_hNotifyEvt);
switch (pThis->m_dwProtocol)
{
case TCPIP_PROTOCOL:
case UDPIP_PROTOCOL:
delete pThis->m_pTcp;
break;
case SERIAL_PROTOCOL:
default:
delete pThis->m_pIo;
break;
}
}
return(1);
}
//----(Member Function)-------------------------------------------------------
//
// @mfunc void | CItkPlcDlg | ParseMsg |
//
// Parses a message from the I/O Driver
//
void CItkPlcDlg::ParseMsg(unsigned char buffer[], DWORD dwSize)
{
DWORD dwLoop;
unsigned char Value;
static unsigned short int rcv_state = DLE1,
calc_bcc = 0,
dest = 0, // destination (our station)
src = 0, // source (from who)
start = 0,
len = 0,
cmd = 0,
dle_flag = 0,
ans_len = 0,
ans_start = 0,
ans_src = 0, // destination (to who)
ans_dest = 0, // source (our station)
set_mask = 0,
reset_mask = 0,
transaction = 0;
static unsigned short int write_val[120];
unsigned int i;
for (dwLoop = 0; dwLoop < dwSize; dwLoop++)
{
Value = buffer[dwLoop];
//
// Check for doubled-up DLE's
//
if (Value == DLE)
{
if (dle_flag) // was previous dle ?
{
dle_flag = FALSE; // clear flag
continue; // done
}
else
{
dle_flag = TRUE; // first dle
}
}
else
{
dle_flag = FALSE; // clear flag
}
switch (rcv_state)
{
case DLE1:
if (Value == DLE)
{
calc_bcc = 0; // reset bcc
rcv_state = STX1;
}
break;
case STX1:
switch(Value)
{
case STX:
if (this->m_bSourceStn)
{
rcv_state = SRC1;
}
else
{
rcv_state = DEST1;
}
calc_bcc = 0; // reset bcc
break;
case NAK:
rcv_state = DLE1;
this->m_pdlgCommStats->m_dwNakRcvdCount++;
AnswerRead(ans_dest, ans_src, ans_start, ans_len, cmd, transaction);
break;
case ACK:
rcv_state = DLE1;
this->m_pdlgCommStats->m_dwAckRcvdCount++;
break;
}
break;
case SRC1: // Source Station address
src = Value;
rcv_state = DEST1;
calc_bcc += Value;
break;
case DEST1: // Destination Station address
dest = Value;
//
// Make sure the message is for us. A Local Station
// set to 0 means to accept ALL messages.
//
if ((this->m_dwLocalStation == 0) ||
(this->m_dwLocalStation == dest))
{
rcv_state = CMD1;
calc_bcc += Value;
break;
}
else
{
rcv_state = DLE1;
SendDLE(NAK);
return;
}
case CMD1: // Command
cmd = Value;
if (this->m_bTransNum)
{
rcv_state = TRANHI;
}
else
{
rcv_state = ADDLO;
}
calc_bcc += Value;
break;
case TRANHI: // Transaction Number hi-byte
transaction = (Value << 8);
rcv_state = TRANLO;
calc_bcc += Value;
break;
case TRANLO: // Transaction Number lo-byte
transaction += Value;
rcv_state = ADDLO;
calc_bcc += Value;
break;
case ADDLO: // Start Adress lo-byte
start = Value;
rcv_state = ADDHI;
calc_bcc += Value;
break;
case ADDHI: // Start Address hi-byte
start |= ((Value<<8) & 0xff00);
calc_bcc += Value;
switch (cmd)
{
case READ_CMD:
rcv_state = LEN1;
break;
case BIT_WRITE_CMD:
rcv_state = SET1;
break;
case WRITE_CMD:
len = 0;
rcv_state = DATA1;
break;
default:
rcv_state = DLE1;
}
break;
case DATA1:
write_val[len] = Value;
if (Value == DLE)
{
rcv_state = DATA_DLE;
dle_flag = FALSE;
}
else
{
rcv_state = DATA2;
calc_bcc += Value;
}
break;
case DATA2:
write_val[len] |= ((Value << 8) & 0xff00);
len++;
if (Value == DLE)
{
rcv_state = DATA_DLE2;
dle_flag = FALSE;
}
else
{
rcv_state = DATA1;
calc_bcc += Value;
}
break;
case DATA_DLE:
switch(Value)
{
case DLE:
rcv_state = DATA2;
calc_bcc += Value;
break;
case ETX:
rcv_state = BCC1;
break;
default:
rcv_state = DLE1;
break;
}
break;
case DATA_DLE2:
switch(Value)
{
case DLE:
rcv_state = DATA1;
calc_bcc += Value;
break;
case ETX:
rcv_state = BCC1;
break;
default:
rcv_state = DLE1;
break;
}
break;
case SET1:
set_mask = Value;
rcv_state = SET2;
calc_bcc += Value;
break;
case SET2:
set_mask |= ((Value<<8) & 0xff00 );
rcv_state = RESET1;
calc_bcc += Value;
break;
case RESET1:
reset_mask = Value;
rcv_state = RESET2;
calc_bcc += Value;
break;
case RESET2:
reset_mask |= ( (Value<<8) & 0xff00 );
rcv_state = DLE2;
calc_bcc += Value;
break;
case LEN1:
len = Value;
rcv_state = DLE2;
calc_bcc += Value;
break;
case DLE2:
if (Value == DLE)
{
rcv_state = ETX1;
}
else
{
rcv_state = DLE1;
}
break;
case ETX1:
if ( Value == ETX )
{
rcv_state = BCC1;
}
else
{
rcv_state = DLE1;
}
break;
case BCC1: // Checksum
calc_bcc += Value;
rcv_state = DLE1;
if ((calc_bcc & this->m_cBCCMask) == 0)
{
SendDLE(ACK);
switch (cmd)
{
case READ_CMD:
this->m_pdlgCommStats->m_dwReadCount++;
ans_len = len;
ans_start = start;
ans_src = dest;
ans_dest = src;
AnswerRead(ans_dest, ans_src, ans_start, ans_len, cmd, transaction);
break;
case BIT_WRITE_CMD:
this->m_pdlgCommStats->m_dwBitWriteCount++;
PlcMemory[start] &= ~reset_mask; // clear bits
PlcMemory[start] |= set_mask; // set bits
this->UpdateRow((start / REGISTERS_PER_ROW));
ans_len = 2;
ans_start = start;
ans_src = dest;
ans_dest = src;
AnswerRead(ans_dest, ans_src, ans_start, ans_len, cmd, transaction);
break;
case WRITE_CMD:
{
DWORD dwNumRows = 0,
dwFirstRow,
dwRow;
this->m_pdlgCommStats->m_dwWriteCount++;
//
// Put the write data in the memory map
//
for (i = 0; i < len; i++)
{
PlcMemory[start + i] = write_val[i];
}
dwNumRows = (len / REGISTERS_PER_ROW) + 1;
dwFirstRow = (start / REGISTERS_PER_ROW);
//
// Update the rows changed
//
for (dwRow = 0; dwRow < dwNumRows; dwRow++)
{
this->UpdateRow(dwFirstRow + dwRow);
}
ans_len = 2;
ans_start = start;
ans_src = dest;
ans_dest = src;
AnswerRead(ans_dest, ans_src, ans_start, ans_len, cmd, transaction);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -