资源
QT环境下实现资源
Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。
Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。
标准的Modbus协议物理层接口有RS232、RS485和以太网接口,采用master/slave方式通信。
常用串行接口区别RS232与RS485
RS232传输电平信号
接口的信号电平值较高(信号“1”为“-3V至-15V”,信号“0”为“3至15V”),易损坏接口电路的芯片,又因为与TTL电平(0“<0.8v”,1“>2.0V”)不兼容故需使用电平转换电路方能与TTL电路连接。另外抗干扰能力差。
RS485传输差分信号
逻辑“1”以两线间的电压差为+(2—6) V表示;逻辑“0”以两线间的电压差为-(2—6)V表示。接口信号电平比RS-232降低了,就不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL电路连接。
通讯距离长短
RS232:
RS232传输距离有限,最大传输距离标准值为15米,且只能点对点通讯,最大传输速率最大为20kB/s。
RS485:
RS485最大无线传输距离为1200米。最大传输速率为10Mbps,在100Kb/S的传输速率下,才可以达到最大的通信距离。
采用阻抗匹配、低衰减的专用电缆可以达到1800米!超过1200米,可加中继器(最多8只),这样传输距离接近10Km。
能否支持多点通讯
**RS232:**RS232接口在总线上只允许连接1个收发器,不能支持多站收发能力,所以只能点对点通信,不支持多点通讯。
**RS485:**RS485接口在总线上是允许连接多达128个收发器。即具有多站通讯能力,这样用户可以利用单一的RS485接口方便地建立起设备网络。
通讯线的差别
RS232:
可以采用三芯双绞线、三芯屏蔽线等。
RS485:
可以采用两芯双绞线、两芯屏蔽线等。
在低速、短距离、无干扰的场合可以采用普通的双绞线,反之,在高速、长线传输时,则必须采用阻抗匹配(一般为120Ω)的RS485专用电缆(STP-120Ω(用于RS485 & CAN)一对18AWG),而在干扰恶劣的环境下还应采用铠装型双绞屏蔽电缆(ASTP-120Ω(用于RS485 & CAN)一对18AWG)。
补充:
即然RS232传输距离只有15米这么短,那么有什么作用呢?
其实它的应用非常广泛,可以连接各种设备,例如监控、其它的设备升级或调试等都可能需要用到它。功能与USB比较接近,随着USB端口的越来越普遍,将会出现更多的把USB转换成RS-232或其它接口的转换装置。
通过USB接口可连接更多的RS-232设备,不仅可获得更高的传输速度,实现真正的即插即用,同时解决了USB接口不能远距离传输的缺点(USB通讯距离在5米内)。
在城市轻轨风机控制系统中,变频器凭借着其变频节能,能软启,可调速等特点有着广泛的应用。但变频器本身对数据的计算、存储、分析能力不足,智能化程度不高等缺点也越发明显。传统的控制常采用硬接线方式,只能单纯的实现控制,但对变频器内部的信息不能查询也无法控制。而RS-485协议通信方法控制变频器方式编程工作量较大。通过变频器与PLC通信能有效的避免这些不足,提高变频器控制的自动化水平。
Modbus是被广泛应用于PLC与变频器通信的网络协议。采用Modbus通信方式,速度快、距离远、效率高、工作稳定、编程简单等优点。在城市轻轨单向运转的耐高温轴流排热风机控制项目中,风机变频器就是通过Modbus的通信方式实现的,通过Modbus通信将变频器中的电气参数如电流、电压、运行频率和报警信息传送到PLC中,实现PLC对风机启动,旁路切换等自动控制和状态监控。
Modbus RTU通常具有优良的通讯能力和更大的存储容量,适用于更恶劣的温度和湿度环境,提供更多的计算功能。广泛应用于智慧水利、智慧环保、工业物联网、智慧市政等,如:水文远程监控、水资源远程监测、水源井远程监控、山洪灾害监测、地质灾害监测、河道监测预警、气象监测、泵站远程监控、污染源远程监控等远程测控领域。
QT串口通信验证
QT 的串口通信,QT为我们提供了一个用于串口通信的类QSerialPort,该类可以帮助我们实现串口通信,在QT中我编写了一个案例验证了是可以实现串口通信的。
首先是创建一个QSerialPort对象,然后调用对应的方法设置串口号等参数,例如调用setPortName方法设置端口号。当串口成功打开后,QSerialPort对象会监听IO口是否有数据,当有数据时会发出readyRead信号,我们只需要编写一个槽去接收即可,当向串口写入数据时,我们只需要调用QSerialPort对象的write方法即可。
QT网络通信验证
QT 的网络通信,在Qt中提供了QTcpSocket类来编写客户端程序,使用QTcpServer类编写服务器端程序。我们在服务器端进行端口的设置,一旦发现客户端的连接请求,就会发出newConnection()信号,可以关联这个信号到我们自己的槽进行数据的读取和发送。而在客户端,一旦有数据到来就会发出readyRead()信号,可以关联此信号进行数据的接收。
Modbus_RTU从站项目,我是基于QT 5.6.3 版本开发的,使用的是C++作为开发语言,下面是我的项目的目录结构。
文件夹名称 | 存放文件类型 |
---|---|
analysis | 存放用于报文解析的类文件 |
uartPort | 存放串口通信的类文件 |
dataini | 存放寄存器和线圈数据的ini文件 |
logi | 存放通信历史信息的txt文件 |
utils | 存放用到的辅助工具类文件 |
RTU从站项目总体框图如下所示:
RTU从站总体流程图
上述流程描述:
主程序启动后进行界面初始化,界面初始化完成后,开启串口线程,和数据解析线程。串口线程负责数据的收发,数据解析线程负责对接收到的报文进行解析。
当用户在界面上配置好串口参数后,例如串口号,波特率等,用户点击打开串口按钮,UI线程会向串口线程发送upCfg2Uart信号,串口线程会执行对应的槽函数打开串口,如果打开失败,串口线程会向UI线程发送errOccurred信号,UI线程会执行对应的槽函数弹出错误提示框。
当串口的readyread信号被触发表明有数据到来,这时串口线程开启定时器,当定时器时间溢出后,表明接收完了一帧数据,将会发送readyread(sendArray)信号并停止定时器,UI线程会执行对应的槽函数。
当数据解析线程接收到UI线程的Start信号后,数据解析线程会执行对应的槽函数,进行数据的解析,当数据解析完毕后,会向UI线程发送analysis_over信号UI线程会执行对应的槽函数向串口线程发送sendData2Uart信号,串口线程会执行对应的槽函数进行数据发送。
当用户退出程序后结束。
Modbus_RTU主站项目,我是基于QT 5.6.3 版本开发的,使用的是C++作为开发语言,下面是我的项目的目录结构。
文件夹名称 | 存放文件类型 |
---|---|
modbusmsg | 存放用于报文解析的类文件 |
uartPort | 存放串口通信的类文件 |
config | 存放寄存器和线圈数据的ini文件,通信历史信息的txt文件 |
utils | 存放用到的辅助工具类文件 |
RTU主站项目总体框图如下所示:
RTU主站总体流程图
上述流程描述:
主程序启动后进行界面初始化,界面初始化完成后,开启串口通信线程,和数据封装线程。串口通信线程负责数据的收发,数据封装线程负责对请求报文进行封装。
当用户在界面上配置好串口参数后,例如串口号,波特率等,用户点击打开串口按钮,UI线程会向串口线程发送upCfg2Uart信号,串口线程会执行对应的槽函数打开串口,如果打开失败,串口线程会向UI线程发送errOccurred信号,UI线程会执行对应的槽函数弹出错误提示框。
当用户配置好数据信息后点击发送按钮后,会发送信号给数据封装线程。
当数据封装线程接收到UI线程的Start信号后,会进行报文的封装,封装完毕后会发送package_over信号给主线程,主线程发送信号给串口通信线程去发送数据。
当用户退出程序后结束。
Modbus_TCP从站项目,我是基于QT 5.6.3 版本开发的,使用的是C++作为开发语言,下面是我的项目的目录结构。
文件夹名称 | 存放文件类型 |
---|---|
analysis | 存放用于报文解析的类文件 |
network | 存放网络通信的类文件 |
dataini | 存放寄存器和线圈数据的ini文件 |
logi | 存放通信历史信息的txt文件 |
utils | 存放用到的辅助工具类文件 |
TCP从站项目总体框图如下所示:
上述流程描述:
主程序启动后进行界面初始化,界面初始化完成后,开启网络通信线程,和数据解析线程。网络通信线程负责数据的收发,数据解析线程负责对接收到的报文进行解析。
当用户在界面上配置好网络通信参数后,例如IP地址,端口号,用户点击监听按钮,会创建Myserver对象并调用listen方法进行监听。
当MySocket的readyread信号被触发表明有数据到来,这时会执行deal_readyRead槽函数接收数据,当数据接收完成后会向UI线程发送AddMessage和revcMsg信号。
当数据解析线程接收到UI线程的Start信号后,数据解析线程会执行对应的槽函数,进行数据的解析,当数据解析完毕后,会向UI线程发送analysis_over信号UI线程会执行对应的槽函数向网络线程发送WriteMessage信号,网络线程会执行对应的槽函数进行数据发送。
当用户退出程序后结束。
Modbus_TCP主站项目,我是基于QT 5.6.3 版本开发的,使用的是C++作为开发语言,下面是我的项目的目录结构。
文件夹名称 | 存放文件类型 |
---|---|
modbusmsg | 存放用于报文解析的类文件 |
config | 存放寄存器和线圈数据的ini文件,通信历史信息的txt文件 |
utils | 存放用到的辅助工具类文件 |
TCP主站项目总体框图如下所示:
TCP主站总体流程图
上述流程描述:
主程序启动后进行界面初始化,界面初始化完成后,开启网络通信线程,和数据封装线程。网络通信线程负责数据的收发,数据封装线程负责对接收到的报文进行封装。
当用户在界面上配置好网络通信参数后,例如IP地址,端口号,用户点击监听按钮,会创建Myserver对象并调用connect方法进行连接。
当用户配置好数据信息后点击发送按钮后,会发送信号给数据封装线程。
当数据封装线程接收到UI线程的封装信号后,数据封装线程会执行对应的槽函数,进行数据的封装,当数据封装完毕后,会向UI线程发送pack_over信号UI线程会执行对应的槽函数向网络线程发送WriteMessage信号,网络线程会执行对应的槽函数进行数据发送。
当用户退出程序后结束。
RTU从站详细分为以下几个模块,界面布局模块,串口通信模块,报文解析模块,历史信息记录模块,系统时间显示模块。下面分别详细介绍实现方案。
RTU从站界面布局如下图所示:
串口类(uartPort)设计:
主要信号与槽设计
信号 | 描述 |
---|---|
void openError(bool); | 传输串口开闭标志给主线程 |
void readyread(QByteArray); | 传输读取的串口数据给主线程 |
void errOccurred(QString); | 传输串口错误信息给主线程 |
槽 | 描述 |
---|---|
void updateComCfg(comcfg_t cfg); | 主线程传入串口配置信息后打开串口 |
void readyRead(); | 串口对象接受导数据后执行 |
void writeData(QByteArray); | 接收到主线程数据后通过串口发送 |
void timerOut(); | 数据帧间隔处理槽 |
串口类处理流程:
上述流程描述:
当用户点击打开串口按钮,UI线程会向串口线程发送upCfg2Uart信号,串口线程会执行对应的槽函数打开串口,如果打开失败,串口线程会向UI线程发送errOccurred信号,UI线程会执行对应的槽函数弹出错误提示框。
当串口的readyread信号被触发表明有数据到来,这时串口线程开启定时器,当定时器时间溢出后,表明接收完了一帧数据,将会发送readyread(sendArray)信号并停止定时器,UI线程会执行对应的槽函数。
当用户点击关闭串口按钮后,UI线程会向串口线程发送closeUart信号,串口线程会执行对应的槽函数关闭串口并销毁串口对象。
报文分析类(analysis)设计:
主要信号与槽设计
信号 | 描述 |
---|---|
void analysis_over(QByteArray ba); | 回应报文 |
void wirtTablec(quint16 num, quint16 satrtaddr,QString bac); | 传输数据给主线程显示写入线圈状态 |
void wirtTabler(quint16 num, quint16 satrtaddr,quint16 bar[]); | 传输数据给主线程显示写入寄存器数据 |
槽 | 描述 |
---|---|
void recvModbusMsg(QByteArray msg,quint8 addr); | 接收报文 |
void readIniCoilTobyte(QByteArray &ba,quint16 startaddr,quint16 num); | 封装ini线圈状态to byte |
void readByteToCoilIni(QByteArray ba,quint16 startaddr,quint16 num); | 封装字节数据to ini线圈状态 |
void parse_Modbus_MB_satae(MB_satae); | 状态处理 |
void parse_Modbus_True_Msg(QByteArray msg); | 正常帧处理 |
void parse_Modbus_Exception_Handling03(); void parse_Modbus_Exception_Handling02(); void parse_Modbus_Exception_Handling01(); | 异常处理 |
MB_satae parse_Modbus_Msg(QByteArray msg); | 解析报文查询状态 |
void func_01(); void func_03(); void func_0f(); void func_10(); | 功能码处理函数 |
报文分析类处理流程:
上述流程描述:
当数据解析线程接收到UI线程的Start信号后,数据解析线程会执行void recvModbusMsg(QByteArray msg,quint8 addr)槽函数接收数据,recvModbusMsg槽函数会调用parse_Modbus_MB_satae进行数据的解析给出报文状态。
1.MB_SLAVE_STATE_PACKET_OTHER 状态:不做响应
Modbus正常报文须满足小于256字节,大于8个字节,CRC校验是否满足条件,当接收到的报文不满足这个条件是会返回
MB_SLAVE_STATE_PACKET_OTHER状态。
2.MB_SLAVE_STATE__ADDR_ERROR状态:从机地址异常。
当发送的报文不是给本机时返回
MB_SLAVE_STATE__ADDR_ERROR
3.MB_SLAVE_STATE_DATA_ERROR状态:数据范围异常
Modbus正常报文须满足小于256字节,大于8个字节,读线圈数量需满足小于等于2000,写线圈需满足小于等于1968,读寄存器需满足小于125,写寄存器需满足小于123。如果条件不满足返回
MB_SLAVE_STATE_DATA_ERROR状态。
4.MB_SLAVE_STATE_DATAADDR_ERROR状态:数据地址异常
Modbus地址范围0~65535,当数量OK且数量+起始地址OK。如果不满足返回
MB_SLAVE_STATE_DATAADDR_ERROR状态。
5.MB_SLAVE_STATE_FUNCTION_ERROR状态:功能码错误。
当报文里不是允许的功能码返回该状态。
6.MB_SLAVE_STATE_PACKET_PROCESS状态:一切正常。
当报文没有问题返回该状态。
处理完毕后调用parse_Modbus_MB_satae对状态进行处理,根据状态去执行对应的槽,执行完毕后会向UI线程发送analysis_over信号。
历史信息记录处理流程:
开启一个定时器,并定时两分钟中,当定时时间到了就会执行对应的槽去获取界面通信历史信息,并将信息写入到TXT文件中。
系统时间显示处理流程:
开启一个定时器,并定时1秒中,当定时时间到了就会执行对应的槽去获取系统时间,并更新系统时间。
RTU主站界面布局如下图所示
串口类(uartPort)设计:
主要信号与槽设计
信号 | 描述 |
---|---|
void openError(bool); | 传输串口开闭标志给主线程 |
void readyread(QByteArray); | 传输读取的串口数据给主线程 |
void errOccurred(QString); | 传输串口错误信息给主线程 |
槽 | 描述 |
---|---|
void updateComCfg(comcfg_t cfg); | 主线程传入串口配置信息后打开串口 |
void readyRead(); | 串口对象接受导数据后执行 |
void writeData(QByteArray); | 接收到主线程数据后通过串口发送 |
void timerOut(); | 数据帧间隔处理槽 |
串口类处理流程:
上述流程描述:
当用户点击打开串口按钮,UI线程会向串口线程发送upCfg2Uart信号,串口线程会执行对应的槽函数打开串口,如果打开失败,串口线程会向UI线程发送errOccurred信号,UI线程会执行对应的槽函数弹出错误提示框。
当串口的readyread信号被触发表明有数据到来,这时串口线程开启定时器,当定时器时间溢出后,表明接收完了一帧数据,将会发送readyread(sendArray)信号并停止定时器,UI线程会执行对应的槽函数。
当用户点击关闭串口按钮后,UI线程会向串口线程发送closeUart信号,串口线程会执行对应的槽函数关闭串口并销毁串口对象。
报文封装类(modbusmsg)设计:
主要信号与槽设计
信号 | 描述 |
---|---|
void package_over(QByteArray package_msg); | 报文封装完成 |
void showMsgtoUi(QString); | 显示日志信息到ui线程 |
槽 | 描述 |
---|---|
void packageSartc(quint8,quint8,quint16,QList,QByteArray ba,quint16 cnums); | 主线程传入数据开始处理100f功能报文 |
void packageSartr(quint8 addr,quint8 funcode,quint16 startaddr,quint16 numreg); | 主线程传入数据开始处理0103功能报文 |
void funCode01(quint8 addr,quint16 startaddr,quint16 numreg); void funCode03(quint8 addr,quint16 startaddr,quint16 numreg); void funCode0f(quint8 addr,quint16 startaddr,QList,QByteArray ba,quint16 cnums); void funCode10(quint8 addr,quint16 startaddr,QList); | 报文封装函数 |
报文封装类处理流程:
当用户配置好数据信息后点击发送按钮后,会发送信号给数据封装线程。
当数据封装线程接收到UI线程的Start信号后,会进行报文的封装,封装完毕后会发送package_over信号给主线程,主线程发送信号给串口通信线程去发送数据。
当用户点击查看按钮时
1.判断有无文件路径
2.如果有文件路径则进入显示历史消息函数进行显示
3.如果没有文件路径先弹出对话框进行选择路径
4.如果选择路径为空则提示打开失败
5.如果路径合法则提示成功,并进入显示历史消息函数进行显示
系统时间显示处理流程:
开启一个定时器,并定时1秒中,当定时时间到了就会执行对应的槽去获取系统时间,并更新系统时间。
TCP从站详细分为以下几个模块,界面布局模块,网络通信模块,报文解析模块,历史信息记录模块,系统时间显示模块。下面分别详细介绍实现方案。
TCP服务端(myserver)设计:
myserver类继承与QTCPServer类,我重写了QTCPServer类的void incomingConnection(qintptr socketDescriptor)方法,当有客户端连接时会自动执行改槽。
主要信号与槽设计
槽 | 描述 |
---|---|
void SetThread(int num); | 设置最大线程数 |
int GetMinLoadThread(); | 获取最少线程数 |
void incomingConnection(qintptr socketDescriptor); | 重写的 |
void AddInf(MySocket* mysocket,int index); | 添加客户端套接字的信息 |
void RemoveInf(MySocket* mysocket); | 移除客户端的套接字信息 |
myserver类处理流程:
上述流程描述:
当用户设置好ip和端口信息后点击监听按钮,会进行监听,当有客户端连接时会发送Create信号去创建套接字对象,当创建成功后会发送AddList信号将创建成功的套戒字信息添加到列表中,当客户端断开时会发送RemoveList信号将对应的客户端信息从列表中移除。
然后等待新的客户端连接进来。
TCP服务端(mysocket)设计:
mysocket类继承与QTcpSocket类。
主要信号与槽设计
信号 | 描述 |
---|---|
void AddMessage(QByteArray msg); | 发送给UI显示 |
void revcMsg(QByteArray msg); | 接收客户端数据 |
void WriteMessage(QByteArray ba); | UI发送过来数据 |
void DeleteSocket(); | 主动关闭socket |
槽 | 描述 |
---|---|
void deal_readyRead(); | 读取数据槽函数 |
void deal_disconnect(); | 断开连接槽函数 |
void deal_write(QByteArray ba); | 写入数据槽函数 |
mysocket类处理流程:
上述流程描述:
当建立好连接后该类负责数据的读取和发送,当有数据到来时会触发readyRead信号去执行deal_readyRead槽去接收数据当数据接收完毕后会向UI线程发送AddMessage和revcMsg信号。
当WriteMessage信号被触发时,会执行deal_write槽去写数据。
当DeleteSocket或Disconnected信号被触发时会断开连接。
TCP服务端(mythread)设计:
mythread类继承与QThread类,重写run方法。SocketHelper类用于创建套接字对象并加入到线程中。
SocketHelper类主要信号与槽设计
信号 | 描述 |
---|---|
void Create(qintptr socketDescriptor,int index); | 创建套接字对象 |
void AddList(MySocket* tcpsocket,int index); | 添加信息套接字信息 |
void RemoveList(MySocket* tcpsocket); | 移除信息套接字信息 |
槽 | 描述 |
---|---|
void CreateSocket(qintptr socketDescriptor,int index); | 创建一个socket,传入socket通信标识符,和线程编号 |
mythread类处理流程:
上述流程描述:
当有新的客户端连接进来时会触发Creat信号去创建Socket对象,当创建完毕后会发送Addlist信号,当连接断开会发送RemoveList。
报文分析类(analysis)设计:
主要信号与槽设计
信号 | 描述 |
---|---|
void analysis_over(QByteArray ba); | 回应报文 |
void wirtTablec(quint16 num, quint16 satrtaddr,QString bac); | 传输数据给主线程显示写入线圈状态 |
void wirtTabler(quint16 num, quint16 satrtaddr,quint16 bar[]); | 传输数据给主线程显示写入寄存器数据 |
槽 | 描述 |
---|---|
void recvModbusMsg(QByteArray msg,quint8 addr); | 接收报文 |
void readIniCoilTobyte(QByteArray &ba,quint16 startaddr,quint16 num); | 封装ini线圈状态to byte |
void readByteToCoilIni(QByteArray ba,quint16 startaddr,quint16 num); | 封装字节数据to ini线圈状态 |
void parse_Modbus_MB_satae(MB_satae); | 状态处理 |
void parse_Modbus_True_Msg(QByteArray msg); | 正常帧处理 |
void parse_Modbus_Exception_Handling03(); void parse_Modbus_Exception_Handling02(); void parse_Modbus_Exception_Handling01(); | 异常处理 |
MB_satae parse_Modbus_Msg(QByteArray msg); | 解析报文查询状态 |
void func_01(); void func_03(); void func_0f(); void func_10(); | 功能码处理函数 |
报文分析类处理流程:
上述流程描述:
当数据解析线程接收到UI线程的Start信号后,数据解析线程会执行void recvModbusMsg(QByteArray msg,quint8 addr)槽函数接收数据,recvModbusMsg槽函数会调用parse_Modbus_MB_satae进行数据的解析给出报文状态。
1.MB_SLAVE_STATE_PACKET_OTHER 状态:不做响应
Modbus正常报文须满足小于259字节,大于12个字节,协议标识是否满足条件,当接收到的报文不满足这个条件是会返回
MB_SLAVE_STATE_PACKET_OTHER状态。
2.MB_SLAVE_STATE__ADDR_ERROR状态:从机地址异常。
当发送的报文不是给本机时返回
MB_SLAVE_STATE__ADDR_ERROR
3.MB_SLAVE_STATE_DATA_ERROR状态:数据范围异常
Modbus正常报文须满足小于259字节,大于12个字节,读线圈数量需满足小于等于2000,写线圈需满足小于等于1968,读寄存器需满足小于125,写寄存器需满足小于123。如果条件不满足返回
MB_SLAVE_STATE_DATA_ERROR状态。
4.MB_SLAVE_STATE_DATAADDR_ERROR状态:数据地址异常
Modbus地址范围0~65535,当数量OK且数量+起始地址OK。如果不满足返回
MB_SLAVE_STATE_DATAADDR_ERROR状态。
5.MB_SLAVE_STATE_FUNCTION_ERROR状态:功能码错误。
当报文里不是允许的功能码返回该状态。
6.MB_SLAVE_STATE_PACKET_PROCESS状态:一切正常。
当报文没有问题返回该状态。
处理完毕后调用parse_Modbus_MB_satae对状态进行处理,根据状态去执行对应的槽,执行完毕后会向UI线程发送analysis_over信号。
开启一个定时器,并定时两分钟中,当定时时间到了就会执行对应的槽去获取界面通信历史信息,并将信息写入到TXT文件中。
开启一个定时器,并定时1秒中,当定时时间到了就会执行对应的槽去获取系统时间,并更新系统时间。
报文封装类(modbusmsg)设计:
主要信号与槽设计
信号 | 描述 |
---|---|
void package_over(QByteArray package_msg); | 报文封装完成 |
void showMsgtoUi(QString); | 显示日志信息到ui线程 |
槽 | 描述 |
---|---|
void packageSartc(quint8,quint8,quint16,QList,QByteArray ba,quint16 cnums); | 主线程传入数据开始处理100f功能报文 |
void packageSartr(quint8 addr,quint8 funcode,quint16 startaddr,quint16 numreg); | 主线程传入数据开始处理0103功能报文 |
void funCode01(quint8 addr,quint16 startaddr,quint16 numreg); void funCode03(quint8 addr,quint16 startaddr,quint16 numreg); void funCode0f(quint8 addr,quint16 startaddr,QList,QByteArray ba,quint16 cnums); void funCode10(quint8 addr,quint16 startaddr,QList); | 报文封装函数 |
报文封装类处理流程:
当用户配置好数据信息后点击发送按钮后,会发送信号给数据封装线程。
当数据封装线程接收到UI线程的Start信号后,会进行报文的封装,封装完毕后会发送package_over信号给主线程,主线程发送信号给串口通信线程去发送数据。
当用户点击查看按钮时
1.判断有无文件路径
2.如果有文件路径则进入显示历史消息函数进行显示
3.如果没有文件路径先弹出对话框进行选择路径
4.如果选择路径为空则提示打开失败
5.如果路径合法则提示成功,并进入显示历史消息函数进行显示
历史信息显示处理流程:
系统时间显示处理流程:
umreg); void funCode0f(quint8 addr,quint16 startaddr,QList,QByteArray ba,quint16 cnums); void funCode10(quint8 addr,quint16 startaddr,QList); | 报文封装函数 |
报文封装类处理流程:
当用户配置好数据信息后点击发送按钮后,会发送信号给数据封装线程。
当数据封装线程接收到UI线程的Start信号后,会进行报文的封装,封装完毕后会发送package_over信号给主线程,主线程发送信号给串口通信线程去发送数据。
当用户点击查看按钮时
1.判断有无文件路径
2.如果有文件路径则进入显示历史消息函数进行显示
3.如果没有文件路径先弹出对话框进行选择路径
4.如果选择路径为空则提示打开失败
5.如果路径合法则提示成功,并进入显示历史消息函数进行显示
历史信息显示处理流程:
[外链图片转存中…(img-U0iuJrR3-1687692972775)]
系统时间显示处理流程:
[外链图片转存中…(img-FZM8bRyY-1687692972775)]
开启一个定时器,并定时1秒中,当定时时间到了就会执行对应的槽去获取系统时间,并更新系统时间。