MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/driver/ModbusRtu.hh
2024-06-07 11:12:56 +03:00

198 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* ModbusRtu.hh
*
* Created on: 26 авг. 2020 г.
* Author: LeonidTitov
*/
#ifndef UMLIBRARY_DRIVER_MODBUSRTU_HH_
#define UMLIBRARY_DRIVER_MODBUSRTU_HH_
#include <cstddef>
#include <stdint.h>
#include <memory_resource>
#include <deque>
#include <vector>
#include <map>
#include "../common/Crc.hpp"
#include "../peripheral/IUartPort.hh"
#include "IModBus.hh"
namespace driver {
namespace modbus {
using peripheral::IUartPort;
using std::pmr::memory_resource;
using std::pmr::polymorphic_allocator;
using std::pmr::get_default_resource;
using std::deque;
using std::vector;
using std::map;
using std::pair;
using std::make_pair;
typedef deque<char,polymorphic_allocator<char> > DequePolyAlloc;
typedef deque<uint16_t,polymorphic_allocator<uint16_t> > DequeU16PolyAlloc;
typedef map<uint16_t, uint16_t, std::less<uint16_t>,
polymorphic_allocator<pair<const uint16_t,uint16_t> > > MapPolyAlloc;
typedef vector<char,polymorphic_allocator<char> > VecPolyAlloc;
typedef map<uint16_t,IModBusDispatch*,std::less<uint16_t>,
polymorphic_allocator<pair<const uint16_t,IModBusDispatch*> > > MapDispPolyAlloc;
class ModBusPdu;
class ModBusDispatch;
class ModBusAdu {
IUartPort & mIUartPort;
const unsigned char mAddr;
memory_resource * const mpMemRes;
friend class ModBusPdu;
friend class ModBusDispatch;
bool crc_error_flag;
public:
typedef common::crc::Crc16_IBM ModbusCrc;
ModBusAdu ( unsigned char addr, IUartPort& port, memory_resource* pMemRes ) :
mIUartPort(port), mAddr(addr), mpMemRes(pMemRes), crc_error_flag(false) {}
/* Запрос фрэйма PDU */
bool getFrm( DequePolyAlloc & deqFrm );
bool putFrm( DequePolyAlloc & deqFrm );
bool isCrcError() const;
};
class ModBusPdu {
enum FuncCode {
DummyCode, // ??
ReadCoil = 1, WriteSingleCoil = 5, WriteMultipleCoil = 15, // DO
ReadDiscreteInput = 2, // DI
ReadHoldingReg = 3, WriteSingleReg = 6, WriteMultipleReg = 16, // AO
ReadInputReg = 4, // AI
};
friend class ModBusDispatch;
public:
enum ExceptCode {
NoException, IllegalFunc, IllegalDataAddr, IllegalDataValue, ServerDeviceFail,
Acknowledge, ServerDeviceBusy, MemoryParityErr = 8,
GatewayPathUnvail = 10, GatewayTargetDeviceFailResp
};
private:
struct DataTableBegin {
static const uint16_t DO = 1;
static const uint16_t DI = 10001;
static const uint16_t AI = 30001;
static const uint16_t AO = 40001;
};
ModBusAdu & mAdu;
DequePolyAlloc deqFrmReq; //!<Буфер для запроса
DequePolyAlloc deqFrmRes; //!<Буфер для ответа
bool mIsBroadcast; //!<Флаг широковешательного запроса
uint16_t mFuncCode; //!< != 0 Текущий активный код, 0 -> состояние ожидания
ExceptCode mExcCode; //!<Код исключения
uint16_t packet_counter;
public:
MapPolyAlloc mMapTaskRd; //!<Очередь заданий на чтение
MapPolyAlloc mMapTaskWr; //!<Очередь заданий на запись
MapPolyAlloc mMapTaskRes; //!<Очередь полученных результатов
public:
ModBusPdu ( ModBusAdu& adu ) :
mAdu(adu), mIsBroadcast(false), mFuncCode(DummyCode), mExcCode(NoException),
deqFrmReq(adu.mpMemRes), deqFrmRes(adu.mpMemRes),
mMapTaskRd(std::less<uint16_t>(),adu.mpMemRes),
mMapTaskWr(std::less<uint16_t>(),adu.mpMemRes),
mMapTaskRes(std::less<uint16_t>(),adu.mpMemRes),
packet_counter(0) {}
//!Процесс ожидания запроса и формирования по нему списка заданий
void processReq();
//!Процесс ожидания выполнение списка заданий и отправка ответа на запрос
void processResp();
void setExceptCode( ExceptCode code );
bool isException() const;
uint16_t getPacketCounter() const;
ExceptCode getExceptCode() const;
private:
//!Получение максимально количества регистров в операции по ее коду
uint16_t getLimitQuantity( FuncCode code ) const;
//!Получение начального смещения в таблице данных по коду операции
uint16_t getDataTblShift( FuncCode code ) const;
};
class ModBusDispatch {
enum TaskType { TaskRead, TaskWrite };
MapDispPolyAlloc mBase;
ModBusPdu & mPdu;
public:
ModBusDispatch ( ModBusPdu& pdu ) :
mPdu(pdu), mBase(std::less<uint16_t>(), pdu.mAdu.mpMemRes) {}
void add( uint16_t nReg, IModBusDispatch & disp );
void del( uint16_t nReg );
void process();
private:
void dispatch( TaskType typeOp, MapPolyAlloc & mapTasks );
};
class ModBusRtu : public IModBus {
ModBusAdu mAdu;
ModBusPdu mPdu;
ModBusDispatch mDisp;
IUartPort& mPort;
public:
ModBusRtu ( uint16_t addr, IUartPort& port,
memory_resource* pMemRes = get_default_resource () ) :
mAdu(addr,port,pMemRes), mPdu(mAdu), mDisp(mPdu), mPort(port) {}
void process();
void add( uint16_t nReg, IModBusDispatch & disp );
void del( uint16_t nReg );
bool isCrcError() const;
bool isException() const;
float getPacketCounter() const;
};
} // namespace modbus
} // namespace driver
#endif /* UMLIBRARY_DRIVER_MODBUSRTU_HH_ */