You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Cigarette/Cigarette/PLC/PLCDevice.cpp

270 lines
8.4 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}
}