Здравствуйте, jak, Вы писали:
jak>буду очень благодарен за исходник класса. Если можно пришли кусок кода для примера как организовывать общение между мастером и слэйвом.
jak>и по поводу соединения через RS232 компы могут быть отдалены друг от друга на расстояние порятка 1500м. на сколько я понимаю просто rs232 тянет в лучшем случаем метров на 10. Правильно? и что тогда делать?
В этом случае можно протянуть кабель и установить обычные модемы, которые будут обеспечивать связь (можно использовать радио-модемы). Я не очень вкурсе конкретных устройств, т.к. я программист. Могу лишь сказать, что мы когда-то использовали некое устройство "удлинитель порта" позволяющие передавать данные по RS232 на большие растояния (точно не скажу насколько

. Что касается кода — это вот такой класс (реализацию могу тоже предоставить после небольшой правки, если интересно, конечно...):
class CModbusConnection
{
public:
enum
{
RtuFrameMaxSize = 256,
RtuFrameMinSize = 4,
fExceptionMask = 0x80,
// Bit access
fReadDiscreteInputs = 1,
fReadCoils = 2,
fWriteSingleCoil = 5,
fWriteMultipleCoils = 15,
// 16 bits access
fReadInputRegisters = 4,
fReadHoldingRegisters = 3,
fWriteSingleRegister = 6,
fWriteMultipleRegisters = 16,
// Diagnostics
fReadExceptionStatus = 7
};
public:
CModbusConnection();
~CModbusConnection();
// Open comm port
bool Open(
/* [in] */ LPCTSTR lpszPortName,
/* [in] */ DWORD dwPortBaudRate,
/* [in] */ BYTE byPortByteSize,
/* [in] */ BYTE byPortParity,
/* [in] */ BYTE byPortStopBits,
/* [in] */ DWORD dwTimeoutRead,
/* [in] */ DWORD dwTimeoutWrite);
// Is openned comm port?
bool IsOpened();
// Close comm port
void Close();
// Sets the retry options
void SetRetryOptions(DWORD dwRetryCount, DWORD dwRetryDelay);
// Returnes the retry options
void GetRetryOptions(DWORD& dwRetryCount, DWORD& dwRetryDelay) const;
public:
// Sends read request (functions 1, 2, 3, 4)
bool ReadRequest(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ BYTE byFunction,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [out] */ BYTE* pbyData,
/* [in] */ BYTE byDataSize,
/* [out] */ BYTE& byDataRealSize);
public:
// #01 - Read Discrete Inputs
bool ReadDiscreteInputs(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [out] */ BYTE* pbyData,
/* [in] */ BYTE byDataSize,
/* [out] */ BYTE& byDataRealSize);
// #02 - Read Coils
bool ReadCoils(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [out] */ BYTE* pbyData,
/* [in] */ BYTE byDataSize,
/* [out] */ BYTE& byDataRealSize);
// #03 - Read Holding Registers
bool ReadHoldingRegisters(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [out] */ BYTE* pbyData,
/* [in] */ BYTE byDataSize,
/* [out] */ BYTE& byDataRealSize);
// #04 - Read Input Registers
bool ReadInputRegisters(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [out] */ BYTE* pbyData,
/* [in] */ BYTE byDataSize,
/* [out] */ BYTE& byDataRealSize);
// #05 - Write Single Coil
bool WriteSingleCoil(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wAddres,
/* [in] */ WORD wData);
// #06 - Write Single Register
bool WriteSingleRegister(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wAddres,
/* [in] */ WORD wData);
// #07 - Read Exception Status
bool ReadExceptionStatus(
/* [in] */ BYTE bySlaveAddres,
/* [out] */ BYTE& byStatus);
// #15 - Write Multiple Coils
bool WriteMultipleCoils(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [in] */ const BYTE* pbyData,
/* [in] */ BYTE byDataSize);
// #16 - Write Multiple Registers
bool WriteMultipleRegisters(
/* [in] */ BYTE bySlaveAddres,
/* [in] */ WORD wStartingAddres,
/* [in] */ WORD wQuantity,
/* [in] */ const WORD* pwData,
/* [in] */ BYTE byDataSize);
protected:
bool SendQueryWithRetry(
/* [in] */ const BYTE* pbyQuery,
/* [in] */ WORD wQuerySize,
/* [out] */ BYTE* pbyResponse,
/* [in] */ WORD wResponseSize,
/* [out] */ WORD* pwResponseRealSize);
bool SendQuery(
/* [in] */ const BYTE* pbyQuery,
/* [in] */ WORD wQuerySize,
/* [out] */ BYTE* pbyResponse,
/* [in] */ WORD wResponseSize,
/* [out] */ WORD* pwResponseRealSize);
bool ValidateResponse(
/* [in] */ const BYTE* pbyQuery,
/* [in] */ WORD wQuerySize,
/* [in] */ const BYTE* pbyResponse,
/* [in] */ WORD wResponseSize,
/* [in] */ WORD wResponseRealSize);
protected:
void TraceModbusError(LPCTSTR lpszPortName, BYTE byError, LPCTSTR lpszMessage);
void TraceCommError(LPCTSTR lpszPortName, DWORD dwError, LPCTSTR lpszMessage);
void TraceCommError(LPCTSTR lpszPortName, LPCTSTR lpszMessage);
void TraceCommInfo(LPCTSTR lpszPortName, LPCTSTR lpszMessage);
void TraceCommDebug(LPCTSTR lpszPortName, LPCTSTR lpszMessage);
void TraceFrame(const BYTE* pbyFrame, const WORD wFrameSize, bool bQuery);
bool ClearAndTraceCommError(HRESULT hrError, LPCTSTR lpszMessage);
protected:
CString m_strPortName;
HANDLE m_hCommPort;
protected:
DWORD m_dwRetryCount;
DWORD m_dwRetryDelay;
};