|
|
#include "stdio.h"
|
|
|
#include "PLCDevice.h"
|
|
|
#include <iostream>
|
|
|
#include <common.h>
|
|
|
#include <QDebug>
|
|
|
|
|
|
extern SysConf g_sys_conf;
|
|
|
|
|
|
bool PLCDevice::init_plc(PLCDevice* PLCptr)
|
|
|
{
|
|
|
// modbus_connect() 建立连接,成功返回0,错误返回-1
|
|
|
// modbus_new_rtu 生成RTU的连接,建立成功则返回指向modbus_t结构的指针,否则将返回NULL/0
|
|
|
|
|
|
const char* comport = g_sys_conf.ComPort.data();
|
|
|
qDebug() << "COM:" << comport;
|
|
|
//连接PLC
|
|
|
PLCptr->g_modbus = modbus_new_rtu(comport, 9600, 'N', 8, 1);
|
|
|
modbus_set_debug(PLCptr->g_modbus, 0); // 用flag设置debug调试标志位,flag=1时显示modbus消息的字节
|
|
|
modbus_set_response_timeout(PLCptr->g_modbus, 1, 0); // 设置响应超时
|
|
|
modbus_connect(PLCptr->g_modbus);
|
|
|
modbus_set_slave(PLCptr->g_modbus, 1); // 设置从站id
|
|
|
|
|
|
uint8_t data;
|
|
|
int ret = modbus_read_bits(PLCptr->g_modbus, 30000, 1, &data);
|
|
|
if (PLCptr->g_modbus && ret == -1) {
|
|
|
PLCptr->g_plc_ok = false;
|
|
|
}
|
|
|
else {
|
|
|
|
|
|
PLCptr->g_plc_ok = true;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool PLCDevice::init_plc_tcp(PLCDevice* PLCptr)
|
|
|
{
|
|
|
#ifdef __ModebusServer
|
|
|
PLCptr->g_modbus = modbus_new_tcp("192.168.1.180", 2000);
|
|
|
modbus_set_debug(PLCptr->g_modbus, 0); // 用flag设置debug调试标志位,flag=1时显示modbus消息的字节
|
|
|
modbus_set_response_timeout(PLCptr->g_modbus, 1, 0); // 设置响应超时
|
|
|
modbus_connect(PLCptr->g_modbus);
|
|
|
modbus_set_slave(PLCptr->g_modbus, 1); // 设置从站id
|
|
|
|
|
|
uint8_t data;
|
|
|
int ret = modbus_read_bits(PLCptr->g_modbus, 0, 1, &data);
|
|
|
// 连接失败
|
|
|
if (-1 == ret)
|
|
|
{
|
|
|
PLCptr->g_plc_ok = false;
|
|
|
qDebug("TCP connect failed:%s\n", modbus_strerror(errno));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
PLCptr->g_plc_ok = true;
|
|
|
qDebug("TCP connect successful ");
|
|
|
}
|
|
|
#endif
|
|
|
#ifdef __ModebusClient
|
|
|
const char* ip = g_sys_conf.TcpIP.data();
|
|
|
qDebug() << "Client ip:" << ip;
|
|
|
qDebug() << "Client port:" << g_sys_conf.TcpPort;
|
|
|
PLCptr->g_modbus = modbus_new_tcp(ip, g_sys_conf.TcpPort);
|
|
|
modbus_set_debug(PLCptr->g_modbus, 0); // 用flag设置debug调试标志位,flag=1时显示modbus消息的字节
|
|
|
modbus_set_response_timeout(PLCptr->g_modbus, 1, 0); // 设置响应超时
|
|
|
// 侦听主站连接
|
|
|
PLCptr->m_modbusSocket = modbus_tcp_listen(PLCptr->g_modbus, 1); // 最多支持的主机数量 1
|
|
|
/*设置线圈, 离散输入, 输入寄存器, 保持寄存器个数(数组元素个数))*/
|
|
|
PLCptr->mapping = modbus_mapping_new(PLCptr->m_numBits, PLCptr->m_numInputBits, PLCptr->m_numInputRegisters, PLCptr->m_numRegisters);
|
|
|
if (PLCptr->mapping == NULL)
|
|
|
{
|
|
|
modbus_free(PLCptr->g_modbus);
|
|
|
PLCptr->m_initialized = false;
|
|
|
return false;
|
|
|
}
|
|
|
PLCptr->m_initialized = true;
|
|
|
|
|
|
PLCptr->modSerThread = new std::thread(&PLCDevice::recieveMessages, PLCptr);
|
|
|
PLCptr->modSerThread->detach();
|
|
|
std::cout << "Running ModbusTcpSlave" << std::endl;
|
|
|
#endif
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
#ifdef __ModebusClient
|
|
|
/***************************************************************
|
|
|
* @file PLCDevice.cpp
|
|
|
* @author seer-txj
|
|
|
* @brief 支持多个master同时连接
|
|
|
* @version v1
|
|
|
* @return null
|
|
|
* @date 2021/10/6
|
|
|
**************************************************************/
|
|
|
void PLCDevice::recieveMessages()
|
|
|
{
|
|
|
uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
|
|
|
|
|
|
int fd_num = 0, fd_max = 0, ret = 0, i = 0, clnt_sock = -1;
|
|
|
fd_set reads, cpy_reads;
|
|
|
FD_ZERO(&reads);
|
|
|
FD_SET(m_modbusSocket, &reads);
|
|
|
fd_max = m_modbusSocket;
|
|
|
while (m_initialized)
|
|
|
{
|
|
|
cpy_reads = reads;
|
|
|
if ((fd_num = select(fd_max + 1, &cpy_reads, 0, 0, 0)) == -1)
|
|
|
break;
|
|
|
if (fd_num == 0)
|
|
|
continue;
|
|
|
for (i = 0; i < fd_max + 1; i++)
|
|
|
{
|
|
|
if (FD_ISSET(i, &cpy_reads))
|
|
|
{
|
|
|
if (i == m_modbusSocket)
|
|
|
{
|
|
|
clnt_sock = modbus_tcp_accept(g_modbus, &m_modbusSocket);
|
|
|
if ((m_modbusSocket == -1) || (clnt_sock == -1))
|
|
|
{
|
|
|
std::cerr << modbus_strerror(errno) << std::endl;
|
|
|
continue;
|
|
|
}
|
|
|
FD_SET(clnt_sock, &reads);
|
|
|
if (fd_max < clnt_sock)
|
|
|
fd_max = clnt_sock;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ret = modbus_receive(g_modbus, query);
|
|
|
if (ret == 0)
|
|
|
{
|
|
|
m_errCount = 0;
|
|
|
continue;
|
|
|
}
|
|
|
else if (ret > 0)
|
|
|
{
|
|
|
m_errCount = 0;
|
|
|
// 填写输出内容,用于测试,实际输出在threadSendTCP::sendData中实现,这边只要reply
|
|
|
/* mapping->tab_registers[0] = 0;
|
|
|
mapping->tab_registers[1] = 11;
|
|
|
mapping->tab_registers[2] = 22;
|
|
|
|
|
|
mapping->tab_input_registers[0] = 0;
|
|
|
mapping->tab_input_registers[1] = 33;
|
|
|
mapping->tab_input_registers[2] = 44;
|
|
|
|
|
|
mapping->tab_bits[0] = 0;
|
|
|
mapping->tab_bits[1] = 1;
|
|
|
mapping->tab_bits[2] = 0;
|
|
|
|
|
|
mapping->tab_input_bits[0] = 1;
|
|
|
mapping->tab_input_bits[1] = 0;
|
|
|
mapping->tab_input_bits[2] = 1;*/
|
|
|
|
|
|
modbus_reply(g_modbus, query, sizeof(query), mapping);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
modbus_set_error_recovery(g_modbus, MODBUS_ERROR_RECOVERY_NONE);
|
|
|
modbus_set_error_recovery(g_modbus, MODBUS_ERROR_RECOVERY_LINK);
|
|
|
modbus_close(g_modbus);
|
|
|
FD_CLR(i, &reads);
|
|
|
#ifdef _WIN32
|
|
|
closesocket(i);
|
|
|
#else
|
|
|
close(i);
|
|
|
#endif // _WIN32
|
|
|
|
|
|
m_errCount++;
|
|
|
}
|
|
|
if(m_errCount > 5)
|
|
|
{
|
|
|
m_initialized = false;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
m_initialized = false;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
bool PLCDevice::disconnect_plc(void)
|
|
|
{
|
|
|
if (g_modbus)
|
|
|
{
|
|
|
modbus_close(g_modbus);
|
|
|
modbus_free(g_modbus);
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
int PLCDevice::write_bit_2_plc(int addr, int value)
|
|
|
{
|
|
|
if (g_plc_ok)
|
|
|
{
|
|
|
g_mutex.lock();
|
|
|
int ret = modbus_write_bit(g_modbus, addr, value);
|
|
|
g_mutex.unlock();
|
|
|
//printf("modbus_write_bit:addr=%d,value=%d,ret=%d\n", addr, value, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
else {
|
|
|
//std::cout << "PLC no ok" << std::endl;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int PLCDevice::read_bits_from_plc(int addr, int nb, uint8_t* value)
|
|
|
{
|
|
|
if (g_plc_ok)
|
|
|
{
|
|
|
g_mutex.lock();
|
|
|
int ret = modbus_read_bits(g_modbus, addr, nb, value);
|
|
|
g_mutex.unlock();
|
|
|
//printf("modbus_read_bits:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
else {
|
|
|
//std::cout << "PLC no ok" << std::endl;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int PLCDevice::write_short_2_plc(int addr, int nb, uint16_t* value)
|
|
|
{
|
|
|
if (g_plc_ok)
|
|
|
{
|
|
|
g_mutex.lock();
|
|
|
int ret = modbus_write_registers(g_modbus, addr, nb, value);
|
|
|
g_mutex.unlock();
|
|
|
//printf("modbus_write_registers:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
else {
|
|
|
//std::cout << "PLC no ok" << std::endl;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int PLCDevice::read_short_from_plc(int addr, int nb, uint16_t* value)
|
|
|
{
|
|
|
if (g_plc_ok)
|
|
|
{
|
|
|
g_mutex.lock();
|
|
|
int ret = modbus_read_registers(g_modbus, addr, nb, value);
|
|
|
g_mutex.unlock();
|
|
|
//printf("modbus_read_registers:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value ,ret);
|
|
|
return ret;
|
|
|
}
|
|
|
else {
|
|
|
//std::cout << "PLC no ok" << std::endl;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int PLCDevice::write_2_plc(int addr, int nb, uint16_t* value)
|
|
|
{
|
|
|
if (g_plc_ok)
|
|
|
{
|
|
|
//g_mutex.lock();
|
|
|
int ret = modbus_write_registers(g_modbus, addr, nb, value);
|
|
|
//g_mutex.unlock();
|
|
|
//printf("modbus_write_registers:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value, ret);
|
|
|
return ret;
|
|
|
}
|
|
|
else {
|
|
|
//std::cout << "PLC no ok" << std::endl;
|
|
|
return false;
|
|
|
}
|
|
|
} |