К обсуждению надо немного исходников добавить :))) Это не совсем модбас, но почти... эксперементы на досуге
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено diper 17 октября 2003 г. 09:59
В ответ на: Большое спасибо всем за обсуждение, даже DASM'у. отправлено КБ 16 октября 2003 г. 21:32

AS IS

h-file

//---------------------------------------------------------------------------

#ifndef ModBusH
#define ModBusH
//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------

typedef enum mdbErrors {
mdbOk = 0, //ОК
mdbIllegalFunction = 1, //неверная функция
mdbIllegalDataAddress = 2, //
mdbIllegalDataValue = 3, //некорректные входные данные
mdbSlaveDeviceFailure = 4, //сбой устройства
mdbAcknowledge = 5, //данные приняты, но требуется обработка
mdbSlaveDeviceBusy = 6, //устройство неготово обрабоать команду
mdbMemoryParityError = 8, //данные повреждены
mdbPortError = 0x100, //ошибка порта
mdbCRCError = 0x101, //ошибка КС
mdbSizeError = 0x102, //неожиданная длина пакета
mdbTimeOut = 0x103, //нет ответа
mdbWrongResponse = 0x104, //структура пакета некорректна
msbWrongInputData = 0x105 //неверные входные данные в функцию
} mdbErrors;

struct ErrorResponseStructure{
unsigned char Address;
unsigned char Command;
unsigned char Error;
unsigned short CRC;
};


class TModBus// : public TThread
{
private:
HANDLE CommHandle;
int TimeOut;
unsigned char SlaveAddress;
protected:
void __fastcall Execute();
mdbErrors __fastcall ProcessErrorResponse(struct ErrorResponseStructure *ErrorResponse);

public:
__fastcall TModBus(void);
mdbErrors __fastcall Init(char* commport, unsigned char addr, unsigned short timeout);

mdbErrors __fastcall Ping(unsigned char addr);
mdbErrors __fastcall SetSlaveAddress(unsigned char addr);
mdbErrors __fastcall DataExchange(void *requestDataPtr, void *responseDataPtr, unsigned short requestDataLen, unsigned short &responseDataLen);
mdbErrors __fastcall SetTimeOut(unsigned short timeout);
};

//---------------------------------------------------------------------------
#endif


c-file
//---------------------------------------------------------------------------

#include
#pragma hdrstop

#include "ModBus.h"
#include "CRC16.h"

#pragma package(smart_init)
//---------------------------------------------------------------------------

// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall TModBusThread::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------

__fastcall TModBus::TModBus(void)
// : TThread(false)
{
CommHandle = INVALID_HANDLE_VALUE;
TimeOut = 1000;
SlaveAddress = 0;
}
//---------------------------------------------------------------------------

void __fastcall TModBus::Execute()
{
//---- Place thread code here ----

}
//---------------------------------------------------------------------------

mdbErrors __fastcall TModBus::Init(char* commport, unsigned char addr, unsigned short timeout){
DCB dcb;
COMMTIMEOUTS to;

SlaveAddress = addr;
BuildCommDCB("baud=9600 parity=N data=8 stop=1",&dcb);
dcb.fOutxCtsFlow = false;
dcb.fOutxDsrFlow = false;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = false;
dcb.fOutX = false;
dcb.fInX = false;
dcb.fRtsControl = RTS_CONTROL_ENABLE;

to.ReadIntervalTimeout = 1;
to.ReadTotalTimeoutMultiplier = 0;
to.ReadTotalTimeoutConstant = timeout;
to.WriteTotalTimeoutMultiplier = 0;
to.WriteTotalTimeoutConstant = 0;

CloseHandle(CommHandle);
CommHandle = CreateFile(commport, GENERIC_READ+GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,NULL);
if (CommHandle == INVALID_HANDLE_VALUE)
return mdbPortError;
if(!SetCommState(CommHandle, &dcb))
return mdbPortError;
if(!SetCommTimeouts(CommHandle, &to))
return mdbPortError;

return mdbOk;
}
//---------------------------------------------------------------------------

