在这个平台上,我一直在为两个通过SPI通信的数字输入扩展器开发软件驱动程序。我的C++代码是基于单片机制造商提供的SDK附带的SPI驱动程序编写的。从时间的角度来看,驱动程序被认为是非阻塞的,并利用回调函数进行定期更新。从架构的角度来看,驱动程序的设计方式如下:
DigitalInputsDriver类组成,它为软件的应用层提供了接口。MAX22190类建模。Register类的实例)。这些实例是MAX22190芯片中真正hw寄存器的“镜像”。根据封装在类Configurator和Refresher中的配置和刷新算法,这些镜像的内容与它们的hw对应保持一致。基于Configurator和Refresher的激励机制,Register对象通过MAX22190抽象类定义的WriteRegRequestMsg、ReadRegRequestMsg、WriteRegResponseMsg和ReadRegResponseMsg类的实例消息与MAX22190芯片进行通信。DigitalInputsDriverCfg类。数字输入
#include "DigitalInputsDriverCfg.h"
#include "MAX22190.h"
#include "Transceiver.h"
#include
class DigitalInputsDriver
{
public:
enum class Input{
kDi_00,
kDi_01,
kDi_02,
kDi_03,
kDi_04,
kDi_05,
kDi_06,
kDi_07,
kDi_08,
kDi_09,
kDi_10,
kDi_11,
kDi_12,
kDi_13,
kDi_14,
kDi_15,
kNoDigitalInputs
};
enum class State{kLow, kHigh};
enum class Fault1{
kWireBreakDevice0,
k24VMDevice0,
k24VLDevice0,
kOverTemperature1Device0,
kOverTemperature2Device0,
kFault2Device0,
kPorDevice0,
kCrcDevice0,
kWireBreakDevice1,
k24VMDevice1,
k24VLDevice1,
kOverTemperature1Device1,
kOverTemperature2Device1,
kFault2Device1,
kPorDevice1,
kCrcDevice1
};
enum class Fault2{
kREFWBShortDevice0,
kREFWBOpenDevice0,
kREFDIShortDevice0,
kREFDIOpenDevice0,
kOverTempShutdownDevice0,
kFault8ClkDevice0,
kREFWBShortDevice1 = 8,
kREFWBOpenDevice1 = 9,
kREFDIShortDevice1 = 10,
kREFDIOpenDevice1 = 11,
kOverTempShutdownDevice1 = 12,
kFault8ClkDevice1 = 13,
};
DigitalInputsDriver(DigitalInputsDriverCfg *_dig_in_cfg, uint16_t _spi_device_id);
void update(void);
void initialize(void);
bool isReady(void);
State getInputState(Input input);
bool isFault1Active(Fault1 fault);
bool isFault2Active(Fault2 fault);
void handleFpgaProtection(void);
void handleSpiEndOfTransactionInterrupt(void);
private:
Transceiver transceiver;
MAX22190 device0;
MAX22190 device1;
MAX22190 *devices[static_cast(DigitalInputsDriverCfg::Device::kNoMAX22190Devices)];
};
#include "DigitalInputsDriver.h"
DigitalInputsDriver::DigitalInputsDriver(DigitalInputsDriverCfg *_dig_in_cfg,
uint16_t _spi_device_id) :
transceiver(_spi_device_id),
device0(DigitalInputsDriverCfg::Device::kMAX22190Device_0, _dig_in_cfg, &transceiver),
device1(DigitalInputsDriverCfg::Device::kMAX22190Device_1, _dig_in_cfg, &transceiver)
{
devices[static_cast(DigitalInputsDriverCfg::Device::kMAX22190Device_0)] =
&device0;
devices[static_cast(DigitalInputsDriverCfg::Device::kMAX22190Device_1)] =
&device1;
}
void DigitalInputsDriver::initialize(void)
{
transceiver.initialize();
for(MAX22190 *device : devices){
device->initialize();
}
}
void DigitalInputsDriver::update(void)
{
for(MAX22190 *device : devices){
device->update();
}
}
bool DigitalInputsDriver::isReady(void)
{
bool retval = true;
for(MAX22190 *device : devices){
if(device->isReady() == false){
retval = false;
break;
}
}
return retval;
}
DigitalInputsDriver::State DigitalInputsDriver::getInputState(Input input)
{
return static_cast(devices[(static_cast(input) >> 3)]->isInputActive(static_cast(static_cast(input) - ((static_cast(input) >> 3) << 3))));
}
bool DigitalInputsDriver::isFault1Active(Fault1 fault)
{
return devices[(static_cast(fault) >> 3)]->isFault1Active(static_cast(static_cast(fault) - ((static_cast(fault) >> 3) << 3)));
}
bool DigitalInputsDriver::isFault2Active(Fault2 fault)
{
return devices[(static_cast(fault) >> 3)]->isFault2Active(static_cast(static_cast(fault) - ((static_cast(fault) >> 3) << 3)));
}
void DigitalInputsDriver::handleFpgaProtection(void)
{
for(MAX22190 *device : devices){
device->handleFaultPinActivation();
}
}
void DigitalInputsDriver::handleSpiEndOfTransactionInterrupt(void)
{
for(MAX22190 *device : devices){
device->notifyEndOfTransaction();
}
}MAX22190 22190
#include "Register.h"
#include "DigitalInputsDriverCfg.h"
#include "Configurator.h"
#include "TransactionEndListener.h"
#include "Transceiver.h"
#include "Refresher.h"
class MAX22190 : public TransactionEndListener
{
friend class Configurator;
friend class Refresher;
public:
enum class Fault1{
kWireBreak,
k24VM,
k24VL,
kOverTemperature1,
kOverTemperature2,
kFault2,
kPor,
kCrc
};
enum class Fault2{
kREFWBShort,
kREFWBOpen,
kREFDIShort,
kREFDIOpen,
kOvertempShd,
kFault8Clk
};
MAX22190(DigitalInputsDriverCfg::Device _device, DigitalInputsDriverCfg *_configuration,
Transceiver *_transceiver);
void initialize(void);
void update(void);
bool isReady(void);
bool isInputActive(DigitalInputsDriverCfg::Input input);
bool isFault1Active(Fault1 fault);
bool isFault2Active(Fault2 fault);
void handleFaultPinActivation(void);
void activateLatch(void);
uint8_t getDeviceId(void);
void notifyEndOfTransaction(void);
private:
enum class ConfigurationState{
kConfigInEnReg,
kConfigFlt1Reg,
kConfigFlt2Reg,
kConfigFlt3Reg,
kConfigFlt4Reg,
kConfigFlt5Reg,
kConfigFlt6Reg,
kConfigFlt7Reg,
kConfigFlt8Reg,
kConfigFault2EnReg,
kConfigFault1EnReg,
kConfigCfgReg,
kConfigGpoReg,
kConfigurationEnd
};
enum class RefreshState{
kRefreshFault1Reg,
kRefreshFault2Reg,
kRefreshDiReg,
kRefreshWbReg
};
static constexpr uint8_t wb_reg_addr = 0x00;
static constexpr uint8_t di_reg_addr = 0x02;
static constexpr uint8_t fault1_reg_addr = 0x04;
static constexpr uint8_t flt1_reg_addr = 0x06;
static constexpr uint8_t flt2_reg_addr = 0x08;
static constexpr uint8_t flt3_reg_addr = 0x0A;
static constexpr uint8_t flt4_reg_addr = 0x0C;
static constexpr uint8_t flt5_reg_addr = 0x0E;
static constexpr uint8_t flt6_reg_addr = 0x10;
static constexpr uint8_t flt7_reg_addr = 0x12;
static constexpr uint8_t flt8_reg_addr = 0x14;
static constexpr uint8_t cfg_reg_addr = 0x18;
static constexpr uint8_t inen_reg_addr = 0x1A;
static constexpr uint8_t fault2_reg_addr = 0x1C;
static constexpr uint8_t fault2en_reg_addr = 0x1E;
static constexpr uint8_t gpo_reg_addr = 0x22;
static constexpr uint8_t fault1en_reg_addr = 0x24;
static constexpr uint8_t nop_reg_addr = 0x26;
static constexpr uint8_t no_regs = 18;
Register wb_reg;
Register di_reg;
Register fault1_reg;
Register flt1_reg;
Register flt2_reg;
Register flt3_reg;
Register flt4_reg;
Register flt5_reg;
Register flt6_reg;
Register flt7_reg;
Register flt8_reg;
Register cfg_reg;
Register inen_reg;
Register fault2_reg;
Register fault2en_reg;
Register gpo_reg;
Register fault1en_reg;
Register nop_reg;
Register* register_map[no_regs];
Configurator configurator;
Refresher refresher;
DigitalInputsDriverCfg::Device device;
DigitalInputsDriverCfg *configuration;
Transceiver *transceiver;
bool device_ready;
bool device_configured;
bool read_faults;
ConfigurationState state_config;
RefreshState state_refresh;
bool configure(void);
void configureInEnReg(void);
void configureFlt1Reg(void);
void configureFlt2Reg(void);
void configureFlt3Reg(void);
void configureFlt4Reg(void);
void configureFlt5Reg(void);
void configureFlt6Reg(void);
void configureFlt7Reg(void);
void configureFlt8Reg(void);
void configureFault2EnReg(void);
void configureFault1EnReg(void);
void configureCfgReg(void);
void configureGpoReg(void);
void refresh(void);
void refreshDiReg(void);
void refreshWbReg(void);
void refreshFault1Reg(void);
void refreshFault2Reg(void);
};
#include "MAX22190.h"
MAX22190::MAX22190(DigitalInputsDriverCfg::Device _device, DigitalInputsDriverCfg *_configuration,
Transceiver *_transceiver) :
wb_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kWb, wb_reg_addr, _transceiver),
di_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kDi, di_reg_addr, _transceiver),
fault1_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFault1,
fault1_reg_addr, _transceiver),
flt1_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt1,
flt1_reg_addr, _transceiver),
flt2_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt2,
flt2_reg_addr, _transceiver),
flt3_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt3,
flt3_reg_addr, _transceiver),
flt4_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt4,
flt4_reg_addr, _transceiver),
flt5_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt5,
flt5_reg_addr, _transceiver),
flt6_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt6,
flt6_reg_addr, _transceiver),
flt7_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt7,
flt7_reg_addr, _transceiver),
flt8_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFlt8,
flt8_reg_addr, _transceiver),
cfg_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kCfg, cfg_reg_addr, _transceiver),
inen_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kInEn,
inen_reg_addr, _transceiver),
fault2_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFault2,
fault2_reg_addr, _transceiver),
fault2en_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFault2En,
fault2en_reg_addr, _transceiver),
gpo_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kGpo, gpo_reg_addr, _transceiver),
fault1en_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kFault1En,
fault1en_reg_addr, _transceiver),
nop_reg(_device, DigitalInputsDriverCfg::MAX22190RegisterType::kNop, nop_reg_addr, _transceiver),
configurator(_configuration),
refresher()
{
register_map[0] = &wb_reg;
register_map[1] = &di_reg;
register_map[2] = &fault1_reg;
register_map[3] = &flt1_reg;
register_map[4] = &flt2_reg;
register_map[5] = &flt3_reg;
register_map[6] = &flt4_reg;
register_map[7] = &flt5_reg;
register_map[8] = &flt6_reg;
register_map[9] = &flt7_reg;
register_map[10]= &flt8_reg;
register_map[11]= &cfg_reg;
register_map[12]= &inen_reg;
register_map[13]= &fault2_reg;
register_map[14]= &fault2en_reg;
register_map[15]= &gpo_reg;
register_map[16]= &fault1en_reg;
register_map[17]= &nop_reg;
device = _device;
device_ready = false;
device_configured = false;
read_faults = false;
configuration = _configuration;
state_config = ConfigurationState::kConfigInEnReg;
state_refresh = RefreshState::kRefreshDiReg;
transceiver = _transceiver;
}
void MAX22190::initialize(void){
transceiver->registerListener(this);
device_ready = true;
}
void MAX22190::update(void)
{
if(device_ready){
if(!device_configured){
device_configured = configure();
}else{
refresh();
}
}
}
bool MAX22190::isReady(void)
{
return (device_ready && device_configured);
}
bool MAX22190::isInputActive(DigitalInputsDriverCfg::Input input)
{
uint8_t reg_data = di_reg.getData();
return ((reg_data & (1 << static_cast(input))) != 0);
}
bool MAX22190::isFault1Active(Fault1 fault)
{
uint8_t reg_data = fault1_reg.getData();
return ((reg_data & (1 << static_cast(fault))) != 0);
}
bool MAX22190::isFault2Active(Fault2 fault)
{
uint8_t reg_data = fault2_reg.getData();
return ((reg_data & (1 << static_cast(fault))) != 0);
}
void MAX22190::handleFaultPinActivation(void)
{
read_faults = true;
}
void MAX22190::activateLatch(void){}
void MAX22190::notifyEndOfTransaction(void){
for(Register* reg : register_map){
if(reg->isPending()){
reg->handleEndOfTransaction();
break;
}
}
}
uint8_t MAX22190::getDeviceId(void){
return static_cast(device);
}
bool MAX22190::configure(void)
{
bool configuration_finished = false;
switch(state_config){
case ConfigurationState::kConfigInEnReg:
configureInEnReg();
break;
case ConfigurationState::kConfigFlt1Reg:
configureFlt1Reg();
break;
case ConfigurationState::kConfigFlt2Reg:
configureFlt2Reg();
break;
case ConfigurationState::kConfigFlt3Reg:
configureFlt3Reg();
break;
case ConfigurationState::kConfigFlt4Reg:
configureFlt4Reg();
break;
case ConfigurationState::kConfigFlt5Reg:
configureFlt5Reg();
break;
case ConfigurationState::kConfigFlt6Reg:
configureFlt6Reg();
break;
case ConfigurationState::kConfigFlt7Reg:
configureFlt7Reg();
break;
case ConfigurationState::kConfigFlt8Reg:
configureFlt8Reg();
break;
case ConfigurationState::kConfigFault2EnReg:
configureFault2EnReg();
break;
case ConfigurationState::kConfigFault1EnReg:
configureFault1EnReg();
break;
case ConfigurationState::kConfigCfgReg:
configureCfgReg();
break;
case ConfigurationState::kConfigGpoReg:
configureGpoReg();
break;
case ConfigurationState::kConfigurationEnd:
configuration_finished = true;
break;
}
return configuration_finished;
}
void MAX22190::refresh(void)
{
switch(state_refresh){
case RefreshState::kRefreshDiReg:
refreshDiReg();
break;
case RefreshState::kRefreshWbReg:
refreshWbReg();
break;
case RefreshState::kRefreshFault1Reg:
refreshFault1Reg();
break;
case RefreshState::kRefreshFault2Reg:
refreshFault2Reg();
break;
}
}
void MAX22190::configureInEnReg(void)
{
if(configurator.configure(inen_reg)){
state_config = ConfigurationState::kConfigFlt1Reg;
}
}
void MAX22190::configureFlt1Reg(void)
{
if(configurator.configure(flt1_reg)){
state_config = ConfigurationState::kConfigFlt2Reg;
}
}
void MAX22190::configureFlt2Reg(void)
{
if(configurator.configure(flt2_reg)){
state_config = ConfigurationState::kConfigFlt3Reg;
}
}
void MAX22190::configureFlt3Reg(void)
{
if(configurator.configure(flt3_reg)){
state_config = ConfigurationState::kConfigFlt4Reg;
}
}
void MAX22190::configureFlt4Reg(void)
{
if(configurator.configure(flt4_reg)){
state_config = ConfigurationState::kConfigFlt5Reg;
}
}
void MAX22190::configureFlt5Reg(void)
{
if(configurator.configure(flt5_reg)){
state_config = ConfigurationState::kConfigFlt6Reg;
}
}
void MAX22190::configureFlt6Reg(void)
{
if(configurator.configure(flt6_reg)){
state_config = ConfigurationState::kConfigFlt7Reg;
}
}
void MAX22190::configureFlt7Reg(void)
{
if(configurator.configure(flt7_reg)){
state_config = ConfigurationState::kConfigFlt8Reg;
}
}
void MAX22190::configureFlt8Reg(void)
{
if(configurator.configure(flt8_reg)){
state_config = ConfigurationState::kConfigFault2EnReg;
}
}
void MAX22190::configureFault2EnReg(void)
{
if(configurator.configure(fault2en_reg)){
state_config = ConfigurationState::kConfigFault1EnReg;
}
}
void MAX22190::configureFault1EnReg(void)
{
if(configurator.configure(fault1en_reg)){
state_config = ConfigurationState::kConfigCfgReg;
}
}
void MAX22190::configureCfgReg(void)
{
if(configurator.configure(cfg_reg)){
state_config = ConfigurationState::kConfigGpoReg;
}
}
void MAX22190::configureGpoReg(void)
{
if(configurator.configure(gpo_reg)){
state_config = ConfigurationState::kConfigurationEnd;
}
}
void MAX22190::refreshDiReg(void)
{
if(refresher.refresh(di_reg)){
state_refresh = RefreshState::kRefreshWbReg;
}
}
void MAX22190::refreshWbReg(void)
{
if(refresher.refresh(wb_reg)){
if(read_faults) {
state_refresh = RefreshState::kRefreshFault1Reg;
}else{
state_refresh = RefreshState::kRefreshDiReg;
}
}
}
void MAX22190::refreshFault1Reg(void)
{
if(refresher.refresh(fault1_reg)){
state_refresh = RefreshState::kRefreshFault2Reg;
}
}
void MAX22190::refreshFault2Reg(void)
{
if(refresher.refresh(fault2_reg)){
state_refresh = RefreshState::kRefreshDiReg;
read_faults = false;
}
}注册
#include "DigitalInputsDriverCfg.h"
#include "Transceiver.h"
#include "Message.h"
#include "WriteRegRequestMsg.h"
#include "WriteRegResponseMsg.h"
#include "ReadRegRequestMsg.h"
#include "ReadRegResponseMsg.h"
#include
class Register
{
public:
Register(DigitalInputsDriverCfg::Device _device,
DigitalInputsDriverCfg::MAX22190RegisterType _type, uint8_t _address, Transceiver *_transceiver);
bool read(void);
bool write(uint8_t data);
bool isConfigured(void);
void setConfigured(void);
bool isRefreshed(void);
void setUnRefreshed(void);
uint8_t getData(void);
uint8_t getAddress(void);
DigitalInputsDriverCfg::MAX22190RegisterType getType(void);
DigitalInputsDriverCfg::Device getDevice(void);
bool isPending(void);
void handleEndOfTransaction(void);
private:
DigitalInputsDriverCfg::Device device;
DigitalInputsDriverCfg::MAX22190RegisterType type;
uint8_t address;
uint8_t data;
bool configured;
bool pending;
bool refreshed;
Message::MessageType sent_msg;
Transceiver *transceiver;
WriteRegRequestMsg write_reg_request;
ReadRegRequestMsg read_reg_request;
WriteRegResponseMsg write_reg_response;
ReadRegResponseMsg read_reg_response;
void setData(uint8_t data);
void handleWriteRegResponseMsg(void);
void handleReadRegResponseMsg(void);
};
#include
#include "Register.h"
#include "Bits.h"
Register::Register(DigitalInputsDriverCfg::Device _device,
DigitalInputsDriverCfg::MAX22190RegisterType _type, uint8_t _address,
Transceiver *_transceiver)
{
type = _type;
address = _address;
device = _device;
configured = false;
refreshed = false;
pending = false;
transceiver = _transceiver;
}
bool Register::read(void)
{
if (!transceiver->isBusy()){
new (&read_reg_request)
ReadRegRequestMsg(device, address, transceiver);
read_reg_request.write();
sent_msg = Message::MessageType::kReadRegRequest;
pending = true;
return true;
}else{
return false;
}
}
bool Register::write(uint8_t data)
{
if(!transceiver->isBusy()){
new (&write_reg_request)
WriteRegRequestMsg(device, address, data, transceiver);
write_reg_request.write();
sent_msg = Message::MessageType::kWriteRegRequest;
pending = true;
return true;
}else{
return false;
}
}
bool Register::isConfigured(void)
{
return configured;
}
void Register::setConfigured(void)
{
configured = true;
}
bool Register::isRefreshed(void)
{
return (refreshed != false);
}
void Register::setUnRefreshed(void)
{
refreshed = false;
}
uint8_t Register::getData(void) {
return data;
}
uint8_t Register::getAddress(void) {
return address;
}
DigitalInputsDriverCfg::MAX22190RegisterType Register::getType(void)
{
return type;
}
DigitalInputsDriverCfg::Device Register::getDevice(void)
{
return device;
}
bool Register::isPending(void)
{
return pending;
}
void Register::handleEndOfTransaction(void)
{
switch(sent_msg){
case Message::MessageType::kWriteRegRequest:
handleWriteRegResponseMsg();
break;
case Message::MessageType::kReadRegRequest:
handleReadRegResponseMsg();
break;
case Message::MessageType::kWriteRegResponse:
break;
case Message::MessageType::kReadRegResponse:
break;
}
}
void Register::setData(uint8_t read_data)
{
data = read_data;
}
void Register::handleWriteRegResponseMsg(void)
{
pending = false;
new (&write_reg_response) WriteRegResponseMsg(transceiver);
write_reg_response.read();
}
void Register::handleReadRegResponseMsg(void)
{
uint8_t read_data;
pending = false;
new (&read_reg_response) ReadRegResponseMsg(transceiver);
read_reg_response.read();
if(read_reg_response.isValid()){
read_data = read_reg_response.getRegisterData();
setData(read_data);
refreshed = true;
}
}配置器
#include "DigitalInputsDriverCfg.h"
#include "Register.h"
class Configurator
{
public:
Configurator(DigitalInputsDriverCfg *_configuration);
bool configure(Register ®);
private:
enum class State {kInit, kWrite, kRead, kCheck};
State state;
DigitalInputsDriverCfg *configuration;
uint8_t data;
};
#include "Configurator.h"
Configurator::Configurator(DigitalInputsDriverCfg *_configuration)
{
configuration = _configuration;
state = State::kInit;
}
bool Configurator::configure(Register ®)
{
bool reg_configured = false;
switch(state){
case State::kInit:
data =
configuration->getRegisterConfigData(reg.getDevice(), reg.getType());
state = State::kWrite;
break;
case State::kWrite:
if(reg.write(data)){
state = State::kRead;
}
break;
case State::kRead:
if(reg.read()){
state = State::kCheck;
}
break;
case State::kCheck:
if(!reg.isPending()){
if(data == reg.getData()){
reg_configured = true;
reg.setConfigured();
state = State::kInit;
}else{
state = State::kWrite;
}
}
break;
}
return reg_configured;
}刷新
#include "Register.h"
class Refresher
{
public:
Refresher();
bool refresh(Register ®);
private:
enum class State {kRead, kCheck};
State state;
};
#include "Refresher.h"
Refresher::Refresher()
{
state = State::kRead;
}
bool Refresher::refresh(Register ®)
{
bool reg_refreshed = false;
switch(state){
case State::kRead:
if(reg.read()){
reg.setUnRefreshed();
state = State::kCheck;
}
break;
case State::kCheck:
if(!reg.isPending()){
if(reg.isRefreshed()){
reg_refreshed = true;
}
state = State::kRead;
}
break;
}
return reg_refreshed;
}消息
class Message
{
public:
enum class MessageType
{
kWriteRegRequest,
kReadRegRequest,
kWriteRegResponse,
kReadRegResponse
};
virtual void read(void) = 0;
virtual void write(void) = 0;
};<#>写入WriteRegRequest
#include "Message.h"
#include "DigitalInputsDriverCfg.h"
#include "Transceiver.h"
class WriteRegRequestMsg : public Message
{
public:
WriteRegRequestMsg();
WriteRegRequestMsg(DigitalInputsDriverCfg::Device _device, uint8_t _address,
uint8_t _data, Transceiver *_transceiver);
void read(void);
void write(void);
private:
union MsgData{
struct
{
uint32_t crc : 5;
uint32_t fill : 3;
uint32_t data : 8;
uint32_t reg_addr : 7;
uint32_t msb : 1;
}bits;
uint8_t bytes[3];
};
DigitalInputsDriverCfg::Device device;
uint8_t address;
uint8_t data;
MsgData msg;
uint8_t length;
Transceiver *transceiver;
};
#include "WriteRegRequestMsg.h"
WriteRegRequestMsg::WriteRegRequestMsg(){}
WriteRegRequestMsg::WriteRegRequestMsg(
DigitalInputsDriverCfg::Device _device, uint8_t _address, uint8_t _data,
Transceiver *_transceiver)
{
device = _device;
address = _address;
data = _data;
transceiver = _transceiver;
}
void WriteRegRequestMsg::read(void){}
void WriteRegRequestMsg::write(void)
{
msg.bits.msb = 1;
msg.bits.reg_addr = (address & 0x7F);
msg.bits.data = data;
msg.bits.fill = 0;
uint8_t crc = crcMAX22190(msg.bytes[2], msg.bytes[1], msg.bytes[0]);
msg.bits.crc = crc;
transceiver->putBytes(msg.bytes);
transceiver->startTransaction(device);
}ReadRegRequest
#include "Message.h"
#include "DigitalInputsDriverCfg.h"
#include "Transceiver.h"
class ReadRegRequestMsg : public Message
{
public:
ReadRegRequestMsg();
ReadRegRequestMsg(DigitalInputsDriverCfg::Device _device, uint8_t _address, Transceiver *_transceiver);
void read(void);
void write(void);
private:
union MsgData{
struct
{
uint32_t crc : 5;
uint32_t fill : 11;
uint32_t reg_addr : 7;
uint32_t msb : 1;
}bits;
uint8_t bytes[3];
};
DigitalInputsDriverCfg::Device device;
uint8_t address;
MsgData msg;
Transceiver *transceiver;
};
#include "ReadRegRequestMsg.h"
ReadRegRequestMsg::ReadRegRequestMsg(){}
ReadRegRequestMsg::ReadRegRequestMsg(DigitalInputsDriverCfg::Device _device,
uint8_t _address,
Transceiver *_transceiver)
{
device = _device;
address = _address;
transceiver = _transceiver;
}
void ReadRegRequestMsg::read(void){}
void ReadRegRequestMsg::write(void)
{
msg.bits.msb = 0;
msg.bits.reg_addr = address;
msg.bits.fill = 0;
uint8_t crc = crcMAX22190(msg.bytes[2], msg.bytes[1], msg.bytes[0]);
msg.bits.crc = crc;
transceiver->putBytes(msg.bytes);
transceiver->startTransaction(device);
}写入WriteRegResponse
#include "Message.h"
#include "Transceiver.h"
class WriteRegResponseMsg : public Message
{
public:
WriteRegResponseMsg();
WriteRegResponseMsg(Transceiver *_transceiver);
void read(void);
void write(void);
bool isValid(void);
uint32_t getData(void);
private:
union MsgData{
struct
{
uint32_t crc : 5;
uint32_t flags : 3;
uint32_t wb_reg_state : 8;
uint32_t inputs_state : 8;
}bits;
uint8_t bytes[3];
};
MsgData msg;
Transceiver *transceiver;
};
#include "WriteRegResponseMsg.h"
WriteRegResponseMsg::WriteRegResponseMsg(){}
WriteRegResponseMsg::WriteRegResponseMsg(Transceiver *_transceiver)
{
transceiver = _transceiver;
}
void WriteRegResponseMsg::read(void)
{
transceiver->getBytes(msg.bytes);
}
void WriteRegResponseMsg::write(void){}
bool WriteRegResponseMsg::isValid(void)
{
uint8_t crc = crcMAX22190(msg.bytes[2], msg.bytes[1], msg.bytes[0]);
if(crc == 0){
return true;
}else{
return false;
}
}
uint32_t WriteRegResponseMsg::getData(void)
{
uint32_t data = 0;
data = ((static_cast(msg.bytes[0]) << 16) |
(static_cast(msg.bytes[1]) << 8) |
(static_cast(msg.bytes[2]) & 0xE0));
return data;
}<#>ReadRegResponse
#include "Message.h"
#include "Transceiver.h"
class ReadRegResponseMsg : public Message
{
public:
ReadRegResponseMsg();
ReadRegResponseMsg(Transceiver *_transceiver);
void read(void);
void write(void);
bool isValid(void);
uint32_t getData(void);
uint8_t getRegisterData(void);
private:
union MsgData{
struct
{
uint32_t crc : 5;
uint32_t flags : 3;
uint32_t reg_state : 8;
uint32_t inputs_state : 8;
}bits;
uint8_t bytes[3];
};
MsgData msg;
Transceiver *transceiver;
};
#include "ReadRegResponseMsg.h"
ReadRegResponseMsg::ReadRegResponseMsg() {}
ReadRegResponseMsg::ReadRegResponseMsg(Transceiver *_transceiver)
{
transceiver = _transceiver;
}
void ReadRegResponseMsg::read(void)
{
transceiver->getBytes(msg.bytes);
}
void ReadRegResponseMsg::write(void){}
bool ReadRegResponseMsg::isValid(void)
{
uint8_t crc = crcMAX22190(msg.bytes[2], msg.bytes[1], msg.bytes[0]);
if(crc == 0){
return true;
}else{
return false;
}
}
uint32_t ReadRegResponseMsg::getData(void)
{
uint32_t data = 0;
data = ((static_cast(msg.bytes[0]) << 16) |
(static_cast(msg.bytes[1]) << 8) |
(static_cast(msg.bytes[2]) & 0xE0));
return data;
}
uint8_t ReadRegResponseMsg::getRegisterData(void)
{
return msg.bytes[1];
}数字输入驱动
#include
class DigitalInputsDriverCfg
{
public:
enum class Device {
kMAX22190Device_0,
kMAX22190Device_1,
kNoMAX22190Devices
};
enum class Input{
kInput_01,
kInput_02,
kInput_03,
kInput_04,
kInput_05,
kInput_06,
kInput_07,
kInput_08,
kNoInputs
};
enum class MAX22190RegisterType{
kWb,
kDi,
kFault1,
kFlt1,
kFlt2,
kFlt3,
kFlt4,
kFlt5,
kFlt6,
kFlt7,
kFlt8,
kCfg,
kInEn,
kFault2,
kFault2En,
kGpo,
kFault1En,
kNop
};
enum class WireBreakDetection{
kWireBreakDetectionDisabled,
kWireBreakDetectionEnabled
};
enum class ProgrammableFilter{
kProgrammableFilterUsed,
kProgrammableFilterBypassed
};
enum class FilterDelay{
kInputFilterDelay50us,
kInputFilterDelay100us,
kInputFilterDelay400us,
kInputFilterDelay800us,
kInputFilterDelay1_6ms,
kInputFilterDelay3_2ms,
kInputFilterDelay12_8ms,
kInputFilterDelay20ms
};
enum class Flags24VClearMethod{
k24VFlagClearedBySpiTransactionFault1RegReading,
k24VFlagClearedByFault1RegReading
};
enum class FiltersOperation{
kFiltersOperationNormal,
kFiltersOperationFixed
};
enum class ShortCircuitDetection{
kShortCircuitDetectionDisabled,
kShortCircuitDetectionEnabled
};
enum class InputEnable{kInputDisabled, kInputEnabled};
enum class Fault2SrcInFault1Reg{
kFault8CkeInFault1Reg,
kOtShdnInFault1Reg,
kPinREFDIOpenInFault1Reg,
kPinREFDIShortInFault1Reg,
kPinREFWBOpenInFault1Reg,
kPinREFWBShortInFault1Reg,
kNoFault2Src
};
enum class Fault2SrcUsage{kFault2SrcNotUsed, kFault2SrcUsed};
struct Fault2BitInFault1RegCfg
{
Fault2SrcInFault1Reg fault2;
Fault2SrcUsage usage;
};
enum class FaultPinCfg{kFaultPinNotSticky, kFaultPinSticky};
enum class FaultPinActivationSrc{
kFaultPinActivationCrc,
kFaultPinActivationPor,
kFaultPinActivationFault2,
kFaultPinActivationAlarmT2,
kFaultPinActivationAlarmT1,
kFaultPinActivation24VL,
kFaultPinActivation24VM,
kFaultPinActivationWireBreak,
kNoFaultPinActivationSrc
};
enum class FaultPinActivationSrcUsage{kNotUsed, kUsed};
struct FaultPinActivationCfg
{
FaultPinActivationSrc src;
FaultPinActivationSrcUsage usage;
};
struct InputCfg
{
Input input;
InputEnable input_enable;
WireBreakDetection wire_break_detection_enable;
ProgrammableFilter filter_enable;
FilterDelay filter_delay;
};
struct MAX22190Config
{
Device device;
InputCfg inputs_cfg[static_cast(Input::kNoInputs)];
Flags24VClearMethod flags_clear_method;
FiltersOperation filters_operation;
ShortCircuitDetection short_circuit_detection;
Fault2BitInFault1RegCfg fault2_src_cfg[static_cast(
Fault2SrcInFault1Reg::kNoFault2Src)];
FaultPinCfg fault_pin_cfg;
FaultPinActivationCfg fault_pin_activation_cfg[static_cast(
FaultPinActivationSrc::kNoFaultPinActivationSrc)];
};
DigitalInputsDriverCfg(const MAX22190Config *_configuration);
uint8_t getRegisterConfigData(Device device, MAX22190RegisterType reg);
private:
union Fault1RegBitMap{
struct
{
uint32_t wbg_bit : 1;
uint32_t _24vm_bit : 1;
uint32_t _24vl_bit : 1;
uint32_t alarmt1_bit : 1;
uint32_t alarmt2_bit : 1;
uint32_t fault2_bit : 1;
uint32_t por_bit : 1;
uint32_t crc_bit : 1;
}bits;
uint8_t byte;
};
union FltxRegBitMap{
struct
{
uint32_t delay : 3;
uint32_t fbp_bit : 1;
uint32_t wbe_bit : 1;
uint32_t reserve : 3;
}bits;
uint8_t byte;
};
union CfgRegBitMap{
struct
{
uint32_t refdi_sh_ena_bit : 1;
uint32_t reserve_01 : 2;
uint32_t clrf_bit : 1;
uint32_t _24vf_bit : 1;
uint32_t reserve_02 : 3;
}bits;
uint8_t byte;
};
union Fault2RegBitMap{
struct
{
uint32_t rfwbs_bit : 1;
uint32_t rfwbo_bit : 1;
uint32_t rfdis_bit : 1;
uint32_t rfdio_bit : 1;
uint32_t otshdn_bit : 1;
uint32_t fault8ck_bit : 1;
uint32_t reserve : 2;
}bits;
uint8_t byte;
};
union Fault2EnRegBitMap{
struct
{
uint32_t rfwbse_bit : 1;
uint32_t rfwboe_bit : 1;
uint32_t rfdise_bit : 1;
uint32_t rfdioe_bit : 1;
uint32_t otshdne_bit : 1;
uint32_t fault8cke_bit : 1;
uint32_t reserve : 2;
}bits;
uint8_t byte;
};
union GpoRegBitMap{
struct
{
uint32_t reserve : 7;
uint32_t stk_bit : 1;
}bits;
uint8_t byte;
};
union Fault1EnRegBitMap{
struct
{
uint32_t wbge_bit : 1;
uint32_t _24vme_bit : 1;
uint32_t _24vle_bit : 1;
uint32_t alarmt1e_bit : 1;
uint32_t alarmt2e_bit : 1;
uint32_t fault2e_bit : 1;
uint32_t pore_bit : 1;
uint32_t crce_bit : 1;
}bits;
uint8_t byte;
};
const MAX22190Config *configuration;
uint8_t readInEnRegCfgData(Device device);
uint8_t readFltxRegCfgData(Device device, Input input);
uint8_t readFault2EnRegCfgData(Device device);
uint8_t readFault1EnRegCfgData(Device device);
uint8_t readCfgRegCfgData(Device device);
uint8_t readGpoRegCfgData(Device device);
};
#include "DigitalInputsDriverCfg.h"
DigitalInputsDriverCfg::DigitalInputsDriverCfg(const MAX22190Config* _configuration)
{
configuration = _configuration;
}
uint8_t DigitalInputsDriverCfg::getRegisterConfigData(Device device, MAX22190RegisterType reg)
{
uint8_t data;
switch(reg)
{
case MAX22190RegisterType::kWb:
data = 0;
break;
case MAX22190RegisterType::kDi:
data = 0;
break;
case MAX22190RegisterType::kFault1:
data = 0;
break;
case MAX22190RegisterType::kFlt1:
data = readFltxRegCfgData(device, Input::kInput_01);
break;
case MAX22190RegisterType::kFlt2:
data = readFltxRegCfgData(device, Input::kInput_02);
break;
case MAX22190RegisterType::kFlt3:
data = readFltxRegCfgData(device, Input::kInput_03);
break;
case MAX22190RegisterType::kFlt4:
data = readFltxRegCfgData(device, Input::kInput_04);
break;
case MAX22190RegisterType::kFlt5:
data = readFltxRegCfgData(device, Input::kInput_05);
break;
case MAX22190RegisterType::kFlt6:
data = readFltxRegCfgData(device, Input::kInput_06);
break;
case MAX22190RegisterType::kFlt7:
data = readFltxRegCfgData(device, Input::kInput_07);
break;
case MAX22190RegisterType::kFlt8:
data = readFltxRegCfgData(device, Input::kInput_08);
break;
case MAX22190RegisterType::kCfg:
data = readCfgRegCfgData(device);
break;
case MAX22190RegisterType::kInEn:
data = readInEnRegCfgData(device);
break;
case MAX22190RegisterType::kFault2:
data = 0;
break;
case MAX22190RegisterType::kFault2En:
data = readFault2EnRegCfgData(device);
break;
case MAX22190RegisterType::kGpo:
data = readGpoRegCfgData(device);
break;
case MAX22190RegisterType::kFault1En:
data = readFault1EnRegCfgData(device);
break;
case MAX22190RegisterType::kNop:
data = 0;
break;
}
return data;
}
uint8_t DigitalInputsDriverCfg::readInEnRegCfgData(Device device)
{
uint8_t reg_data = 0;
for(uint8_t cur_input = 0;
cur_input < static_cast(Input::kNoInputs);
cur_input++){
if(configuration[static_cast(device)]
.inputs_cfg[cur_input]
.input_enable == InputEnable::kInputEnabled){
reg_data |= (1 << cur_input);
}
}
return reg_data;
}
uint8_t DigitalInputsDriverCfg::readFltxRegCfgData(Device device, Input input)
{
FltxRegBitMap reg_data;
reg_data.byte = 0;
if(configuration[static_cast(device)]
.inputs_cfg[static_cast(input)]
.wire_break_detection_enable ==
WireBreakDetection::kWireBreakDetectionEnabled){
reg_data.bits.wbe_bit = 1;
}
if(configuration[static_cast(device)]
.inputs_cfg[static_cast(input)]
.filter_enable ==
ProgrammableFilter::kProgrammableFilterBypassed){
reg_data.bits.fbp_bit = 1;
}
reg_data.bits.delay =
static_cast(configuration[static_cast(device)]
.inputs_cfg[static_cast(input)]
.filter_delay);
return reg_data.byte;
}
uint8_t DigitalInputsDriverCfg::readFault2EnRegCfgData(Device device)
{
Fault2EnRegBitMap reg_data;
reg_data.byte = 0;
for(uint8_t cur_record = 0;
cur_record < static_cast(
Fault2SrcInFault1Reg::kNoFault2Src);
cur_record++){
switch (configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.fault2){
case Fault2SrcInFault1Reg::kFault8CkeInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.fault8cke_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kOtShdnInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.otshdne_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFDIOpenInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfdioe_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFDIShortInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfdise_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFWBOpenInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfwboe_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFWBShortInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfwbse_bit = 1;
}
break;
}
}
return reg_data.byte;
}
uint8_t DigitalInputsDriverCfg::readFault1EnRegCfgData(Device device)
{
Fault1EnRegBitMap reg_data;
reg_data.byte = 0;
for(uint8_t cur_record = 0;
cur_record <
static_cast(
FaultPinActivationSrc::kNoFaultPinActivationSrc);
cur_record++){
switch(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.src){
case FaultPinActivationSrc::kFaultPinActivationCrc:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits.crce_bit = 1;
}
break;
case FaultPinActivationSrc::kFaultPinActivationPor:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits.pore_bit = 1;
}
break;
case FaultPinActivationSrc::kFaultPinActivationFault2:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits.fault2e_bit = 1;
}
break;
case FaultPinActivationSrc::kFaultPinActivationAlarmT2:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits.alarmt2e_bit = 1;
}
break;
case FaultPinActivationSrc::kFaultPinActivationAlarmT1:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits.alarmt1e_bit = 1;
}
break;
case FaultPinActivationSrc::kFaultPinActivation24VL:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits._24vle_bit = 1;
}
break;
case FaultPinActivationSrc::kFaultPinActivation24VM:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits._24vme_bit = 1;
}
break;
case FaultPinActivationSrc::
kFaultPinActivationWireBreak:
if(configuration[static_cast(device)]
.fault_pin_activation_cfg[cur_record]
.usage == FaultPinActivationSrcUsage::kUsed){
reg_data.bits.wbge_bit = 1;
}
break;
}
}
return reg_data.byte;
}
uint8_t DigitalInputsDriverCfg::readCfgRegCfgData(Device device)
{
CfgRegBitMap reg_data;
reg_data.byte = 0;
if(configuration[static_cast(device)].short_circuit_detection ==
ShortCircuitDetection::kShortCircuitDetectionEnabled){
reg_data.bits.refdi_sh_ena_bit = 1;
}
if(configuration[static_cast(device)].filters_operation ==
FiltersOperation::kFiltersOperationFixed){
reg_data.bits.clrf_bit = 1;
}
if(configuration[static_cast(device)].flags_clear_method ==
Flags24VClearMethod::
k24VFlagClearedByFault1RegReading){
reg_data.bits._24vf_bit = 1;
}
return reg_data.byte;
}
uint8_t DigitalInputsDriverCfg::readGpoRegCfgData(Device device)
{
GpoRegBitMap reg_data;
reg_data.byte = 0;
if(configuration[static_cast(device)].fault_pin_cfg ==
FaultPinCfg::kFaultPinSticky){
reg_data.bits.stk_bit = 1;
}
return reg_data.byte;
}驱动程序的预期用途如下:
FpgaDriversCfg结构中。DigitalInputsDriver的实例与“容器”Hal中其他驱动程序的实例一起使用。FpgaDriversCfg
#include "DigitalInputsDriverCfg.h"
struct FpgaDriversCfg
{
DigitalInputsDriverCfg::MAX22190Config di_devices_cfg[static_cast(
DigitalInputsDriverCfg::Device::kNoMAX22190Devices)]={
{DigitalInputsDriverCfg::Device::kMAX22190Device_0,
{{DigitalInputsDriverCfg::Input::kInput_01,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_02,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_03,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_04,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_05,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_06,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_07,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_08,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms}},
DigitalInputsDriverCfg::Flags24VClearMethod::
k24VFlagClearedBySpiTransactionFault1RegReading,
DigitalInputsDriverCfg::FiltersOperation::kFiltersOperationNormal,
DigitalInputsDriverCfg::ShortCircuitDetection::kShortCircuitDetectionEnabled,
{{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kFault8CkeInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kOtShdnInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFDIOpenInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFDIShortInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFWBOpenInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFWBShortInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed}},
DigitalInputsDriverCfg::FaultPinCfg::kFaultPinSticky,
{{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationCrc,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationPor,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationFault2,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationAlarmT2,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationAlarmT1,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivation24VL,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivation24VM,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationWireBreak,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed}}},
{DigitalInputsDriverCfg::Device::kMAX22190Device_1,
{{DigitalInputsDriverCfg::Input::kInput_01,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_02,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_03,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_04,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_05,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_06,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_07,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms},
{DigitalInputsDriverCfg::Input::kInput_08,
DigitalInputsDriverCfg::InputEnable::kInputEnabled,
DigitalInputsDriverCfg::WireBreakDetection::kWireBreakDetectionEnabled,
DigitalInputsDriverCfg::ProgrammableFilter::kProgrammableFilterUsed,
DigitalInputsDriverCfg::FilterDelay::kInputFilterDelay20ms}},
DigitalInputsDriverCfg::Flags24VClearMethod::
k24VFlagClearedBySpiTransactionFault1RegReading,
DigitalInputsDriverCfg::FiltersOperation::kFiltersOperationNormal,
DigitalInputsDriverCfg::ShortCircuitDetection::kShortCircuitDetectionEnabled,
{{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kFault8CkeInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kOtShdnInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFDIOpenInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFDIShortInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFWBOpenInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed},
{DigitalInputsDriverCfg::Fault2SrcInFault1Reg::kPinREFWBShortInFault1Reg,
DigitalInputsDriverCfg::Fault2SrcUsage::kFault2SrcUsed}},
DigitalInputsDriverCfg::FaultPinCfg::kFaultPinSticky,
{{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationCrc,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationPor,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationFault2,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationAlarmT2,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationAlarmT1,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivation24VL,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivation24VM,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed},
{DigitalInputsDriverCfg::FaultPinActivationSrc::kFaultPinActivationWireBreak,
DigitalInputsDriverCfg::FaultPinActivationSrcUsage::kUsed}}}};
DigitalInputsDriverCfg dig_inputs_cfg;
FpgaDriversCfg():dig_inputs_cfg(di_devices_cfg){}
};哈尔
#include "FpgaDriversCfg.h"
#include "DigitalInputsDriver.h"
class Hal{
public:
DigitalInputsDriver dig_in;
Hal();
void initialize(void);
private:
FpgaDriversCfg fpga_configuration;
};
#include "Hal.h"
#include "FpgaDriversCfg.h"
#include "Registers.h"
Hal::Hal():
dig_in(&(fpga_configuration.dig_inputs_cfg), 1){}
void Hal::initialize(void){
dig_in.initialize();
}<#>主要
#include
#include "Hal.h"
int main(int argc, char** argv){
Hal hal;
hal.initialize();
while(1){
hal.dig_in.update();
// the methods getInputState, isFault1Active, isFault2Active are intended to be called from
// different tasks of the RTOS
}
}我想主要询问您对整个驱动程序设计的评估,即驱动程序是如何划分为C++类的,以及这些类是如何交互的。此外,我一直在考虑使用某种设计模式来处理Register对象的可能性。事先谢谢您的留言。
发布于 2020-12-12 22:15:42
我在您的代码中没有看到任何包括警卫。将这些文件添加到头文件是常见的做法;这允许它们依赖于其他头文件,而不必担心循环和重复。最简单的解决方案是将以下内容添加到每个头文件的顶部:
#pragma once大多数编译器都支持这一点,但是它不是标准的C++。符合标准的方法是编写如下所示的头文件:
#ifndef HEADERFILENAME_H
#define HEADERFILENAME_H
// Contents of header file come here
...
#endif但是,您需要将HEADERFILENAME替换为每个头文件的唯一文件,通常头文件的文件名用于此。
enums原则上,常量使用enum class可以提供极好的类型安全性,但是也有一些缺点,特别是需要在需要获得它们的整数值时对它们进行转换。我会继续使用enum classes来处理对于每个可能值都有不同名称的东西,比如故障代码。但是,如果您只打算给出与其值一一对应的引号名称,我就不会将它们用于引号,如:
enum class Input {
kDi_00,
kDi_01,
...
};另外,我看到您在所有枚举名称前加上了一个k。这可能是从使用匈牙利符号的编码样式中遗留下来的,但是由于您不使用匈牙利符号,所以它没有多大意义。我会删除ks,他们只是添加可见噪音,不做任何事情来使代码更安全。
启动标识符
有一定的关于在标识符中使用下划线的规则。特别是,从下划线开始或使用双下划线在某些情况下是保留的。根据这些规则,您的使用是可以的,但是如果您一开始不知道这一点,我建议您不要以下划线开头任何名称。我看到你总是在构造函数中使用这些,但是它们几乎是不必要的。只有当您要隐藏一个成员变量并同时访问主体中的成员变量和参数时,您才需要它们。但是,请注意,如果只在构造函数的初始化程序列表中使用成员变量,则可以使用相同的名称,如下所示:
Register::Register(DigitalInputsDriverCfg::Device device,
DigitalInputsDriverCfg::MAX22190RegisterType type, uint8_t address,
Transceiver *transceiver) :
device{device},
type{type},
address{address},
transceiver{transceiver},
{...} DigitalInputsDriver中的指针数组
不需要同时拥有device0、device1和数组devices[]。我认为您之所以这样做是因为您希望能够在构造函数的初始化程序列表中初始化device0和device1,但希望能够作为数组访问它们。但是,您可以删除冗余,并从这两个世界中获得最佳效果,具体如下所示:
class DigitalInputsDriver
{
...
MAX22190 devices[2];
};
DigitalInputsDriver::DigitalInputsDriver(DigitalInputsDriverCfg *dig_in_cfg, uint16_t spi_device_id) :
transceiver{spi_device_id},
devices{
{DigitalInputsDriverCfg::Device::kMAX22190Device_0, dig_in_cfg, &transceiver},
{DigitalInputsDriverCfg::Device::kMAX22190Device_1, dig_in_cfg, &transceiver},
}
{} 您必须更新所有使用devices[]的代码,因为它不再包含指针,而是包含值,例如:
void DigitalInputsDriver::update(void)
{
for (MAX22190 &device : devices) {
device.update();
}
}const不像成员变量那样修改状态的函数应该标记为const,这样编译器就可以生成更好的代码。如果您不小心从const函数写入一个成员变量,它还会使编译器生成一个错误。例如:
class MAX22190 : public TransactionEndListener
{
...
bool isReady(void) const;
...
};
bool MAX22190::isReady(void) const
{
return device_ready && device_configured;
}中初始化成员变量
与在构造函数中初始化成员变量不同,有时还可以在声明成员变量的位置初始化它们。例如:
class Register
{
...
bool configured = false; // or bool configured{false}; or bool configured{};
bool pending = false;
bool refreshed = false;
...
};如果类中有多个构造函数,这尤其有用,因为这样可以避免大量重复。
new看到下面的代码,我感到有点惊讶:
bool Register::read(void)
{
if (!transceiver->isBusy()) {
new (&read_reg_request) ReadRegRequestMsg(device, address, transceiver);
...possible new是在非常罕见的情况下做的事情,在这种情况下,您要么希望避免默认构造,要么不可能进行副本分配。复制分配ReadRegRequestMsg是没有问题的,而且由于read_reg_request已经默认构造,因此这里没有性能改进。我将用以下代码替换这一行代码:
read_reg_request = ReadRegRequestMsg(device, address, transceiver);但是,在进一步检查后,为什么首先将请求存储在成员变量中?它不在Register::read()之外使用,所以它可能只是一个局部变量。但是,您所做的唯一的事情就是在上面调用write(),因此您甚至不需要将结果存储在局部变量中,只需编写:
bool Register::read(void)
{
if (!transceiver->isBusy()) {
ReadRegRequestMsg(device, address, transceiver).write();
...但接下来我要说的是:
为什么ReadRegRequestMsg是一个类,为什么它继承了class Message本身并没有做任何有用的事情,而您只需要将消息写入设备的函数呢?这可能是一个独立的功能:
void writeReadRegRequestMsg(DigitalInputsDriverCfg::Device device, uint8_t address, Transceiver *transceiver)
{
union {
struct
{
uint32_t crc : 5;
uint32_t fill : 11;
uint32_t reg_addr : 7;
uint32_t msb : 1;
} bits;
uint8_t bytes[3];
} msg;
msg.bits.msb = 0;
msg.bits.reg_addr = address;
msg.bits.fill = 0;
uint8_t crc = crcMAX22190(msg.bytes[2], msg.bytes[1], msg.bytes[0]);
msg.bits.crc = crc;
transceiver->putBytes(msg.bytes);
transceiver->startTransaction(device);
}或者更好的做法是让它成为Register的成员函数。
代码中有几个部分看起来很像for-case-loops,比如MAX22190::configure()、Configure::configure()和Refresher::refresh()。这是因为您已经将系统建模为状态机,并希望一步一步地推进状态吗?问题是,这使得代码流难以读取。我宁愿期待这样的事情:
bool MAX22190::configure(void)
{
for (auto reg: register_map) {
configurator.configure(*reg));
}
return true;
}然后,让configurator.configure()自己完成配置寄存器所需的所有步骤。
发布于 2020-12-12 21:58:41
从枚举开始--如果您要对每个枚举进行编号,请保持一致。就我个人而言,我不喜欢对它们进行编号,如果我有常量(作为来自I2C的返回,等等),那么这些常量就被调用为constexpr值。再说一次,这是你喜欢吃的问题,但你需要保持一致。
您的大多数for-循环都是自己关闭的,而且都是琐碎的--这非常好,使用STL将是过度的。然而,有几个地方的STL将是好的。
/// In particular this
bool DigitalInputsDriver::isReady(void)
{
bool retval = true;
for(MAX22190 *device : devices){
if(device->isReady() == false){
retval = false;
break;
}
}
return retval;
}
/// could be this
bool DigitalInputsDriver::isReady(void)
{
return std::all_of(begin(devices), end(devices), [](MAX22190 * device){
return device->isReady();
});
}突然之间,您的代码更能表达您想要实现的目标。
const和[[nodiscard]]类有很多函数,但我没有看到太多的const或[[nodiscard]]。如果函数不修改类,请确保它是const- -这特别适用于名为isReady或isConfigured的函数。按照同样的思路,如果您有一个返回值的函数,如果您不读取结果,它可能是一个错误;将它指示给编译器将有助于处理整个错误类。
初始化变量的值之前,不要声明变量
///In particular I'm looking at
uint32_t ReadRegResponseMsg::getData(void)
{
uint32_t data = 0;
data = ((static_cast(msg.bytes[0]) << 16) |
(static_cast(msg.bytes[1]) << 8) |
(static_cast(msg.bytes[2]) & 0xE0));
return data;
}
/// which could be
uint32_t ReadRegResponseMsg::getData(void)
{
return ((static_cast(msg.bytes[0]) << 16) |
(static_cast(msg.bytes[1]) << 8) |
(static_cast(msg.bytes[2]) & 0xE0));
}您不需要对data进行零初始化,您也可以直接返回而不是使用指定的变量。并不是每个编译器都会发现您覆盖了数据中的值,但是几乎每个编译器都会尝试这样做一些花哨的优化。儿童权利委员会的职能也是如此。
ReadReg和WriteReg看起来几乎相同,那么为什么不将其中的大部分压缩到一个源文件中呢?就像他们派生出来的消息类?
然后是digitalInputsDriverCfg,它
uint8_t DigitalInputsDriverCfg::readFault2EnRegCfgData(Device device)
{
Fault2EnRegBitMap reg_data;
reg_data.byte = 0;
for(uint8_t cur_record = 0;
cur_record < static_cast(
Fault2SrcInFault1Reg::kNoFault2Src);
cur_record++){
switch (configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.fault2){
case Fault2SrcInFault1Reg::kFault8CkeInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.fault8cke_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kOtShdnInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.otshdne_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFDIOpenInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfdioe_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFDIShortInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfdise_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFWBOpenInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfwboe_bit = 1;
}
break;
case Fault2SrcInFault1Reg::kPinREFWBShortInFault1Reg:
if(configuration[static_cast(device)]
.fault2_src_cfg[cur_record]
.usage == Fault2SrcUsage::kFault2SrcUsed){
reg_data.bits.rfwbse_bit = 1;
}
break;
}
}
return reg_data.byte;
}这是一个怪物的功能,当然可以转化为一个较小的功能。if语句条件的间接数量和行数似乎可疑。很容易创建一个助手函数来使其读起来非常简单。
的使用
你真的需要它吗?这是一个模糊的特性,而且看起来不像是将大多数地方的内容分配给一个专用地址。自动变量有什么问题?我知道嵌入式系统是内存敏感的,但通常placement new用于在特定的内存位置或内存池中设置变量。如果你两者都不做,为什么要把情况复杂化呢?
https://codereview.stackexchange.com/questions/253396
复制相似问题