第三代软件开发-485通信
[toc]
关键字: Qt
、Qml
、QSerialPort
、QSerialPort
、QThread
项目介绍
欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。
在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。
在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。
无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!
重要说明☝
☀该专栏在第三代软开发更新完将涨价
485通信
RS-485 简介
因为咱们项目中有多个设备,所以232无法满足需求,因此使用了485通信,这里不是我的端口不够,而是设备希望的连接是的线越细越好。所以选择了485,这里其实也可以选择CAN,但是485 更简单,是不是。嘿嘿嘿。
485协议,又称为RS-485或EIA-485协议,是一种用于串行通信的标准协议。它是一个基于电气特性的通信标准,定义了电气传输信号、数据格式和通信速率等相关要素,用于在多个设备间实现可靠的长距离数据传输。
485协议可以支持多个设备通过一条共享的双绞线或屏蔽双绞线进行通信,其中一个设备充当主设备(通常是主控制器),其他设备则为从设备。在这种协议下,可以实现多个从设备与主设备双向通信。
485协议的特点包括:
- 长距离传输:485支持的最大传输距离可以达到1200米,能够满足各种远距离通信需求。
- 多设备通信:可以连接多个从设备,并实现与主设备的双向通信。
- 传输速率灵活:支持多种传输速率,常见的有传输速率为9600bps、19200bps、38400bps等。
- 高抗干扰性:485协议在信号传输过程中较好地抵抗干扰,能够适应工业环境中的较高噪音情况。
差分信号传输:485协议使用差分信号传输方式,可以降低信号传输的抗干扰性。
485协议通常应用于工业自动化领域,例如楼宇自控系统、工业控制系统、安防监控系统等。它能够实现设备之间的可靠通信,提高系统的稳定性和可扩展性。
RS-232 简介
RS-232(Recommended Standard 232)是一种用于串行通信的电气接口标准。它最初由美国电子工业协会(EIA)在1962年发布,用于连接计算机和外部设备。RS-232协议定义了数据通信的格式和信号电平等方面的规范,它为设备之间的可靠通信提供了一种标准化的方式。
RS-232协议使用一对称为发送线(TX)和接收线(RX)的信号线进行通信。它使用了一种异步通信协议,其中的数据是按照字节为单位逐个发送的。数据传输是基于起始位、数据位、校验位和停止位等序列完成的。
RS-232协议规定了信号电平的定义,其中逻辑“0”是通过负电平表示,而逻辑“1”则是通过正电平表示。典型的RS-232电平范围是-3V至+3V,其中较高的电平表示逻辑“0”,而较低的电平则表示逻辑“1”。
在RS-232中,数据总线的通信速率(波特率)可以根据特定应用的要求进行配置。常见的波特率包括9600、19200、38400等。此外,RS-232还允许使用硬件握手信号(如RTS、CTS、DTR和DSR)来控制数据流的传输。
尽管RS-232协议广泛用于过去的计算机和外部设备之间的通信,但随着计算机技术的发展,它逐渐被更先进的通信接口(如USB、Ethernet和Wireless)所取代。然而,在某些应用领域,如工业控制系统和通信设备等,RS-232仍然被广泛使用。
RS-485 与 RS-232 区别
RS-485和RS-232是两种常见的串行通信协议,它们在以下几个方面有所区别:
- 电气特性:RS-485是一种差分信号传输标准,使用两条信号线(正负极性)传输数据,可以实现远距离通信和抗干扰能力强。而RS-232是一种单端信号传输标准,使用一条信号线(单极性)传输数据,通信距离较短,也较易受到干扰。
- 通信距离:由于RS-485使用差分信号传输,在合适的电气特性匹配下,可以实现较长的通信距离,一般可达1200米左右。而RS-232的通信距离较短,一般为15米左右。
- 点对点与多点通信:RS-485支持多点通信,可以连接多个设备组成网络,其中一个设备为主设备(发送者),其余设备为从设备(接收者),通过主从通信实现数据传输。而RS-232是点对点通信,只能连接两个设备。
- 速度和扩展性:RS-485的通信速度相对较快,可达几百kbps至几Mbps,且可通过分配多个从设备地址来扩展网络规模。而RS-232的通信速度较低,一般为几十kbps。
综上所述,RS-485比RS-232具有更远的通信距离、更高的通信速度和更好的扩展性,适用于需要长距离、高速和多设备通信的场景。而RS-232适用于通信距离较短、速度要求不高且只需点对点通信的场景。
Qt 中使用485
这里其实在上位机使用来看,没有任何区别,从代码来看,完全看不出来是232 害死 485,我们这里区分就是在BISO修改一下端口的模式就可以了。下面看下代码
/**
* @brief XXXX::initSerialPort
* 初始化串口
*/
void XXXX::initSerialPort()
{
// 重置参数定时器
m_ResetValueTimer = new QTimer;
connect(m_ResetValueTimer,&QTimer::timeout,this,[=](){
setOutputValue(0);
});
// 自动连接定时器
m_AutoConnectTimer = new QTimer;
connect(m_AutoConnectTimer,&QTimer::timeout,this,[=](){
openSeriaPort();
});
connect(this,&XXXX::connectedChanged,this,[=](){
if(!m_connected)
{
m_heartBeatTimer->stop();
m_AutoConnectTimer->start(m_autoConnectDuration);
}
else
m_AutoConnectTimer->stop();
});
// 心跳定时器
m_heartBeatTimer = new QTimer;
m_heartBeatTimer->setTimerType(Qt::PreciseTimer);
connect(m_heartBeatTimer,&QTimer::timeout,this,[=](){
if(m_heartBeatSendFlag)
{
// sendToHandle(CommandHandel::heartBeatHandel);
sendToInterfaceBox(CommandInterfaceBox::heartBeatInterfaceBox);
// sendToInterfaceBox(CommandInterfaceBox::laserClicked);
}
else
{
sendToHandle(CommandHandel::heartBeatHandel);
// sendToInterfaceBox(CommandInterfaceBox::heartBeatInterfaceBox);
}
m_heartBeatSendFlag = !m_heartBeatSendFlag;
});
// 读取定时器
m_readTimer = new QTimer;
m_readTimer->setTimerType(Qt::PreciseTimer);
connect(m_readTimer,&QTimer::timeout,this,&XXXX::readOpticalHandleDate);
m_serialPort = new QSerialPort;
connect(m_serialPort,&QSerialPort::errorOccurred,this,[=](QSerialPort::SerialPortError value){
emit signal_opticalHandleState(value);
if(value > 0)
setConnected(false);});
openSeriaPort();
}
- 首先,先起了一个定时器,看我注释叫做重置参数定时器,这个是做什么的呢,我这里有一个变量A,当我从缓冲器读取到数据,解析后,会把对应的数据赋值给A,那么这个A的值在我下次赋值前就一直是保持不变的了,但是我的需求是1.5秒后需要归零,所以就有了这个定时器,这个定时器在每接收到一次数据后重新计时。这就实现了1.5秒内没有数据清零。
- 后面可以看到又起了一个定时器,这个是自动重连定时器,没错,这个定时器的原理和上面的差不多,因为咱现在的情况是基本是不存在打开485端口失败的情况的,所以这里就需要有一个定时器来检测我们的设备是否在线,同样,在接收到数据后,重置这个定时器,当到达时间后,如果没有数据,那就表示这个设备断开,这里就可以尝试重新连接,并且抛出异常
- 嘿嘿,看到又一个定时器是不是,这个就是我们的心跳定时器,我们按照一定的频率分别给每个设备发送心跳,并等待数据返回。
- 是不是又看到一个定时器,这个定时器是在发送数据后启动的,就是在数据发送多少ms后,去缓冲区读取数据。没错,我没有用readready信号,因为我的数据是边长的,我这里就偷懒处理了。
- 最后一步就是打开串口了
/**
* @brief XXXX::openSeriaPort
* @return
* 打开串口
*/
bool XXXX::openSeriaPort()
{
if(m_serialPort)
{
if(m_serialPort->isOpen())
{
m_serialPort->close();
}
m_serialPort->setPortName(m_serialPortname); //设置串口名称
if(m_serialPort->open(QIODevice::ReadWrite)) //打开串口模式为读写模式
{
m_serialPort->setBaudRate(QSerialPort::Baud115200); //设置串口波特率为115200
m_serialPort->setDataBits(QSerialPort::Data8); //设置串口数据位为8位
m_serialPort->setParity(QSerialPort::NoParity); //设置串口没有校验位
m_serialPort->setStopBits(QSerialPort::OneStop); //设置串口停止位为1位
m_serialPort->setFlowControl(QSerialPort::NoFlowControl); //设置串口流控为无
setConnected(true);
m_heartBeatTimer->start(40);
emit signal_opticalHandleState(0);
return true;
}
else
{
setConnected(false);
emit signal_opticalHandleState(1);
return false;
}
}
return false;
}
这里就没有好解释的,不管你怎么百度, Qt使用串口就这么几步,固定的。
总结一下
这里如果是普通使用或者学术没有问题,放到生产力,会遇到高频数据通信问题,这个我们可以看后面的一篇,使用第三方串口库来尝试解决这个问题。不过也不确定会不会解决,在当下的系统演示阶段是使用Qt 的串口是可以的,但是最终我们还是希望提高数据的通信频率。