1、通过sock通讯读取到PLC传到地址里面去的对应的数据
开一个线程不断刷新地址里的数据,把读到的数据全部保存进一个容器中
2、从地址里获取到的转化出来一般为有符号的整形
bool ModbusBase::getBit(const modbusCell& cell, bool & value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, true, false);
}
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
switch (cell.type_)
{
case ModbusDataType_Coils: //线圈----读写
case ModbusDataType_DiscreteInput: //离散量--只读
{
checkSpsce(space, cell.slave_, (cell.addr_ + 15) / 16);
value = (space->at(cell.slave_)[cell.addr_ / 16] & (0x0001 << cell.addr_ % 16)) > 0;
break;
}
case ModbusDataType_RegisterInput: //输入寄存器--只读
case ModbusDataType_RegisterHolding: //保持寄存器--读写
{
checkSpsce(space, cell.slave_, cell.addr_);
value = (space->at(cell.slave_)[cell.addr_] & (0x0001 << (cell.bitAddr_ % 16))) > 0;
break;
}
default:
break;
}
return m_statusOK;
}
bool ModbusBase::setBit(const modbusCell& cell, bool value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
switch (cell.type_)
{
case ModbusDataType_Coils: //线圈----读写
case ModbusDataType_DiscreteInput: //离散量--只读
{
checkSpsce(space, cell.slave_, (cell.addr_ + 15) / 16);
unsigned short temp = space->at(cell.slave_)[cell.addr_ / 16];
if (value) {
temp = temp | (0x0001 << (cell.addr_ % 16));
}
else {
temp = temp & (~(0x0001 << (cell.addr_ % 16)));
}
space->at(cell.slave_)[cell.addr_ / 16] = temp;
break;
}
case ModbusDataType_RegisterInput: //输入寄存器--只读
case ModbusDataType_RegisterHolding: //保持寄存器--读写
{
checkSpsce(space, cell.slave_, cell.addr_);
unsigned short temp = space->at(cell.slave_)[cell.addr_];
if (value) {
temp = temp | (0x0001 << (cell.bitAddr_ % 16));
}
else {
temp = temp & (~(0x0001 << (cell.bitAddr_ % 16)));
}
space->at(cell.slave_)[cell.addr_] = temp;
break;
}
default:
break;
}
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, false, false);
}
return m_statusOK;
}
bool ModbusBase::getWord(const modbusCell& cell, short & value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, true, false);
}
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_);
value = space->at(cell.slave_)[cell.addr_];
return m_statusOK;
}
bool ModbusBase::setWord(const modbusCell& cell, short value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_);
space->at(cell.slave_)[cell.addr_] = value;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, false, false);
}
return m_statusOK;
}
bool ModbusBase::getInt(const modbusCell& cell, int& value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, true, false);
}
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_ + 1);
//value = space->at(cell.slave_)[cell.addr_] << 16 | space->at(cell.slave_)[cell.addr_ + 1];
value = space->at(cell.slave_)[cell.addr_] | space->at(cell.slave_)[cell.addr_ + 1] << 16;
//space里面存的值是一个无符号的十进制数 一个地址2个字节16位
unsigned int highUnsigned = space->at(cell.slave_)[cell.addr_] & 0xFFFF; // 将有符号数与 0xFFFF 进行按位与操作 转成无符号十进制
unsigned int lowUnsigned = space->at(cell.slave_)[cell.addr_ + 1] & 0xFFFF; // 将有符号数与 0xFFFF 进行按位与操作
// 合成无符号 32 位数
uint32_t combinedValue = (static_cast<uint32_t>(highUnsigned) << 16) | lowUnsigned;
value = combinedValue;
short s = space->at(cell.slave_)[cell.addr_];
short s1 = space->at(cell.slave_)[cell.addr_ + 1];
short s2 = space->at(cell.slave_)[cell.addr_ + 1] << 16;
return m_statusOK;
}
bool ModbusBase::setInt(const modbusCell& cell, int value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_ + 1);
/*space->at(cell.slave_)[cell.addr_ + 0] = (value & 0xffff0000) >> 16;
space->at(cell.slave_)[cell.addr_ + 1] = value & 0x0000ffff;*/
/*space->at(cell.slave_)[cell.addr_ + 0] = (value & 0x0000ffff);
space->at(cell.slave_)[cell.addr_ + 1] = value & 0xffff0000 >> 16;*/
// 拆分为高位和低位
int16_t highByte = (value >> 16) & 0xFFFF;
int16_t lowByte = value & 0xFFFF;
space->at(cell.slave_)[cell.addr_ + 0] = highByte;
space->at(cell.slave_)[cell.addr_ + 1] = lowByte;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, false, false);
}
return m_statusOK;
}
bool ModbusBase::getString(const modbusCell& cell, std::string & value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, true, false);
}
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_);
std::vector <unsigned short>& vec = space->at(cell.slave_);
std::string str;
str = value;
//从当前地址逐个往下遍历并将里面的字符提取出来知道提取到0x0000,表示这一个字符串结束 一个地址两个字节16位
//默认使用UTF-8编码,一个中文占三个字节
//例如 "啊" 汉字 “啊” 的Unicode码点是U+554A 它的UTF-8编码为:0xE5 0x95 0x8A。0xE5(229) 0x95(149)0x8A(138) 十进制数为229 149 138
for (int i = cell.addr_; i < vec.size(); i++)
{
if (cell.endian_ == "BADC") //每两个字节反序 把高八位和低八位的值反序
{
if ((vec[i] & 0x00ff) == 0x0000) break;
str.push_back(vec[i] & 0x00ff); //提取低八位的数值
if ((vec[i] & 0xff00) == 0x0000) break;
str.push_back((vec[i] & 0xff00) >> 8); //提取高八位的数值 转化为ASCII字符存到字符串中
}
else //默认ABCD 大端序
{
if ((vec[i] & 0xff00) == 0x0000) break;
str.push_back((vec[i] & 0xff00) >> 8); //提取高八位的数值 转化为ASCII字符存到字符串中
if ((vec[i] & 0x00ff) == 0x0000) break;
str.push_back(vec[i] & 0x00ff); //提取低八位的数值
}
}
value = str;
return m_statusOK;
}
bool ModbusBase::setString(const modbusCell& cell, std::string value)
{
std::string last_str;
getString(cell, last_str);
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
size_t len = value.length();
int it = cell.addr_;
if (len < last_str.size())
len = last_str.size();
size_t count = (len + 1) / 2;
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_ + (count / 2) + 1);
std::vector <unsigned short>& vec = space->at(cell.slave_);
for (size_t i = 0; i < count; i++)
{
vec[it + i] = 0;
}
len = value.length();
if (cell.endian_ == "BADC") //每两个字节反序 把高八位和低八位的值反序
{
for (size_t i = 0; i < len; i++)
{
unsigned short temp = 0x00ff & value.at(i++);
if (i >= len) { //如果是单数,例如"123"就不进行调换
vec[it++] = temp;
}
else {
temp = (temp & 0x00ff ) | ( value.at(i) << 8);
vec[it++] = temp;
}
}
}
else //默认ABCD 大端序
{
for (size_t i = 0; i < len; i++)
{
unsigned short temp = 0x00ff & value.at(i++);
if (i >= len) {
temp = temp << 8;
vec[it++] = temp;
}
else {
temp = (temp << 8) | (0x00ff & value.at(i));
vec[it++] = temp;
}
}
}
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, false, false);
}
return m_statusOK;
}
// 将十进制数转换为小端序的16进制数
QString decimalToLittleEndianHex(int decimalValue)
{
QString hexValue = QString::number(decimalValue, 16);
// 确保每个 16 进制数是 4 位的
hexValue = hexValue.rightJustified(4, '0');
// 交换字节顺序
QString littleEndianHexValue;
littleEndianHexValue.append(hexValue[2]);
littleEndianHexValue.append(hexValue[3]);
littleEndianHexValue.append(hexValue[0]);
littleEndianHexValue.append(hexValue[1]);
return littleEndianHexValue;
}
bool ModbusBase::getFloat(const modbusCell & cell, float & value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, true, false);
}
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_);
//浮点数测试
union IntFloatUnion {
unsigned int intValue;
float floatValue;
};
//拿取slave对应站号的地址里的十进制数据进行转换
std::vector <unsigned short>& vec = space->at(cell.slave_);
QVariant v = vec[cell.addr_];
QVariant v1 = vec[cell.addr_ + 1];
// 将两个十进制数转换为 16 进制数
QString hexValue1 = QString::number(vec[cell.addr_], 16);
QString hexValue2 = QString::number(vec[cell.addr_ + 1], 16);
// 确保每个 16 进制数是 4 位的
hexValue1 = hexValue1.rightJustified(4, '0');
hexValue2 = hexValue2.rightJustified(4, '0');
// 按照大端序组合两个 16 进制数为一个 32 位的 16 进制数
QString combinedHexValue = hexValue1 + hexValue2;
/*
Big-endian ABCD 大端序
Big-endian Byte Swap BADC 大端序字节反序
Little-endian DCBA 小端序
Little-endian Byte Swap CDAB 小端序字节反序
*/
if (cell.endian_ == "CDAB") //小端序字节反序
{
combinedHexValue = hexValue2 + hexValue1;
}
else if (cell.endian_ == "DCBA")//小端序
{
hexValue1 = decimalToLittleEndianHex(vec[cell.addr_]);
hexValue2 = decimalToLittleEndianHex(vec[cell.addr_ + 1]);
combinedHexValue = hexValue2 + hexValue1;
}
else if (cell.endian_ == "BADC") //大端序字节反序
{
hexValue1 = decimalToLittleEndianHex(vec[cell.addr_]);
hexValue2 = decimalToLittleEndianHex(vec[cell.addr_ + 1]);
combinedHexValue = hexValue1 + hexValue2;
}
// 将组合后的 16 进制数转换为整数
bool ok;
unsigned int intValue = combinedHexValue.toUInt(&ok, 16);
if (ok) {
IntFloatUnion unionValue;
unionValue.intValue = intValue;
float floatValue = unionValue.floatValue; // 转换为浮点数
// 保留三位小数
QString formattedValue = QString::number(floatValue, 'f', 3);
value = formattedValue.toFloat();
}
return m_statusOK;
}
// 将32位的浮点数拆分为两个16位的整数(大端序)
void splitBigFloatToRegisters(float floatValue, quint16& register1, quint16& register2) {
quint32 intValue = *reinterpret_cast<quint32*>(&floatValue);
register1 = (intValue >> 16) & 0xFFFF;
register2 = intValue & 0xFFFF;
}
// 将32位的浮点数拆分为两个16位的整数(小端序)
void splitLittleFloatToRegisters(float floatValue, quint16& register1, quint16& register2) {
quint32 intValue = *reinterpret_cast<quint32*>(&floatValue);
quint16 ts1 = (intValue >> 16) & 0xFFFF; //转换为整数
register1 = ((ts1 & 0xFF) << 8) | ((ts1 & 0xFF00) >> 8); //再把整数反序
quint16 ts2 = intValue & 0xFFFF;
register2 = ((ts2 & 0xFF) << 8) | ((ts2 & 0xFF00) >> 8);
}
bool ModbusBase::setFloat(const modbusCell & cell, float value)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_statusOK = true;
std::map<char, std::vector <unsigned short>>* space = m_space[cell.type_];
checkSpsce(space, cell.slave_, cell.addr_);
if (m_manualFlag)
{
m_statusOK = manualDeal(cell, false, false);
}
/*
Big-endian ABCD 大端序
Big-endian Byte Swap BADC 大端序字节反序
Little-endian DCBA 小端序
Little-endian Byte Swap CDAB 小端序字节反序
*/
quint16 register1, register2;
if (cell.endian_ == "CDAB") //小端序字节反序
{
splitBigFloatToRegisters(value, register1, register2);
space->at(cell.slave_)[cell.addr_] = register2;
space->at(cell.slave_)[cell.addr_ + 1] = register1;
}
else if (cell.endian_ == "DCBA")//小端序
{
splitLittleFloatToRegisters(value, register1, register2);
space->at(cell.slave_)[cell.addr_] = register2;
space->at(cell.slave_)[cell.addr_ + 1] = register1;
}
else if (cell.endian_ == "BADC") //大端序字节反序
{
splitLittleFloatToRegisters(value, register1, register2);
space->at(cell.slave_)[cell.addr_] = register1;
space->at(cell.slave_)[cell.addr_ + 1] = register2;
}
else //默认大端序Big-endian ABCD 大端序
{
splitBigFloatToRegisters(value, register1, register2);
space->at(cell.slave_)[cell.addr_] = register1;
space->at(cell.slave_)[cell.addr_ + 1] = register2;
}
return m_statusOK;
}