Fins/UDP通信
编写上位机通过发送Fins/UDP命令读写plc内部数据,可以用于上位机socket通讯测试,员工操作监控,运行日志打印。Fins/UDP是以十六进制字符发送命令,所以所有字符在发送前都需要将其转换成十六进制。
写格式
固定头:800002 不变
plc节点:006E00 地址:XXX.XXX.XXX.110
PC节点:00F400 地址:XXX.XXX.XXX.244
结束:00 不变
写代码:0102 不变
D区代码:82 不变
D区地址:01A600 根据需求修改,十六进制数据
写入长度:0001 根据需求修改,十六进制数据
写入数据:0212
写反馈
固定头:C00002 不变
PC节点:00F400 地址:XXX.XXX.XXX.244
plc节点:006E00 地址:XXX.XXX.XXX.110
结束:00 不变
写代码:0102 不变
写入成功:0000
读格式
固定头:800002 不变
plc节点:006E00 地址:XXX.XXX.XXX.110
PC节点:00F400 地址:XXX.XXX.XXX.244
结束:00 不变
读代码:0101 不变
D区代码:82 不变
D区地址:01A600 根据需求修改,十六进制数据
读取长度:0002 根据需求修改,十六进制数据
读反馈
固定头:C00002 不变
PC节点:00F400 地址:XXX.XXX.XXX.244
plc节点:006E00 地址:XXX.XXX.XXX.110
结束:00 不变
读代码:0101 不变
plc状态:0000 自动变换
plc反馈的数据:66664006
进制间转换函数
int型与字符串转16进制,16进制转字符串。
int-to-16进制
int num=666;
QString Dnum = QString::number(num,16);
字符串-to-16进制
QByteArray ReadPLC::QString2Hex(QString str)
{
QByteArray senddata;
int hexdata,lowhexdata;
int hexdatalen = 0;
int len = str.length();
senddata.resize(len/2);
char lstr,hstr;
for(int i=0; i<len; )
{
hstr=str[i].toLatin1();
if(hstr == ' ')
{
i++;
continue;
}
i++;
if(i >= len)
break;
lstr = str[i].toLatin1();
hexdata = ConvertHexChar(hstr);
lowhexdata = ConvertHexChar(lstr);
if((hexdata == 16) || (lowhexdata == 16))
break;
else
hexdata = hexdata*16+lowhexdata;
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
return senddata;
}
char ReadPLC::ConvertHexChar(char ch)
{
if((ch >= '0') && (ch <= '9'))
return ch-0x30;
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
else return (-1);
}
16进制-to-字符串
自行补充
Fins/UDP通信
读函数与写函数都差不多,读写反馈可以使用信号槽来监听新数据,也可以直接后面写函数来读取,只不过需要做一下延时处理。
读写函数
void ReadPLC::readplcdata(QString bindPort,QString bindIP, QString winIP, int IO, int WID)
{
QString plcip,winddowip;
int plcIPEnd = bindIP.split(".").at(3).toInt();
plcip = QString::number(plcIPEnd,16).toUpper();
int winIPEnd = winIP.split(".").at(3).toInt();
winddowip = QString::number(winIPEnd,16).toUpper();
if(plcip.size()==1){
plcip = "0"+plcip;
}
if(winddowip.size()==1){
winddowip = "0"+winddowip;
}
QString ID = intTo16(WID);
QString writeIO = "000"+QString::number(IO,16).toUpper();
QString plcwrite = "80000200"+plcip+"0000"+winddowip+"0000010182";
plcwrite += ID+"00000"+QString::number(IO);
QByteArray data = QString2Hex(plcwrite);
udpsocket->writeDatagram(data, QHostAddress(bindIP), quint16(bindPort.toInt()));
}
读写反馈
void ReadPLC::Read_plc_data()
{
QByteArray datagram;
datagram.resize(int(udpsocket->pendingDatagramSize()));
udpsocket->readDatagram(datagram.data(),datagram.size());
QString str = datagram.data();
QString byte = datagram.toHex();
if(!byte.isEmpty())
{
QString str_rev = QString(datagram.toHex(' ').toUpper().append(' '));
qDebug()<<"data:"<<str_rev;
}
}
|