042-第三代软件开发-485通信-LMLPHP

第三代软件开发-485通信


关键字: QtQmlQSerialPortQSerialPortQThread

项目介绍

重要说明☝

☀该专栏在第三代软开发更新完将涨价

485通信

RS-485 简介

因为咱们项目中有多个设备,所以232无法满足需求,因此使用了485通信,这里不是我的端口不够,而是设备希望的连接是的线越细越好。所以选择了485,这里其实也可以选择CAN,但是485 更简单,是不是。嘿嘿嘿。

RS-232 简介

RS-485 与 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();

}
  1. 首先,先起了一个定时器,看我注释叫做重置参数定时器,这个是做什么的呢,我这里有一个变量A,当我从缓冲器读取到数据,解析后,会把对应的数据赋值给A,那么这个A的值在我下次赋值前就一直是保持不变的了,但是我的需求是1.5秒后需要归零,所以就有了这个定时器,这个定时器在每接收到一次数据后重新计时。这就实现了1.5秒内没有数据清零。
  2. 后面可以看到又起了一个定时器,这个是自动重连定时器,没错,这个定时器的原理和上面的差不多,因为咱现在的情况是基本是不存在打开485端口失败的情况的,所以这里就需要有一个定时器来检测我们的设备是否在线,同样,在接收到数据后,重置这个定时器,当到达时间后,如果没有数据,那就表示这个设备断开,这里就可以尝试重新连接,并且抛出异常
  3. 嘿嘿,看到又一个定时器是不是,这个就是我们的心跳定时器,我们按照一定的频率分别给每个设备发送心跳,并等待数据返回。
  4. 是不是又看到一个定时器,这个定时器是在发送数据后启动的,就是在数据发送多少ms后,去缓冲区读取数据。没错,我没有用readready信号,因为我的数据是边长的,我这里就偷懒处理了。
  5. 最后一步就是打开串口了
/**
 * @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 的串口是可以的,但是最终我们还是希望提高数据的通信频率。


042-第三代软件开发-485通信-LMLPHP
11-02 23:22