mdbErrors __fastcall TModBus::Ping(unsigned char addr){
unsigned char data[300];
DWORD tmp;
data[0] = addr;
data[1] = 0x00;
*(unsigned short*)&data[2] = CRC16(data,2);

if(!WriteFile(CommHandle, data, 4, &tmp, NULL))
return mdbPortError;
if(tmp != 4)
return mdbPortError;

if(!PurgeComm(CommHandle,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR))
return mdbPortError;
if(!ReadFile(CommHandle, data, 257, &tmp, NULL))
return mdbPortError;
if(tmp == 0)
return mdbTimeOut;
if(data[0] != addr)
return mdbWrongResponse;

if(data[1] == 0x80 && tmp==5)
return ProcessErrorResponse((struct ErrorResponseStructure*)data);

if(tmp != 4)
return mdbWrongResponse;
if(data[1] != 0)
return mdbWrongResponse;
if(*(unsigned short*)&data[2] != CRC16(data,2))
return mdbCRCError;


return mdbOk;
}
//---------------------------------------------------------------------------

mdbErrors __fastcall TModBus::ProcessErrorResponse(struct ErrorResponseStructure *ErrorResponse){
if(ErrorResponse->CRC != CRC16((unsigned char*)&ErrorResponse,3))
return mdbCRCError;
return (mdbErrors)(ErrorResponse->Error&0x0F);
}
//---------------------------------------------------------------------------

mdbErrors __fastcall TModBus::DataExchange(void *requestDataPtr, void *responseDataPtr, unsigned short requestDataLen, unsigned short &responseDataLen){
DWORD tmp;
unsigned char data[300];

data[0] = SlaveAddress;
data[1] = 0x20;
data[2] = requestDataLen;
memcpy(data+3, requestDataPtr, requestDataLen);
*(unsigned short*)&data[requestDataLen+3] = CRC16(data, requestDataLen+3);

if(!WriteFile(CommHandle, data, requestDataLen+5, &tmp, NULL))
return mdbPortError;
if(tmp!=(DWORD)(requestDataLen+5))
return mdbPortError;

if(!PurgeComm(CommHandle,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR))
return mdbPortError;
if(!ReadFile(CommHandle, data, 257, &tmp, NULL))
return mdbPortError;
if(tmp == 0)
return mdbTimeOut;
if(data[0] != SlaveAddress)
return mdbWrongResponse;
if(tmp == 5 && data[1] == 0x20+0x80)
return ProcessErrorResponse((struct ErrorResponseStructure*)data);
if(data[1] != 0x20)
return mdbWrongResponse;
if(tmp>256 || tmp< 5)
return mdbWrongResponse;
if((DWORD)data[2] != tmp-5)
return mdbWrongResponse;
if(responseDataLen == 0){//если ответ может иметь любую длинну, то...
if(*(unsigned short*)&data[data[2]+3] != CRC16(data, tmp-2))
return mdbCRCError;
memcpy(responseDataPtr, data+3, data[2]);
responseDataLen = data[2];
}else{//предполагается ответ с определенной длинной
if(data[2] != responseDataLen)
return mdbSizeError;
memcpy(responseDataPtr, data+3, data[2]);
}

return mdbOk;
}
//---------------------------------------------------------------------------

mdbErrors __fastcall TModBus::SetTimeOut(unsigned short timeout){
COMMTIMEOUTS to;

to.ReadIntervalTimeout = 1;
to.ReadTotalTimeoutMultiplier = 0;
to.ReadTotalTimeoutConstant = timeout;
to.WriteTotalTimeoutMultiplier = 0;
to.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(CommHandle, &to))
return mdbPortError;
return mdbOk;
}
//---------------------------------------------------------------------------

mdbErrors __fastcall TModBus::SetSlaveAddress(unsigned char addr){
SlaveAddress = addr;
return mdbOk;
}


Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru